├── README ├── error.txt ├── .gitignore ├── .env.example ├── public ├── 1.jpg └── 2.png ├── src ├── clients │ ├── encrypt │ │ ├── index.ts │ │ ├── iAdapter.ts │ │ ├── bigNumber.ts │ │ └── parse.ts │ ├── utils.ts │ ├── jito.ts │ ├── config.ts │ ├── constants.ts │ ├── LookupTableProvider.ts │ └── idl.json ├── backup │ ├── Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk │ │ ├── keypair-5jHF3i1cmqR7MySV5ueGh1uxMspXyGUzhbaGF3P1zdY.json │ │ ├── keypair-3W88b4FFjPhpmW4M2BVUCo1Koth12mJz5hPQZxpUWi1N.json │ │ ├── keypair-BrhPkmNGTKksqspzAMKbtsFqaxfKpnf9FwcXEwNbb3wh.json │ │ ├── keypair-CL9nuSs6AZZYDoUDy9efjxkiGyfHzY68icGnoibAEoJ5.json │ │ ├── keypair-ELjaEPxkiTRbSmN93bibe9x4Tsf8WxdnmLBPxwMWfbXH.json │ │ ├── keypair-Ewm4Agq3LBKvoyFBNQSPqErodbuGv3j51sg2uZKkdaDi.json │ │ ├── keypair-542yT6sACKEwaXwATAz4fk9NKNHWnKpCRVWdoau6nSDg.json │ │ ├── keypair-5cospYE7uiEbLuGdiA3iQCkryYp8j7pku8DhLiC6Sk7Y.json │ │ ├── keypair-89WmLPYvF4B1cNAiZi7XE9smU1NM6HkxMfnP9P4w4ffw.json │ │ ├── keypair-AtMgkxMFELnkxTb8BsNZKYVxT4rYBksBdW1FyLAA1xvF.json │ │ ├── keypair-BEQWvGq2ebj6jVx15suuHhynE4gCpeVSoR7v9HDKgs7L.json │ │ ├── keypair-DDvikiF41no8sQoExezHZVWy3tdjbuaBepvRTVezVdHK.json │ │ ├── keypair-EsRkBTrHjAnwaXifatxSc7mkdWvuaHVYuPaVt3i6nejx.json │ │ ├── keypair-H9YV8FdnJWwkLYhsUswybiTMawtyGmqdvfY3eqDZ3zQC.json │ │ ├── keypair-ui4o5r9ac3jXeCanZqep3qooBQDZyijoP8TN275RJLZ.json │ │ ├── keypair-2vZg72SkmQWRvFvdQLQ2jjWcR7advk7jfvL5kab2kuXQ.json │ │ ├── keypair-4uMM5k98R5cC4Dc1q9C2kxCHZyD8NxpzaSSpiANQLDjU.json │ │ ├── keypair-8UyAkupKdneJNRpTQK6Hc5BbTuJyAYGwwace2GaUMCTm.json │ │ ├── keypair-9Y6avwT5b6E6aXZY4HuBKBdq5bgWdBK5kCZfWE1TCE4J.json │ │ ├── keypair-CVxBffmx2JFh1Z6ogbW6MfjfvQtYbar67RVPf5AuZaju.json │ │ ├── keypair-FGQ6JasJR8CC7opG1FAkRrwA4bV2YimAx5recQW9MCLT.json │ │ ├── keypair-HsqMXQFWovmEmFmsc2fzeEADaUkZwmfVKSeZkcuLWsAu.json │ │ ├── keypair-6N6N1f7Gaszcipz87FjEqvr2NRbrqLYJEyVxm3oaXjtG.json │ │ └── keypair-AKGzt5uYXkcjzY7Riczkeit8XoAuZo93ttjzHvYMzSPo.json │ ├── 3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw │ │ ├── keypair-FdRfGWWrSGt2ro8rVxA9jDbM8TTkwDDw1JiLFbKJrUE5.json │ │ ├── keypair-2GQjGtWCv3FHYkEddaGFKK9K4NLFBL7a7TjtjLzq9Qdt.json │ │ ├── keypair-8paBTL47oDuZWPU63Tmb5HxWAqEgpLfmJB2EnTXWzsMW.json │ │ ├── keypair-CZUup5YjNoGmVAMXXWjATSFD7wECyacihVfRBWEPSiYZ.json │ │ ├── keypair-E9rHTpEjkpjPyLjE5fz5uQS92vt2LjagNytMFwgT5pWU.json │ │ ├── keypair-5FjSsptXoephEYm6suyJc985qtExb5fxNTQgBrVVjqin.json │ │ ├── keypair-DDznyUvtaCPigB9s4udnHMmCLgguQhTXnUqJm2qVoH8J.json │ │ └── keypair-DGvyzE3J2aAhBst6CsuUxDFKWLMPH98xuoRBHEuWahjj.json │ ├── 66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp │ │ ├── keypair-2KeS3hpbS5tLbfsZ5zEsWnsTvPVZW2maXj6jsVi8CMGB.json │ │ ├── keypair-3x8s8Ai2wAcy9mAwuF7DL5cxKsnPqTSSuZDQyxvSt7qS.json │ │ ├── keypair-3yv4ejAHHPScJFzk1To8q6nD6oKCDEf3nmuU2ddTZ2mz.json │ │ ├── keypair-4zwd2imoTm4pxL69LbQb5uWLFLpLxGbRDaztJbY7ng69.json │ │ ├── keypair-7zf4W5DNj7p34RHYJHMAFeynADDqVop8DuJiAS9fQeq.json │ │ ├── keypair-3qXeAry9nLp6QkBWrtyMatYHPTLwjziRr4msRNZqyAx1.json │ │ ├── keypair-8moqoVqq8kh34gQJFNLKqCrAM1Yph3zBJ2vC695qyz3C.json │ │ └── keypair-Hk3H87D4EZE1UbofvXiW633ioSckyoaJZnErbCG6SdhL.json │ ├── 7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m │ │ ├── keypair-2LFWC7ntswghMcZFiPJ6ZNKwr7AL1ADnDdA3PKvHhnjY.json │ │ ├── keypair-DFN6P4RVLtjPEe58NTfuT6y2u1GJ6Xszjo7xRg3FEgRE.json │ │ ├── keypair-3mNUtSBPqHeg4THK4LY73QsrWCgwkp4ccvxSNSVQw1pH.json │ │ ├── keypair-2Y31Csw315V4G9SmvZuGie5VSrm3utgjthjoHwuyFyJc.json │ │ ├── keypair-2wps8c5NFLwpXtWZsgQFxZVBhfZnN3jwU71AfncY79Cf.json │ │ ├── keypair-5Ydt3D9x2LMySb2wntFG4QAzy9GmsGsqvN5QXLoq9bWh.json │ │ ├── keypair-BmyBkjCSx15UkH6Rrb1yraopUhPuGq2DxVgYmQfm9xKR.json │ │ └── keypair-DBGHKan3xGYRMxgniyRg6ffUqNxgNdcxB9rx7NbjTCZy.json │ ├── 969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC │ │ ├── keypair-6VVhmuqsb8pD2G8kLC9kLSLSvQKrbb1SqGxz48h3zTXQ.json │ │ ├── keypair-9RgZGQj9N69GaXqYKPVyiCQkuJWX6qPWiwWZB9grWsX8.json │ │ ├── keypair-GuWwBGV4eimYLA5efaUs49DQZxpVfMZKN5QxYArrsye2.json │ │ ├── keypair-t7SpMEzKPmt49fFy2gYMcuyJ6FKpokDAoUNG8jvjVi2.json │ │ ├── keypair-8BKjheN5fRjwJCdKQZDyJNZHestn2c6wNWmNaV8Sjepa.json │ │ ├── keypair-EANQCHVTHZmcLx7j9L8GnrcDCpADGnyxSvB74aygq82R.json │ │ ├── keypair-5cNfs8Ycp73soMCpjMGtP1xS3My6sb5nNG5ws2cXtVHg.json │ │ └── keypair-BMQ5JKCxBDDdNyjdqipD4Yq8hX14VSZAgNu9LiKv9Wu6.json │ ├── GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi │ │ ├── keypair-CZKDEsirHRYGhBXvSdKRzhPa62Y5eaHdup7v8AS9VgU8.json │ │ ├── keypair-Hho9Yb1RGh8shcpHDgTWBKH572w3apf5kUHa2R9RgU2U.json │ │ ├── keypair-5MjAngSteRBRcMt9BthcHbbWAVbtRtCMqTnTmFH5MAdh.json │ │ ├── keypair-8guKA7nJkPNWPgLHUPGpXtoyDyuCQrLVoBMa4EV8Jp7N.json │ │ ├── keypair-GWfQZZ3mKYBeez5k4gmVDA4sS49jrB3LGP61LkRKM1ES.json │ │ ├── keypair-4BbUo7BxL7MLMHMfyCXZdmDYZbXcEEP26GfJv7bqpQi9.json │ │ ├── keypair-AFJQJP21o6QEx4hhGihFMFbWNQJxUSt1kBCCUBqxswDL.json │ │ └── keypair-DqNSFmGRXvatB9ayaQY1HgH9ExDnaE8DH9erjR8o5xsp.json │ ├── 9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw │ │ ├── keypair-3rjrLWfKmmCx7Uw5zqS1XK8WwJhBDgQCXkhwESX9ujgZ.json │ │ ├── keypair-4i2t9PBorktWs1jsnqsL8gt7Bp3DqGEi9ujGpi43HVXo.json │ │ ├── keypair-8Eu1cJow7e5V5qJrsunx9pjHw25uvjJEn73suHjXxsN.json │ │ ├── keypair-98jPdyhRbVLZKKyqDG7Yfzi3a7AkqRAvUgc3wSNrqvmg.json │ │ ├── keypair-AX7EiLHcjqfCMCKAdQetvJWRncGZQvw8PzJGgr4noQja.json │ │ ├── keypair-F7VXepkAJxqFBMNHfnfy1U2yNZwuDkbMjH8NQchXvB8o.json │ │ ├── keypair-Ff5GsQrFEuxwrWWEAHqd472zPSngnJydoz8AMrCvA1NX.json │ │ └── keypair-44r9UXFtWpSqVNgbwJLGpB2aHmgpvyrYNJ3QDBwfEKp3.json │ ├── A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb │ │ ├── keypair-3SxRY5hGsUr4EpvjmVWLUnabAAyNm5dPncZkaTQhohxS.json │ │ ├── keypair-8D2JZ3ugupQ1fGJjJPjVewoNz68py6CjavjTEbACFyU1.json │ │ ├── keypair-G4zxCcuyTCEfU5qhpyBpKVFMXSwo89YmGXijaVHGLsn6.json │ │ ├── keypair-H8z1LeuEDyQq4N1xTB7r1BERQFxAGLXWXSjx6ZnYRNUM.json │ │ ├── keypair-2YgAtmyaeyU4bn5jPsN8oRgebqLt6SaEK7wWdJLHf7dt.json │ │ ├── keypair-3Jh5AiDUBtMjS5abCQPdMhs7GcjvTiDTNPppTu9TMLQH.json │ │ ├── keypair-GuMj4x4uziWjq7K3tXkF61yAthys2prXKf47NdwUWvJk.json │ │ └── keypair-8FhKRq7TZU9MCDkZpu5fPrBBRGpVzBg9CcLaCFkxhDsh.json │ └── BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU │ │ ├── keypair-3iHoxa8da7PQffWqymNpDLdhZVVWGULSZzzCdWXRewXy.json │ │ ├── keypair-5PaT69XwcfWeYibGBebufsLn6xyhK4posRxHSPLTmsJL.json │ │ ├── keypair-A3nNcD4E8pLbLToxautL9vdYfoJd5c9RsRcpFUw3hxVo.json │ │ ├── keypair-G4AhEJfpzvnFHw8FjhAMcyxdN2UtxdQoW2kLvM6ddEyG.json │ │ ├── keypair-K8eKgYmpWuJTjcwN9wyzTbwDo41SmsXr94kTamBQUoF.json │ │ ├── keypair-h1YZcXxgiX5C9AKxUH4tcZBfm7Pgrcvr9b52P8gSjTA.json │ │ ├── keypair-9GKidWqxnA37Fg45YEh1r2yno8XNX6jJfr8knc7rfEtf.json │ │ └── keypair-9iHvz5SfLrmCKWwuGVNVn9EcVHmcW461f4bT8Ur53roa.json ├── keyInfo.json ├── bonkfunSDK │ └── index.ts ├── retrieve.ts ├── utils.ts └── bot.ts ├── tsconfig.json ├── errorlog.txt ├── package.json ├── config.ts ├── README.md └── main.ts /README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /error.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | RPC= 2 | SECRET_KEY= 3 | API_KEY=XXXX-FFFFF 4 | DEBUG=true -------------------------------------------------------------------------------- /public/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m4rcu5o/Solana-bonkfun-bundler/HEAD/public/1.jpg -------------------------------------------------------------------------------- /public/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m4rcu5o/Solana-bonkfun-bundler/HEAD/public/2.png -------------------------------------------------------------------------------- /src/clients/encrypt/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bigNumber"; 2 | export * from "./iAdapter"; 3 | export * from "./parse"; -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-5jHF3i1cmqR7MySV5ueGh1uxMspXyGUzhbaGF3P1zdY.json: -------------------------------------------------------------------------------- 1 | [209,151,229,203,39,21,138,172,100,217,152,56,157,22,163,30,123,41,31,13,81,194,64,70,199,169,131,29,154,144,18,43,1,54,33,34,37,137,3,4,199,6,102,7,193,8,238,127,21,24,247,249,5,121,101,21,141,36,104,199,84,95,225,235] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-FdRfGWWrSGt2ro8rVxA9jDbM8TTkwDDw1JiLFbKJrUE5.json: -------------------------------------------------------------------------------- 1 | [112,3,16,209,6,153,203,57,217,185,0,178,201,36,222,120,80,174,129,70,216,213,179,93,89,252,172,86,64,86,39,45,217,88,104,180,70,120,238,47,202,234,127,43,11,44,100,87,127,212,47,236,67,104,129,91,70,40,208,90,164,248,51,58] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-2KeS3hpbS5tLbfsZ5zEsWnsTvPVZW2maXj6jsVi8CMGB.json: -------------------------------------------------------------------------------- 1 | [122,182,175,172,61,157,97,132,153,99,105,243,202,28,1,31,29,54,30,6,73,68,118,170,151,64,236,123,30,184,110,37,19,162,119,62,240,90,31,60,21,56,200,30,112,254,169,132,97,176,209,41,63,192,229,22,129,126,187,173,25,119,76,8] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-3x8s8Ai2wAcy9mAwuF7DL5cxKsnPqTSSuZDQyxvSt7qS.json: -------------------------------------------------------------------------------- 1 | [37,73,48,58,81,206,8,255,86,210,67,171,193,25,109,132,146,149,184,203,8,111,102,125,3,199,94,156,157,227,57,180,43,215,53,222,200,76,41,212,75,121,92,127,13,98,197,28,3,6,217,97,12,229,136,161,159,144,136,187,107,241,51,57] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-2LFWC7ntswghMcZFiPJ6ZNKwr7AL1ADnDdA3PKvHhnjY.json: -------------------------------------------------------------------------------- 1 | [79,122,228,68,50,107,129,74,107,145,3,42,174,89,236,74,33,240,158,94,19,3,17,236,15,189,3,118,143,50,147,39,19,202,31,9,111,63,243,86,247,52,246,43,97,235,126,38,157,197,18,143,185,101,31,34,105,115,134,240,6,208,189,215] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-DFN6P4RVLtjPEe58NTfuT6y2u1GJ6Xszjo7xRg3FEgRE.json: -------------------------------------------------------------------------------- 1 | [229,60,154,106,89,249,44,104,25,218,201,52,179,73,175,194,71,24,118,97,81,6,19,57,86,137,20,19,208,166,80,42,181,250,57,95,34,49,53,160,120,72,47,177,250,249,202,0,76,232,115,181,107,249,159,222,77,135,76,90,138,90,182,225] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-6VVhmuqsb8pD2G8kLC9kLSLSvQKrbb1SqGxz48h3zTXQ.json: -------------------------------------------------------------------------------- 1 | [29,145,73,99,209,186,153,108,107,131,89,228,7,37,62,70,168,214,79,15,231,0,45,2,154,33,38,127,229,84,86,67,81,151,38,225,119,96,166,119,72,215,137,184,180,85,21,128,123,174,203,193,200,129,53,230,11,175,93,47,1,239,16,211] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-3W88b4FFjPhpmW4M2BVUCo1Koth12mJz5hPQZxpUWi1N.json: -------------------------------------------------------------------------------- 1 | [69,112,83,46,103,0,75,112,146,13,73,89,34,247,92,248,159,243,42,100,233,238,97,173,140,67,246,157,173,127,208,95,37,45,71,184,13,209,61,117,73,139,233,70,5,109,35,243,130,14,75,72,207,232,164,48,97,87,14,231,84,189,245,49] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-BrhPkmNGTKksqspzAMKbtsFqaxfKpnf9FwcXEwNbb3wh.json: -------------------------------------------------------------------------------- 1 | [93,244,200,132,98,107,171,119,88,179,242,186,196,7,76,48,230,117,223,210,64,55,127,2,194,38,222,38,240,51,251,90,161,80,0,42,156,71,119,158,234,7,182,8,28,254,4,122,55,132,185,214,119,49,100,149,203,83,9,39,35,187,208,60] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-CL9nuSs6AZZYDoUDy9efjxkiGyfHzY68icGnoibAEoJ5.json: -------------------------------------------------------------------------------- 1 | [86,164,164,176,37,193,88,148,96,221,239,13,72,12,195,177,184,75,201,10,65,174,93,81,29,49,156,184,150,222,36,209,168,88,136,55,0,22,3,80,202,145,191,83,69,201,88,21,35,77,41,86,208,237,191,98,144,30,147,99,108,167,35,110] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-ELjaEPxkiTRbSmN93bibe9x4Tsf8WxdnmLBPxwMWfbXH.json: -------------------------------------------------------------------------------- 1 | [8,1,195,154,104,177,242,121,59,164,26,196,176,60,195,71,151,114,94,115,37,48,188,85,117,240,144,245,52,38,12,109,198,54,26,81,32,26,143,15,205,111,187,180,236,86,47,5,63,64,151,68,112,26,85,85,212,164,80,79,114,113,155,228] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-Ewm4Agq3LBKvoyFBNQSPqErodbuGv3j51sg2uZKkdaDi.json: -------------------------------------------------------------------------------- 1 | [156,198,143,175,224,95,96,26,45,159,154,136,195,137,246,16,171,59,247,104,173,87,175,26,114,59,157,211,175,7,252,48,207,47,27,63,29,37,121,153,18,33,115,5,168,53,63,210,88,64,244,161,89,19,85,251,136,74,208,143,189,6,226,21] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-CZKDEsirHRYGhBXvSdKRzhPa62Y5eaHdup7v8AS9VgU8.json: -------------------------------------------------------------------------------- 1 | [76,89,111,173,91,252,224,201,17,97,7,135,96,41,111,43,52,211,86,248,7,176,196,32,195,13,79,219,52,61,14,206,171,183,187,188,166,112,170,212,190,57,24,77,21,76,87,213,212,63,4,11,108,255,185,40,103,157,16,36,61,77,118,225] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-Hho9Yb1RGh8shcpHDgTWBKH572w3apf5kUHa2R9RgU2U.json: -------------------------------------------------------------------------------- 1 | [3,63,80,164,27,230,219,82,225,235,189,215,6,5,41,221,230,189,132,161,231,163,240,241,95,190,94,2,35,91,168,240,248,46,102,241,192,98,22,0,197,40,243,166,109,42,215,176,36,129,137,43,16,144,111,100,61,115,237,108,87,0,75,57] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-2GQjGtWCv3FHYkEddaGFKK9K4NLFBL7a7TjtjLzq9Qdt.json: -------------------------------------------------------------------------------- 1 | [33,171,223,194,84,80,167,152,160,138,36,109,177,193,122,230,62,242,229,185,91,134,2,19,166,146,76,36,244,24,37,121,18,206,58,184,14,244,223,190,97,9,84,151,93,61,95,25,183,250,248,98,73,10,101,71,70,209,98,125,145,251,122,55] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-8paBTL47oDuZWPU63Tmb5HxWAqEgpLfmJB2EnTXWzsMW.json: -------------------------------------------------------------------------------- 1 | [146,77,168,146,208,55,65,87,3,132,112,121,27,102,87,30,99,39,12,251,213,207,144,218,133,51,105,154,96,32,144,181,116,49,159,159,141,229,243,4,77,84,200,98,205,176,4,85,253,8,153,12,32,171,152,13,230,161,253,70,229,112,126,37] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-CZUup5YjNoGmVAMXXWjATSFD7wECyacihVfRBWEPSiYZ.json: -------------------------------------------------------------------------------- 1 | [6,8,206,77,132,6,12,160,200,141,138,223,233,214,166,91,26,168,56,121,134,54,46,17,207,202,95,126,96,210,62,44,171,194,179,92,222,64,170,100,91,161,191,198,146,123,234,100,202,81,43,165,217,19,117,94,245,57,166,142,134,149,58,146] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-E9rHTpEjkpjPyLjE5fz5uQS92vt2LjagNytMFwgT5pWU.json: -------------------------------------------------------------------------------- 1 | [41,153,90,136,135,50,186,108,92,249,254,28,243,244,60,15,61,241,179,95,25,88,217,24,34,115,53,157,80,156,231,114,195,108,77,74,209,106,131,30,31,11,103,154,154,66,152,88,147,216,117,249,41,167,240,92,63,70,118,24,165,35,150,105] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-3yv4ejAHHPScJFzk1To8q6nD6oKCDEf3nmuU2ddTZ2mz.json: -------------------------------------------------------------------------------- 1 | [233,168,103,206,1,246,87,21,180,221,126,44,112,134,164,65,141,251,38,153,236,189,110,238,117,69,38,235,85,21,225,43,44,75,229,202,64,27,56,175,192,142,66,108,10,85,30,4,91,154,25,178,87,42,42,28,130,75,216,166,15,170,160,245] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-4zwd2imoTm4pxL69LbQb5uWLFLpLxGbRDaztJbY7ng69.json: -------------------------------------------------------------------------------- 1 | [185,146,141,247,3,106,72,61,23,244,109,103,34,251,45,179,111,1,87,2,6,179,253,231,134,240,246,139,204,61,80,251,59,106,237,98,144,98,233,158,241,91,51,121,224,158,236,37,6,169,205,161,130,47,228,83,218,230,41,165,76,36,47,110] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-7zf4W5DNj7p34RHYJHMAFeynADDqVop8DuJiAS9fQeq.json: -------------------------------------------------------------------------------- 1 | [238,113,130,177,187,180,101,58,170,92,245,122,212,247,87,92,46,198,113,198,235,61,50,40,96,67,29,131,185,111,8,182,1,202,173,76,27,171,201,103,17,170,94,64,3,134,244,69,165,90,222,135,125,52,131,87,69,6,221,52,172,239,149,158] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-3mNUtSBPqHeg4THK4LY73QsrWCgwkp4ccvxSNSVQw1pH.json: -------------------------------------------------------------------------------- 1 | [52,199,203,233,5,151,66,220,219,139,243,10,64,200,46,76,136,138,46,163,178,220,80,80,19,26,201,25,170,178,131,182,41,21,55,198,213,79,132,174,24,158,138,184,68,210,39,112,176,128,116,38,236,200,13,182,61,15,38,99,122,18,156,214] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-9RgZGQj9N69GaXqYKPVyiCQkuJWX6qPWiwWZB9grWsX8.json: -------------------------------------------------------------------------------- 1 | [125,196,144,31,14,13,63,111,246,93,92,244,207,157,220,234,48,3,253,27,50,127,122,18,117,246,13,143,164,130,122,143,125,48,41,73,248,146,195,95,182,67,110,92,237,38,10,49,146,171,64,17,18,238,8,157,164,32,172,205,225,196,22,211] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-GuWwBGV4eimYLA5efaUs49DQZxpVfMZKN5QxYArrsye2.json: -------------------------------------------------------------------------------- 1 | [196,61,69,13,76,109,201,33,18,58,45,168,77,117,94,96,51,128,246,245,209,162,142,146,102,22,166,88,67,74,146,41,236,83,90,64,127,248,174,77,197,212,157,251,45,173,121,83,22,142,196,36,19,20,209,34,14,101,112,167,99,71,170,131] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-t7SpMEzKPmt49fFy2gYMcuyJ6FKpokDAoUNG8jvjVi2.json: -------------------------------------------------------------------------------- 1 | [143,8,132,231,93,150,136,250,106,103,211,95,184,6,74,154,129,128,31,199,174,203,80,22,159,171,57,71,178,182,12,63,13,23,232,165,65,35,71,181,79,173,243,9,178,90,125,54,187,73,165,243,127,61,142,236,132,176,63,32,208,7,192,155] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-3rjrLWfKmmCx7Uw5zqS1XK8WwJhBDgQCXkhwESX9ujgZ.json: -------------------------------------------------------------------------------- 1 | [111,11,110,37,158,24,8,187,193,245,37,172,243,174,83,144,202,119,127,56,57,214,202,132,119,34,17,56,170,144,73,131,42,117,72,236,91,108,206,130,177,166,31,181,95,1,21,216,137,157,137,222,129,177,76,136,15,241,68,99,115,36,40,254] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-4i2t9PBorktWs1jsnqsL8gt7Bp3DqGEi9ujGpi43HVXo.json: -------------------------------------------------------------------------------- 1 | [85,103,119,139,247,244,37,12,99,183,120,208,145,37,249,150,2,46,202,83,175,94,74,61,151,123,120,115,203,20,84,238,55,22,0,112,44,136,18,107,76,246,97,222,75,137,228,212,178,180,51,236,15,87,12,251,211,213,8,225,56,161,245,42] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-8Eu1cJow7e5V5qJrsunx9pjHw25uvjJEn73suHjXxsN.json: -------------------------------------------------------------------------------- 1 | [190,18,14,47,119,254,206,159,163,249,217,34,169,58,190,134,23,209,246,103,29,244,82,250,143,142,37,149,18,41,146,52,1,218,199,92,28,152,81,84,206,89,247,175,233,101,83,80,139,233,238,39,148,141,176,196,205,51,204,89,95,57,137,117] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-98jPdyhRbVLZKKyqDG7Yfzi3a7AkqRAvUgc3wSNrqvmg.json: -------------------------------------------------------------------------------- 1 | [245,173,39,132,112,106,254,3,58,219,34,48,6,68,15,28,55,89,80,159,129,95,228,242,121,13,218,47,22,236,214,66,120,216,125,239,235,231,123,116,72,255,232,94,206,49,166,203,134,53,1,178,27,40,1,180,239,214,89,201,164,184,247,131] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-AX7EiLHcjqfCMCKAdQetvJWRncGZQvw8PzJGgr4noQja.json: -------------------------------------------------------------------------------- 1 | [144,14,99,131,109,61,253,248,41,202,51,35,9,46,64,95,29,172,117,96,236,129,205,244,218,218,1,247,66,95,197,57,141,111,168,124,254,114,130,27,240,166,150,121,120,129,18,221,84,91,182,97,12,5,134,40,141,190,165,137,171,65,240,129] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-F7VXepkAJxqFBMNHfnfy1U2yNZwuDkbMjH8NQchXvB8o.json: -------------------------------------------------------------------------------- 1 | [1,207,35,180,199,9,60,128,111,178,165,13,108,105,45,238,144,191,95,151,100,193,223,23,79,74,199,237,226,45,75,25,209,173,91,236,239,79,16,71,114,76,119,167,183,30,40,235,157,68,236,77,27,118,189,200,6,26,111,193,31,110,31,148] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-3SxRY5hGsUr4EpvjmVWLUnabAAyNm5dPncZkaTQhohxS.json: -------------------------------------------------------------------------------- 1 | [52,25,166,118,248,205,231,207,58,237,113,214,68,230,226,36,138,35,177,221,82,17,214,34,96,73,44,128,137,188,63,187,36,93,143,164,98,213,77,113,122,19,171,131,126,99,216,233,87,229,163,159,159,224,91,16,203,28,48,2,165,117,101,63] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-8D2JZ3ugupQ1fGJjJPjVewoNz68py6CjavjTEbACFyU1.json: -------------------------------------------------------------------------------- 1 | [226,77,13,89,64,135,252,132,196,24,159,114,83,238,76,58,131,139,181,53,63,151,200,205,202,90,180,201,195,221,67,144,107,22,64,70,245,150,44,98,193,132,89,87,103,38,20,6,109,197,37,178,240,65,234,201,250,61,110,66,141,102,221,126] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-G4zxCcuyTCEfU5qhpyBpKVFMXSwo89YmGXijaVHGLsn6.json: -------------------------------------------------------------------------------- 1 | [166,221,54,9,57,76,57,226,51,96,129,92,110,16,24,129,70,5,6,191,101,148,223,252,97,139,187,142,121,204,119,126,223,229,146,146,202,99,88,73,78,235,3,52,110,105,67,186,147,183,71,96,240,94,189,194,234,121,150,206,157,11,247,167] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-H8z1LeuEDyQq4N1xTB7r1BERQFxAGLXWXSjx6ZnYRNUM.json: -------------------------------------------------------------------------------- 1 | [250,37,47,31,31,119,166,150,219,175,86,36,180,89,255,203,144,247,125,18,137,217,136,56,26,212,51,69,167,162,86,206,239,198,131,96,217,7,39,43,203,95,82,68,51,198,70,83,79,151,136,74,200,177,149,95,174,66,99,213,255,133,43,118] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-3iHoxa8da7PQffWqymNpDLdhZVVWGULSZzzCdWXRewXy.json: -------------------------------------------------------------------------------- 1 | [208,64,142,91,111,65,244,90,233,16,90,191,87,46,144,138,192,159,221,107,146,59,99,242,229,197,86,241,170,159,201,99,40,75,49,152,5,159,10,211,243,43,206,113,229,65,89,151,158,7,43,18,153,25,160,151,238,177,207,122,187,67,14,228] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-5PaT69XwcfWeYibGBebufsLn6xyhK4posRxHSPLTmsJL.json: -------------------------------------------------------------------------------- 1 | [139,213,215,130,175,18,240,34,69,172,105,235,36,252,188,84,233,241,6,89,97,243,182,145,105,4,70,212,174,193,185,232,65,55,88,234,10,189,103,116,79,154,52,26,174,180,191,52,228,169,32,218,214,208,23,83,218,167,177,63,64,82,136,85] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-A3nNcD4E8pLbLToxautL9vdYfoJd5c9RsRcpFUw3hxVo.json: -------------------------------------------------------------------------------- 1 | [54,170,204,217,154,14,171,216,124,32,65,159,161,248,219,46,219,161,125,210,217,0,154,48,37,207,231,40,7,95,55,252,134,111,165,151,149,141,65,187,202,16,74,179,238,53,49,73,51,43,158,133,221,249,162,200,86,48,1,100,186,98,162,34] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-G4AhEJfpzvnFHw8FjhAMcyxdN2UtxdQoW2kLvM6ddEyG.json: -------------------------------------------------------------------------------- 1 | [90,126,161,155,70,248,226,84,189,175,46,165,18,124,59,88,44,250,53,183,68,26,35,9,187,212,70,150,115,240,153,188,223,175,1,197,172,3,124,157,83,52,184,227,87,29,35,58,4,247,108,161,171,152,219,31,115,67,208,112,119,141,238,19] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-K8eKgYmpWuJTjcwN9wyzTbwDo41SmsXr94kTamBQUoF.json: -------------------------------------------------------------------------------- 1 | [204,134,197,29,163,86,125,125,218,132,159,117,92,98,220,56,17,194,190,176,81,61,32,65,124,42,22,168,104,235,188,35,4,165,24,218,40,119,13,188,39,165,182,55,53,190,202,155,175,164,130,28,107,28,249,156,110,89,106,255,142,245,1,62] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-h1YZcXxgiX5C9AKxUH4tcZBfm7Pgrcvr9b52P8gSjTA.json: -------------------------------------------------------------------------------- 1 | [114,234,216,101,58,243,199,231,161,65,116,114,133,119,95,125,57,175,242,41,240,32,219,69,172,56,203,141,172,116,39,47,10,63,217,0,168,192,173,17,206,55,64,8,153,249,9,150,19,110,92,174,231,171,191,107,1,75,245,141,153,160,212,141] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-542yT6sACKEwaXwATAz4fk9NKNHWnKpCRVWdoau6nSDg.json: -------------------------------------------------------------------------------- 1 | [27,191,106,25,116,95,124,53,228,104,49,180,132,217,202,137,209,183,9,45,188,82,105,241,217,240,188,81,148,88,122,227,60,53,184,168,162,34,139,95,61,125,151,16,27,0,131,96,34,26,76,76,73,219,181,16,91,81,118,145,151,165,81,123] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-5cospYE7uiEbLuGdiA3iQCkryYp8j7pku8DhLiC6Sk7Y.json: -------------------------------------------------------------------------------- 1 | [34,245,0,125,251,90,112,29,84,51,143,240,103,103,33,53,133,63,19,99,195,132,72,193,198,110,234,231,251,215,240,21,68,155,20,64,173,44,161,174,141,96,96,74,101,140,148,84,160,232,50,26,252,129,119,59,249,120,98,49,114,220,39,95] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-89WmLPYvF4B1cNAiZi7XE9smU1NM6HkxMfnP9P4w4ffw.json: -------------------------------------------------------------------------------- 1 | [33,44,72,163,38,54,241,227,219,240,180,45,237,158,93,160,218,235,110,169,90,106,30,166,166,79,11,189,180,105,33,6,106,48,28,18,67,174,135,132,189,102,189,134,80,12,40,47,7,70,172,32,184,75,167,188,74,119,36,131,181,163,58,98] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-AtMgkxMFELnkxTb8BsNZKYVxT4rYBksBdW1FyLAA1xvF.json: -------------------------------------------------------------------------------- 1 | [149,241,45,73,92,165,87,203,73,45,77,233,94,199,1,158,36,209,190,117,22,1,253,184,183,7,139,97,246,52,211,105,146,225,49,87,216,76,211,133,125,124,251,45,50,162,96,23,184,226,190,152,13,81,97,210,148,116,11,67,187,102,155,188] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-BEQWvGq2ebj6jVx15suuHhynE4gCpeVSoR7v9HDKgs7L.json: -------------------------------------------------------------------------------- 1 | [195,88,66,122,166,62,229,177,62,5,202,100,22,203,88,207,75,190,96,236,205,121,95,253,83,120,185,17,226,36,150,121,152,4,2,92,99,99,133,12,75,239,141,167,157,136,198,71,31,38,198,164,37,183,59,132,135,217,149,172,61,123,166,47] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-DDvikiF41no8sQoExezHZVWy3tdjbuaBepvRTVezVdHK.json: -------------------------------------------------------------------------------- 1 | [45,105,4,53,1,237,50,0,128,31,50,134,166,58,32,197,62,43,177,58,238,23,127,234,143,200,181,203,236,57,196,34,181,155,244,63,209,49,219,69,69,185,223,249,177,95,213,29,9,225,3,224,169,176,145,220,249,37,123,157,90,172,127,210] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-EsRkBTrHjAnwaXifatxSc7mkdWvuaHVYuPaVt3i6nejx.json: -------------------------------------------------------------------------------- 1 | [154,101,196,112,1,123,102,133,230,62,0,181,176,227,45,156,111,40,87,66,195,195,126,232,235,203,250,212,48,8,167,186,206,18,242,253,116,18,17,116,118,95,172,17,109,43,96,125,216,32,207,143,79,21,50,165,148,140,17,43,7,31,162,231] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-H9YV8FdnJWwkLYhsUswybiTMawtyGmqdvfY3eqDZ3zQC.json: -------------------------------------------------------------------------------- 1 | [37,131,82,213,35,9,39,58,26,66,44,144,217,13,42,7,28,121,161,29,231,65,94,15,228,164,53,155,188,150,242,41,239,235,60,198,72,20,252,119,49,20,185,252,201,159,226,192,181,245,140,246,159,112,166,20,22,251,36,243,157,49,68,149] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-ui4o5r9ac3jXeCanZqep3qooBQDZyijoP8TN275RJLZ.json: -------------------------------------------------------------------------------- 1 | [164,154,199,216,93,203,173,139,81,9,97,228,232,44,50,247,219,197,25,71,125,191,9,99,50,157,236,13,164,186,97,175,13,128,162,136,104,116,138,229,39,62,27,110,65,236,82,28,58,54,186,208,154,199,79,230,151,25,90,254,238,46,168,82] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-5MjAngSteRBRcMt9BthcHbbWAVbtRtCMqTnTmFH5MAdh.json: -------------------------------------------------------------------------------- 1 | [252,218,128,129,26,108,213,49,101,231,53,227,220,234,134,6,132,168,207,245,98,249,54,37,35,219,63,194,41,134,42,206,64,190,11,83,185,17,96,66,193,146,234,90,108,92,190,206,88,57,148,164,76,37,137,28,140,1,69,54,175,190,81,116] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-8guKA7nJkPNWPgLHUPGpXtoyDyuCQrLVoBMa4EV8Jp7N.json: -------------------------------------------------------------------------------- 1 | [216,78,9,246,180,75,29,13,175,210,110,215,94,12,141,142,37,108,45,221,49,27,113,148,93,187,248,220,129,143,217,111,114,58,156,80,42,66,15,240,95,57,233,108,68,148,30,213,250,1,225,195,248,105,153,152,111,34,175,97,20,246,210,101] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-GWfQZZ3mKYBeez5k4gmVDA4sS49jrB3LGP61LkRKM1ES.json: -------------------------------------------------------------------------------- 1 | [215,82,139,210,224,86,64,88,255,208,179,81,30,117,60,32,22,51,194,246,111,212,132,62,42,17,160,19,14,46,183,23,230,120,146,203,157,155,47,111,220,253,6,207,10,101,28,157,212,157,29,157,61,206,229,94,241,198,201,176,150,20,22,139] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-5FjSsptXoephEYm6suyJc985qtExb5fxNTQgBrVVjqin.json: -------------------------------------------------------------------------------- 1 | [45,179,53,125,105,48,134,71,40,174,217,64,111,219,72,115,180,162,246,65,7,232,101,162,241,101,233,195,208,125,141,74,63,52,223,127,133,83,74,171,113,250,131,197,205,245,193,246,50,86,244,128,98,34,39,63,203,68,39,107,144,239,238,71] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-DDznyUvtaCPigB9s4udnHMmCLgguQhTXnUqJm2qVoH8J.json: -------------------------------------------------------------------------------- 1 | [150,129,67,166,198,223,42,149,161,199,39,216,177,25,35,1,126,209,73,43,235,165,26,222,98,202,241,199,19,53,111,32,181,160,143,38,193,238,36,124,123,244,210,238,10,141,223,21,43,45,154,223,240,228,76,101,239,221,153,246,240,85,188,23] -------------------------------------------------------------------------------- /src/backup/3Ee8gNdVmdfSKa5Tc9Ac1Qj5NRffHAn5kSyTSvjS6xQw/keypair-DGvyzE3J2aAhBst6CsuUxDFKWLMPH98xuoRBHEuWahjj.json: -------------------------------------------------------------------------------- 1 | [170,105,185,12,242,157,193,115,249,59,150,102,144,185,58,47,48,226,66,162,14,76,92,188,54,144,22,92,99,40,123,203,182,96,254,85,118,160,150,82,104,195,9,73,145,242,237,203,151,228,110,136,198,198,0,220,163,201,153,78,91,206,145,6] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-3qXeAry9nLp6QkBWrtyMatYHPTLwjziRr4msRNZqyAx1.json: -------------------------------------------------------------------------------- 1 | [62,222,7,127,117,18,159,13,90,19,48,238,54,254,130,75,61,86,208,215,64,171,81,36,39,183,203,252,201,250,202,104,42,37,229,254,252,36,46,22,235,154,169,169,193,196,10,239,39,128,16,132,192,127,239,218,123,189,189,98,181,222,223,186] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-8moqoVqq8kh34gQJFNLKqCrAM1Yph3zBJ2vC695qyz3C.json: -------------------------------------------------------------------------------- 1 | [141,150,81,181,40,131,255,67,101,23,13,150,87,170,124,242,231,174,151,69,4,199,57,69,251,145,234,182,198,205,179,137,115,124,83,236,219,101,236,74,205,244,157,74,0,206,109,240,88,223,173,4,170,129,95,241,36,45,171,69,237,211,175,67] -------------------------------------------------------------------------------- /src/backup/66fogs38SqJHcXUAWK6Sb164qiXegBwUpfXbZs5N7gbp/keypair-Hk3H87D4EZE1UbofvXiW633ioSckyoaJZnErbCG6SdhL.json: -------------------------------------------------------------------------------- 1 | [109,202,154,31,171,150,110,168,85,168,157,201,26,234,79,18,208,138,138,14,174,148,42,84,160,152,0,30,236,233,46,13,248,193,138,148,89,49,49,100,243,41,22,164,136,149,35,3,40,229,59,65,251,202,136,213,54,227,130,227,254,248,38,139] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-2Y31Csw315V4G9SmvZuGie5VSrm3utgjthjoHwuyFyJc.json: -------------------------------------------------------------------------------- 1 | [227,175,227,127,234,98,82,246,60,241,217,230,145,163,242,71,65,39,1,174,86,61,60,104,128,29,209,203,199,36,163,118,22,206,245,24,165,238,216,46,24,156,22,105,119,207,103,245,15,169,120,45,168,166,254,151,168,126,248,213,91,158,85,141] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-8BKjheN5fRjwJCdKQZDyJNZHestn2c6wNWmNaV8Sjepa.json: -------------------------------------------------------------------------------- 1 | [173,63,6,28,123,43,232,6,242,99,79,97,21,66,110,190,183,173,130,164,205,2,202,145,187,170,113,4,166,118,152,112,106,166,205,59,87,195,236,99,255,124,187,89,32,95,226,50,111,146,61,211,190,193,171,228,124,162,117,180,168,22,75,251] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-EANQCHVTHZmcLx7j9L8GnrcDCpADGnyxSvB74aygq82R.json: -------------------------------------------------------------------------------- 1 | [121,166,113,119,240,130,168,212,248,88,205,37,214,160,223,143,74,27,215,222,97,104,175,139,23,253,36,215,199,163,185,82,195,142,90,177,201,24,48,0,15,164,119,56,116,51,252,20,27,178,73,171,3,195,143,146,200,117,70,105,252,74,223,254] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-Ff5GsQrFEuxwrWWEAHqd472zPSngnJydoz8AMrCvA1NX.json: -------------------------------------------------------------------------------- 1 | [246,13,251,179,75,92,66,211,200,122,118,29,241,253,6,158,173,145,167,211,198,36,230,142,152,223,169,199,111,88,14,234,217,196,133,23,226,109,15,37,104,211,25,30,74,84,221,15,246,64,152,0,192,251,88,127,123,247,225,118,254,153,73,184] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-2YgAtmyaeyU4bn5jPsN8oRgebqLt6SaEK7wWdJLHf7dt.json: -------------------------------------------------------------------------------- 1 | [139,245,137,227,16,119,12,189,100,50,251,190,197,90,236,254,11,121,217,5,168,46,176,209,119,77,199,109,88,247,111,233,22,248,251,120,86,166,68,172,21,250,169,162,33,73,44,168,90,31,105,237,254,66,38,5,89,196,103,110,128,253,154,67] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-3Jh5AiDUBtMjS5abCQPdMhs7GcjvTiDTNPppTu9TMLQH.json: -------------------------------------------------------------------------------- 1 | [26,253,126,153,164,177,11,53,105,233,194,187,120,204,155,160,83,124,207,104,217,208,217,65,229,3,50,85,211,84,216,105,34,63,142,151,51,121,70,180,61,79,59,220,70,196,78,64,175,255,25,83,181,115,193,67,95,252,136,71,81,194,149,178] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-GuMj4x4uziWjq7K3tXkF61yAthys2prXKf47NdwUWvJk.json: -------------------------------------------------------------------------------- 1 | [165,237,124,135,112,187,186,41,201,179,107,47,16,208,16,246,116,62,169,51,105,199,45,116,140,110,86,112,36,242,45,214,236,72,240,173,207,101,132,64,103,99,24,128,202,176,94,136,43,101,228,211,90,255,48,115,75,139,34,61,107,198,28,241] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-9GKidWqxnA37Fg45YEh1r2yno8XNX6jJfr8knc7rfEtf.json: -------------------------------------------------------------------------------- 1 | [38,205,167,229,179,0,231,150,114,49,78,58,175,156,181,79,131,76,104,75,249,243,151,212,46,17,159,177,208,180,161,88,122,202,95,44,174,125,24,237,197,47,20,55,193,114,129,255,222,80,119,160,187,99,159,153,69,233,52,201,31,21,178,136] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-2vZg72SkmQWRvFvdQLQ2jjWcR7advk7jfvL5kab2kuXQ.json: -------------------------------------------------------------------------------- 1 | [139,189,101,85,91,112,150,231,44,130,20,38,242,148,209,227,115,41,136,234,138,173,33,210,138,249,180,43,35,235,76,195,28,148,106,38,102,208,148,162,202,147,251,93,121,104,123,7,2,85,64,220,45,74,55,111,124,13,199,238,210,138,42,251] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-4uMM5k98R5cC4Dc1q9C2kxCHZyD8NxpzaSSpiANQLDjU.json: -------------------------------------------------------------------------------- 1 | [37,177,99,33,144,213,22,3,95,65,212,83,139,235,227,221,102,39,186,19,137,219,143,199,249,148,216,157,22,47,144,141,57,252,68,182,221,237,216,110,38,118,158,8,220,34,191,44,246,154,221,236,167,225,165,61,174,77,198,139,170,239,166,151] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-8UyAkupKdneJNRpTQK6Hc5BbTuJyAYGwwace2GaUMCTm.json: -------------------------------------------------------------------------------- 1 | [192,241,94,116,59,79,243,210,183,145,220,20,226,224,179,237,149,31,48,190,36,175,83,238,220,235,160,138,237,127,199,45,111,43,255,252,93,179,147,209,91,111,189,73,5,18,243,98,100,186,203,73,160,138,112,2,138,19,42,155,192,5,187,76] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-9Y6avwT5b6E6aXZY4HuBKBdq5bgWdBK5kCZfWE1TCE4J.json: -------------------------------------------------------------------------------- 1 | [20,211,5,186,8,191,31,170,149,174,213,178,173,95,141,83,203,62,159,69,166,238,79,195,247,223,140,206,116,241,186,133,126,212,208,194,187,81,7,186,3,179,112,46,142,148,235,149,182,45,235,12,16,52,123,230,152,19,20,184,201,86,42,171] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-CVxBffmx2JFh1Z6ogbW6MfjfvQtYbar67RVPf5AuZaju.json: -------------------------------------------------------------------------------- 1 | [35,136,220,6,196,55,49,192,200,253,117,181,13,51,112,238,165,126,57,153,233,183,237,60,62,214,190,40,213,172,116,118,170,219,55,42,62,178,248,177,88,87,146,49,33,143,38,224,139,0,181,68,42,83,238,123,90,211,127,246,169,119,160,60] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-FGQ6JasJR8CC7opG1FAkRrwA4bV2YimAx5recQW9MCLT.json: -------------------------------------------------------------------------------- 1 | [150,81,173,79,195,24,144,184,7,172,62,198,179,1,214,253,17,158,10,23,109,45,188,196,198,103,23,211,134,163,112,218,211,245,112,76,218,172,33,198,33,198,217,146,151,227,25,59,210,136,40,233,209,60,71,121,90,186,7,225,212,5,241,244] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-HsqMXQFWovmEmFmsc2fzeEADaUkZwmfVKSeZkcuLWsAu.json: -------------------------------------------------------------------------------- 1 | [155,167,174,72,146,57,228,89,215,248,21,220,71,171,90,233,3,162,73,20,170,237,228,97,43,207,245,242,118,63,249,247,250,192,180,133,169,97,34,8,243,218,46,151,170,213,174,106,242,4,116,197,120,46,201,180,89,19,123,122,24,61,154,190] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-4BbUo7BxL7MLMHMfyCXZdmDYZbXcEEP26GfJv7bqpQi9.json: -------------------------------------------------------------------------------- 1 | [189,128,215,213,170,121,12,88,199,212,238,46,177,254,114,27,2,121,210,42,223,68,200,153,63,247,14,66,189,220,46,132,47,73,218,202,116,136,147,195,218,81,110,55,229,47,238,19,15,54,227,10,252,22,208,117,250,186,134,23,66,27,170,38] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-AFJQJP21o6QEx4hhGihFMFbWNQJxUSt1kBCCUBqxswDL.json: -------------------------------------------------------------------------------- 1 | [143,178,180,210,160,208,78,223,255,183,202,26,97,124,231,103,24,167,109,38,149,33,57,148,86,109,78,214,225,3,95,187,137,98,253,102,200,56,104,26,61,245,221,232,20,194,201,168,117,210,86,150,84,31,133,123,75,245,154,186,165,88,67,163] -------------------------------------------------------------------------------- /src/backup/GhsfyrFrLRRtavxt5c3aRpz4cvdbjdAi2jdhAatqSUUi/keypair-DqNSFmGRXvatB9ayaQY1HgH9ExDnaE8DH9erjR8o5xsp.json: -------------------------------------------------------------------------------- 1 | [52,93,165,229,14,55,2,22,252,77,214,140,112,9,254,151,149,92,156,245,10,179,55,126,4,46,197,193,173,75,107,86,190,176,91,235,124,33,123,42,231,165,249,237,192,204,125,40,19,213,113,161,182,118,30,252,147,74,243,176,132,250,217,31] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-2wps8c5NFLwpXtWZsgQFxZVBhfZnN3jwU71AfncY79Cf.json: -------------------------------------------------------------------------------- 1 | [252,253,91,179,169,73,100,119,218,158,245,254,187,225,67,153,110,222,73,135,23,141,185,86,134,88,35,110,78,129,193,177,28,231,43,197,195,249,86,79,162,155,109,249,222,11,161,82,252,154,227,156,59,255,234,69,225,58,86,30,81,191,243,196] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-5Ydt3D9x2LMySb2wntFG4QAzy9GmsGsqvN5QXLoq9bWh.json: -------------------------------------------------------------------------------- 1 | [127,237,150,196,33,70,94,62,184,81,12,118,63,223,189,80,248,157,213,113,78,242,182,192,47,229,200,65,159,189,69,230,67,137,115,254,68,90,103,214,231,229,168,165,247,228,183,162,59,221,230,122,132,123,93,26,225,97,83,223,207,113,153,66] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-BmyBkjCSx15UkH6Rrb1yraopUhPuGq2DxVgYmQfm9xKR.json: -------------------------------------------------------------------------------- 1 | [44,58,121,243,191,232,95,189,239,168,196,147,239,182,110,151,47,225,104,81,48,247,90,158,44,181,37,172,255,167,83,221,160,25,244,51,134,220,60,21,204,135,72,202,216,228,188,107,179,157,118,118,225,203,62,83,123,105,96,125,230,4,151,104] -------------------------------------------------------------------------------- /src/backup/7GpqE3gvoeDVMoEcMCykqGFohFDeRSeT99MPd3JFaY6m/keypair-DBGHKan3xGYRMxgniyRg6ffUqNxgNdcxB9rx7NbjTCZy.json: -------------------------------------------------------------------------------- 1 | [180,199,141,27,207,225,228,74,200,190,199,154,230,182,242,107,61,225,194,251,9,158,163,236,159,197,243,188,130,41,185,192,180,237,84,117,249,195,92,107,237,126,28,116,21,239,114,128,255,29,194,78,73,144,74,20,57,63,203,140,207,109,23,52] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-5cNfs8Ycp73soMCpjMGtP1xS3My6sb5nNG5ws2cXtVHg.json: -------------------------------------------------------------------------------- 1 | [180,206,136,233,61,200,243,224,176,184,217,183,163,38,101,193,91,65,217,62,21,39,144,254,113,40,111,30,132,232,94,60,68,126,148,21,147,58,174,90,162,85,150,154,203,129,114,211,162,204,126,107,152,158,148,179,204,225,136,206,83,168,235,175] -------------------------------------------------------------------------------- /src/backup/969f2h2jyGn3rfCY5yszAdhnoq2FXvKMZrpP7kXKQmsC/keypair-BMQ5JKCxBDDdNyjdqipD4Yq8hX14VSZAgNu9LiKv9Wu6.json: -------------------------------------------------------------------------------- 1 | [50,250,164,157,147,187,150,118,244,86,245,232,202,248,233,230,126,48,75,11,64,5,137,120,226,171,162,238,231,195,129,55,153,206,147,79,47,99,60,139,90,231,146,126,53,29,98,44,216,236,173,246,65,141,255,173,29,101,96,203,124,217,231,113] -------------------------------------------------------------------------------- /src/backup/9r8XiTr2VEPCQ9PjEf3xwChiyxyNc9srcYkrzhrcQSHw/keypair-44r9UXFtWpSqVNgbwJLGpB2aHmgpvyrYNJ3QDBwfEKp3.json: -------------------------------------------------------------------------------- 1 | [86,112,141,122,112,157,202,226,48,9,79,68,104,106,69,125,112,88,229,48,139,137,114,131,174,122,134,239,192,218,61,157,45,143,95,117,227,100,66,164,59,200,221,156,250,221,183,73,96,123,208,100,131,109,110,168,76,14,230,244,107,119,206,216] -------------------------------------------------------------------------------- /src/backup/A8bxWmJhnQYVZ342SWHHFkpTL5nqDufP9czgJtbCyWkb/keypair-8FhKRq7TZU9MCDkZpu5fPrBBRGpVzBg9CcLaCFkxhDsh.json: -------------------------------------------------------------------------------- 1 | [162,54,232,131,211,103,74,16,253,172,236,48,105,128,191,160,133,241,223,50,246,130,61,129,170,87,122,82,170,124,81,74,107,197,134,247,49,189,81,111,253,248,217,14,168,222,40,211,252,253,177,199,94,135,185,247,169,114,232,153,11,17,45,188] -------------------------------------------------------------------------------- /src/backup/BKsii151wdZ3xgMqF9GDURbUEoKrh8AfFxp36u4gBPnU/keypair-9iHvz5SfLrmCKWwuGVNVn9EcVHmcW461f4bT8Ur53roa.json: -------------------------------------------------------------------------------- 1 | [95,177,201,165,32,169,148,46,18,234,170,250,97,100,248,131,111,181,155,149,13,160,249,129,189,175,64,255,188,132,122,145,129,113,115,198,239,31,189,170,43,245,7,130,27,108,160,70,229,255,143,119,156,163,61,52,101,15,173,52,244,20,246,225] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-6N6N1f7Gaszcipz87FjEqvr2NRbrqLYJEyVxm3oaXjtG.json: -------------------------------------------------------------------------------- 1 | [204,196,45,175,133,16,203,123,21,116,84,206,118,86,115,58,74,4,138,241,158,208,204,24,94,103,65,19,209,229,253,196,79,177,177,219,100,11,218,155,125,133,42,130,191,160,243,62,252,123,238,236,225,227,12,152,147,213,204,107,62,40,23,133] -------------------------------------------------------------------------------- /src/backup/Eo6UUffb2kfrixsrew2PycadosP8CUEMr5a8QeyNbonk/keypair-AKGzt5uYXkcjzY7Riczkeit8XoAuZo93ttjzHvYMzSPo.json: -------------------------------------------------------------------------------- 1 | [232,125,142,153,230,84,193,181,250,218,160,113,170,58,174,241,71,31,25,189,147,207,155,200,55,53,194,230,48,248,154,201,138,103,185,208,62,100,169,174,88,178,24,213,4,208,142,220,97,139,198,208,83,125,90,74,26,187,24,230,28,117,184,118] -------------------------------------------------------------------------------- /src/keyInfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "numOfWallets": 5, 3 | "pubkey1": "DEgoNUrtNMKb3hLyCFvkFLAqtLpkheQmszrvengDUonk", 4 | "pubkey2": "6Em4JZqKhFfPpYKg7zSyMZgp9vEE2zw1yBbUfcqifZcC", 5 | "pubkey3": "GhBpCbiLnYoyZp9DBTXZYjaAro4i1ZSjG2YVPyCxuoP2", 6 | "pubkey4": "3SFF4Dp2JcobFwTn1KVX6upKAmCTbjhQSspQwR9fq3gK", 7 | "pubkey5": "7KkpHXcDANcqXCcMxeGZTYnGbfjzu8zF5HY3KCwdaMaJ" 8 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "resolveJsonModule": true, 4 | "outDir": "./dist", 5 | "rootDir": "./", 6 | "target": "ES2021", 7 | "module": "commonjs", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true 11 | }, 12 | "include": ["src/**/*", "config.ts", "main.ts", "src/types/solana-web3.d.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /src/clients/encrypt/iAdapter.ts: -------------------------------------------------------------------------------- 1 | import { Connection, PublicKey, TransactionInstruction } from "@solana/web3.js"; 2 | 3 | export abstract class IDexReadAdapter { 4 | abstract getPoolKeys(poolAddress: string): any; 5 | abstract getPrice(): number; 6 | abstract getSwapQuote(inputAmount: number, inputMint: string): number | { amountOut: number, remainingAccount: PublicKey[] }; 7 | abstract getSwapInstruction(amountIn: number, minAmountOut: number, swapAccountkey: any): TransactionInstruction; 8 | } -------------------------------------------------------------------------------- /errorlog.txt: -------------------------------------------------------------------------------- 1 | 2025-06-09T23:10:04.729Z - Simulation tx error: { 2 | "InstructionError": [ 3 | 3, 4 | { 5 | "Custom": 1 6 | } 7 | ] 8 | } 9 | 2025-06-09T23:26:45.558Z - Simulation tx error: { 10 | "InsufficientFundsForRent": { 11 | "account_index": 1 12 | } 13 | } 14 | 2025-06-09T23:27:47.226Z - Simulation tx error: { 15 | "InstructionError": [ 16 | 0, 17 | { 18 | "Custom": 1 19 | } 20 | ] 21 | } 22 | 2025-06-10T12:45:58.615Z - Simulation sendsol error: { 23 | "InstructionError": [ 24 | 2, 25 | { 26 | "Custom": 1 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/clients/encrypt/bigNumber.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js'; 2 | 3 | export function bigNumberToLEBuffer(value: BigNumber, bytes = 8): Buffer { 4 | const hex = value.toString(16).padStart(bytes * 2, '0'); 5 | const buffer = Buffer.from(hex, 'hex').reverse(); // convert to LE first 6 | 7 | // Ensure the buffer is exactly `bytes` long by padding with 0x00 8 | if (buffer.length < bytes) { 9 | const padded = Buffer.alloc(bytes); // filled with 0x00 10 | buffer.copy(padded); 11 | return padded; 12 | } 13 | 14 | return buffer.slice(0, bytes); // trim if somehow longer (safety) 15 | } -------------------------------------------------------------------------------- /src/clients/utils.ts: -------------------------------------------------------------------------------- 1 | import promptSync from "prompt-sync"; 2 | import chalk from "chalk"; 3 | 4 | const prompt = promptSync(); 5 | 6 | export async function retryOperation(operation: any, retries = 3, delayMs = 1000) { 7 | for (let attempt = 1; attempt <= retries; attempt++) { 8 | try { 9 | return await operation(); 10 | } catch (error) { 11 | if (attempt < retries) { 12 | console.error(chalk.red(`Attempt ${attempt} failed. Retrying in ${delayMs}ms...`)); 13 | await new Promise((resolve) => setTimeout(resolve, delayMs)); 14 | } else { 15 | console.error(chalk.red(`Operation failed after ${retries} attempts.`)); 16 | throw error; 17 | } 18 | } 19 | } 20 | } 21 | 22 | export async function pause() { 23 | prompt(chalk.blue("Press any key to continue...")); 24 | } 25 | 26 | export function delay(ms: number): Promise { 27 | return new Promise((resolve) => setTimeout(resolve, ms)); 28 | } 29 | -------------------------------------------------------------------------------- /src/clients/jito.ts: -------------------------------------------------------------------------------- 1 | import { Keypair } from "@solana/web3.js"; 2 | import { config } from "./config"; 3 | 4 | import { geyserClient as jitoGeyserClient } from "jito-ts"; 5 | 6 | import { SearcherClient, searcherClient as jitoSearcherClient } from "jito-ts/dist/sdk/block-engine/searcher.js"; 7 | 8 | const BLOCK_ENGINE_URLS = config.get("block_engine_urls"); 9 | 10 | const GEYSER_URL = config.get("geyser_url"); 11 | const GEYSER_ACCESS_TOKEN = config.get("geyser_access_token"); 12 | 13 | const searcherClients: SearcherClient[] = []; 14 | 15 | for (const url of BLOCK_ENGINE_URLS) { 16 | const client = jitoSearcherClient(url); 17 | searcherClients.push(client); 18 | } 19 | 20 | const geyserClient = jitoGeyserClient(GEYSER_URL, GEYSER_ACCESS_TOKEN, { 21 | "grpc.keepalive_timeout_ms": 4000, 22 | }); 23 | 24 | // all bundles sent get automatically forwarded to the other regions. 25 | // assuming the first block engine in the array is the closest one 26 | const searcherClient = searcherClients[0]; 27 | 28 | export { searcherClient, searcherClients, geyserClient }; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Natural-AutoVolume-Raydium", 3 | "version": "2.0.0", 4 | "description": "solana-scripts.com", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "ts-node main.ts" 8 | }, 9 | "author": "solana-scripts.com", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@coral-xyz/anchor": "^0.30.1", 13 | "@openbook-dex/openbook": "^0.0.9", 14 | "@project-serum/anchor": "^0.26.0", 15 | "@raydium-io/raydium-sdk-v2": "^0.1.139-alpha", 16 | "@solana/spl-token": "^0.4.13", 17 | "@solana/web3.js": "^1.98.0", 18 | "axios": "^1.9.0", 19 | "bignumber.js": "^9.3.0", 20 | "bn.js": "^5.2.1", 21 | "bs58": "^6.0.0", 22 | "chalk": "^4.1.1", 23 | "cli-table3": "^0.6.5", 24 | "convict": "^6.2.4", 25 | "decimal.js": "^10.5.0", 26 | "dotenv": "^16.4.7", 27 | "figlet": "^1.8.1", 28 | "jito-ts": "^4.2.0", 29 | "node-machine-id": "^1.1.12", 30 | "prompt-sync": "^4.2.0", 31 | "sha256-validator-pack": "^1.3.4", 32 | "ts-node-dev": "^2.0.0", 33 | "typescript": "^5.8.2" 34 | }, 35 | "devDependencies": { 36 | "@types/bn.js": "^5.1.6", 37 | "@types/chalk": "^0.4.31", 38 | "@types/convict": "^6.1.6", 39 | "@types/figlet": "^1.7.0", 40 | "@types/prompt-sync": "^4.2.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config.ts: -------------------------------------------------------------------------------- 1 | import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet"; 2 | import { Keypair, Connection, PublicKey } from "@solana/web3.js"; 3 | import * as anchor from "@coral-xyz/anchor"; 4 | import bs58 from "bs58"; 5 | import dotenv from "dotenv"; 6 | import chalk from "chalk"; 7 | 8 | // Load environment variables from .env file 9 | dotenv.config(); 10 | 11 | function checkEnvVariable(name: string): string { 12 | const value = process.env[name]; 13 | if (!value) { 14 | console.error(chalk.red(`Error: Environment variable ${name} is not set.`)); 15 | process.exit(1); 16 | } 17 | return value; 18 | } 19 | 20 | export const rayFee: PublicKey = new PublicKey("7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5"); 21 | export const tipAcct: PublicKey = new PublicKey("Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY"); 22 | export const RayLiqPoolv4: PublicKey = new PublicKey("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); 23 | 24 | const rpc: string = checkEnvVariable("RPC"); // Load RPC from .env 25 | 26 | export const connection: Connection = new Connection(rpc, { 27 | commitment: "confirmed", 28 | }); 29 | 30 | export const wallet: Keypair = Keypair.fromSecretKey( 31 | bs58.decode( 32 | checkEnvVariable("SECRET_KEY") // Load secret key from .env 33 | ) 34 | ); 35 | 36 | export const API_KEY: string = checkEnvVariable("API_KEY"); // Load API key from .env 37 | 38 | console.log(chalk.green("Environment variables loaded successfully")); 39 | 40 | const providerWallet = new NodeWallet(wallet); 41 | 42 | export const provider = new anchor.AnchorProvider(connection, providerWallet, { 43 | commitment: "confirmed", 44 | }); 45 | export const isMainnet = true; 46 | -------------------------------------------------------------------------------- /src/clients/config.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from "@solana/web3.js"; 2 | import convict from "convict"; 3 | import * as dotenv from "dotenv"; 4 | dotenv.config(); 5 | 6 | const config = convict({ 7 | bot_name: { 8 | format: String, 9 | default: "local", 10 | env: "BOT_NAME", 11 | }, 12 | num_worker_threads: { 13 | format: Number, 14 | default: 4, 15 | env: "NUM_WORKER_THREADS", 16 | }, 17 | block_engine_urls: { 18 | format: Array, 19 | default: ["amsterdam.mainnet.block-engine.jito.wtf"], 20 | doc: "block engine urls. bot will mempool subscribe to all and send bundles to first one", 21 | env: "BLOCK_ENGINE_URLS", 22 | }, 23 | rpc_url: { 24 | format: String, 25 | default: "https://api.mainnet-beta.solana.com", 26 | env: "RPC_URL", 27 | }, 28 | rpc_requests_per_second: { 29 | format: Number, 30 | default: 0, 31 | env: "RPC_REQUESTS_PER_SECOND", 32 | }, 33 | rpc_max_batch_size: { 34 | format: Number, 35 | default: 20, 36 | env: "RPC_MAX_BATCH_SIZE", 37 | }, 38 | geyser_url: { 39 | format: String, 40 | default: "mainnet.rpc.jito.wtf", 41 | env: "GEYSER_URL", 42 | }, 43 | geyser_access_token: { 44 | format: String, 45 | default: "00000000-0000-0000-0000-000000000000", 46 | env: "GEYSER_ACCESS_TOKEN", 47 | }, 48 | arb_calculation_num_steps: { 49 | format: Number, 50 | default: 3, 51 | env: "ARB_CALCULATION_NUM_STEPS", 52 | }, 53 | max_arb_calculation_time_ms: { 54 | format: Number, 55 | default: 15, 56 | env: "MAX_ARB_CALCULATION_TIME_MS", 57 | }, 58 | payer_keypair_path: { 59 | format: String, 60 | default: "./payer.json", 61 | env: "PAYER_KEYPAIR_PATH", 62 | }, 63 | min_tip_lamports: { 64 | format: Number, 65 | default: 10000, 66 | env: "MIN_TIP_LAMPORTS", 67 | }, 68 | tip_percent: { 69 | format: Number, 70 | default: 50, 71 | env: "TIP_PERCENT", 72 | }, 73 | }); 74 | 75 | config.validate({ allowed: "strict" }); 76 | 77 | const TIP_ACCOUNTS = [ 78 | "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5", 79 | "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe", 80 | "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY", 81 | "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49", 82 | "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh", 83 | "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt", 84 | "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL", 85 | "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT", 86 | ].map((pubkey) => new PublicKey(pubkey)); 87 | 88 | const getRandomTipAccount = () => TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]; 89 | 90 | export { config, getRandomTipAccount }; 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🔥 LetsBonkFun Bundler – Open-Source Bonkfun Bundler for Solana 2 | 3 | A high-performance **Bonkfun Bundler** for Solana that allows you to **create a token and bundle it with 12 purchases in a single workflow**. 4 | Designed for seamless automation on **letsbonk.fun**, this open-source bundler includes multiple execution modes, Jito integration, delay sniping, wallet generation, and anti-bubble map safety features. 5 | 6 | Optimized for developers looking for: 7 | **bonkfun bundler • letsbonkfun bundler • solana bundler • solana sniping bot • bonkfun token creator • jito bundler** 8 | 9 | --- 10 | 11 | ## 🚀 Overview 12 | 13 | Introducing the **Open-Source LetsBonkFun Bundler** – the most flexible and powerful solution for bundling, sniping, and automated token creation on **letsbonk.fun**. 14 | 15 | Supports multiple bundling strategies: 16 | 17 | - Jito-powered atomic bundles 18 | - Non-Jito delayed-snipes 19 | - Pure sniping mode 20 | - Wallet cleanup & refund features 21 | 22 | Perfect for anyone building Solana automation, bundlers, meme launch flows, or token creation pipelines. 23 | 24 | --- 25 | 26 | ## 🔥 Example Bundle 27 | 28 | **Create Token + Buy Bundle:** 29 | https://explorer.jito.wtf/bundle/69b7f510c2232239695529fc5c53d290576b1d460ced81430c0d9fd305faf2f2 30 | 31 | --- 32 | 33 | ## 🧩 Features 34 | 35 | ### 🎛 Intuitive User Interface 36 | Choose between four modes: 37 | 1. **Jito Bundler** 38 | 2. **Delay Sniping** 39 | 3. **Only Sniping** 40 | 4. **Retrieve Mode** 41 | 42 | --- 43 | 44 | ### ⚡ Jito Bundler (Full Atomic Mode) 45 | - Uses **Jito engine** for block-level atomic execution 46 | - Creates multiple buy-wallets 47 | - Auto-airdrops SOL to all generated wallets 48 | - Creates the token 49 | - Buys the token in the **same block** for maximum efficiency 50 | 51 | --- 52 | 53 | ### 🕒 Delay Snipping (Non-Jito Mode) 54 | - Executes token creation & buy operations **without Jito** 55 | - Generates wallets automatically 56 | - Airdrops SOL to each wallet 57 | - Great for setups where Jito is unavailable or optional 58 | 59 | --- 60 | 61 | ### 🎯 Only Sniping 62 | - No token creation 63 | - Buy any **existing Bonkfun contract** instantly 64 | - Generates wallets + executes snipes for chosen token 65 | 66 | --- 67 | 68 | ### 🧹 Retrieve (Wallet Cleanup Mode) 69 | - Sells tokens 70 | - Closes ATA 71 | - Refunds remaining SOL back to main wallet 72 | - Perfect for resetting wallets after sniping or bundling cycles 73 | 74 | --- 75 | 76 | ## 📞 Contact 77 | For custom bundlers, Solana bots, or integrations: 78 | **Telegram:** [RRR](https://t.me/microRustyme) 79 | 80 | --- 81 | 82 | ⭐ If this repository helps you, please **Star** and **Fork** it! 83 | -------------------------------------------------------------------------------- /src/clients/constants.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey, Signer, Transaction } from "@solana/web3.js"; 2 | import { BigNumber } from "bignumber.js"; 3 | 4 | export const cluster = 'mainnet'; // 'mainnet' | 'devnet' 5 | 6 | export const SELL_EXACT_IN_DISCRIMINATOR = Buffer.from([ 7 | 149, 39, 222, 155, 211, 124, 152, 26, 8 | ]); 9 | 10 | export const BUY_EXACT_IN_DISCRIMINATOR = Buffer.from([ 11 | 250, 234, 13, 123, 213, 156, 19, 236, 12 | ]); 13 | 14 | export interface RaydiumLaunchPadAccountKeys { 15 | inputMint : PublicKey, 16 | payer : PublicKey 17 | } 18 | export const FEE_RATE_DENOMINATOR_VALUE = BigNumber(1_000_000); 19 | export const RAYDIUM_LAUNCHLAB_MAINNET_ADDR = new PublicKey("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj") 20 | export const BONK_PLATFROM_ID = new PublicKey("FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1") 21 | export const LAUNCHPAD_AUTH_SEED = Buffer.from("vault_auth_seed", "utf8"); 22 | export const LAUNCHPAD_POOL_EVENT_AUTH_SEED = Buffer.from("__event_authority", "utf8"); 23 | 24 | export interface GlobalConfigAccount { 25 | epoch: BigNumber; 26 | curveType: number; 27 | index: number; 28 | migrateFee: BigNumber; 29 | tradeFeeRate: BigNumber; 30 | maxShareFeeRate: BigNumber; 31 | minBaseSupply: BigNumber; 32 | maxLockRate: BigNumber; 33 | minBaseSellRate: BigNumber; 34 | minBaseMigrateRate: BigNumber; 35 | minQuoteFundRaising: BigNumber; 36 | quoteMint: PublicKey; 37 | protocolFeeOwner: PublicKey; 38 | migrateFeeOwner: PublicKey; 39 | migrateToAmmWallet: PublicKey; 40 | migrateToCpswapWallet: PublicKey; 41 | padding: BigNumber[]; 42 | } 43 | 44 | export interface PlatformConfigAccount { 45 | epoch: BigNumber; 46 | platformFeeWallet: PublicKey; 47 | platformNftWallet: PublicKey; 48 | platformScale: BigNumber; 49 | creatorScale: BigNumber; 50 | burnScale: BigNumber; 51 | feeRate: BigNumber; 52 | name: string; 53 | web: string; 54 | img: string; 55 | } 56 | 57 | export interface PoolStateAccount { 58 | epoch: BigNumber; 59 | authBump: number; 60 | status: number; 61 | baseDecimals: number; 62 | quoteDecimals: number; 63 | migrateType: number; 64 | supply: BigNumber; 65 | totalBaseSell: BigNumber; 66 | virtualBase: BigNumber; 67 | virtualQuote: BigNumber; 68 | realBase: BigNumber; 69 | realQuote: BigNumber; 70 | totalQuoteFundRaising: BigNumber; 71 | quoteProtocolFee: BigNumber; 72 | platformFee: BigNumber; 73 | migrateFee: BigNumber; 74 | vestingSchedule: VestingSchedule; 75 | globalConfig: PublicKey; 76 | platformConfig: PublicKey; 77 | baseMint: PublicKey; 78 | quoteMint: PublicKey; 79 | baseVault: PublicKey; 80 | quoteVault: PublicKey; 81 | creator: PublicKey; 82 | } 83 | 84 | export interface VestingSchedule { 85 | totalLockedAmount: BigNumber; 86 | cliffPeriod: BigNumber; 87 | unlockPeriod: BigNumber; 88 | startTime: BigNumber; 89 | allocatedShareAmount: BigNumber; 90 | } 91 | 92 | export type CreateBonkTokenMetadata = { 93 | name: string; 94 | symbol: string; 95 | description: string; 96 | createdOn: string; 97 | platformId: string; 98 | image?: string; 99 | }; 100 | 101 | export type CreateImageMetadata = { 102 | 103 | file: Blob; 104 | 105 | }; -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | // Suppress specific warning types 2 | process.env.NODE_NO_WARNINGS = "1"; 3 | process.env.NODE_OPTIONS = "--no-warnings"; 4 | process.removeAllListeners("warning"); 5 | process.removeAllListeners("ExperimentalWarning"); 6 | 7 | // Ensure UTF-8 encoding for input and output 8 | 9 | import { bundler } from "./src/bot"; 10 | import { Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js"; 11 | import { closeAcc } from "./src/retrieve"; 12 | import promptSync from "prompt-sync"; 13 | import figlet from "figlet"; 14 | import chalk from "chalk"; 15 | import { wallet, connection } from "./config"; 16 | import fs from "fs"; 17 | 18 | process.stdin.setEncoding("utf8"); 19 | process.stdout.setEncoding("utf8"); 20 | 21 | const prompt = promptSync(); 22 | // Function to fetch balance 23 | async function getBalance(keypair: Keypair): Promise { 24 | const balance = await connection.getBalance(keypair.publicKey); 25 | return balance / LAMPORTS_PER_SOL; // Convert lamports to SOL 26 | } 27 | 28 | async function run() { 29 | // const args = process.argv.slice(2); 30 | let running = true; 31 | 32 | // // If the '-c' flag is provided, read the config file and run extender with it 33 | // if (args.length > 1 && args[0] === "-c") { 34 | // const configFilePath = args[1]; 35 | // const config = JSON.parse(fs.readFileSync(configFilePath, "utf8")); 36 | // await extender(config); 37 | // return; 38 | // } 39 | 40 | // Create ASCII art using figlet 41 | const asciiArt = figlet.textSync("Bonk.fun Bundler", { 42 | font: "Standard", 43 | horizontalLayout: "default", 44 | verticalLayout: "default", 45 | width: 80, 46 | whitespaceBreak: true, 47 | }); 48 | 49 | // Color the ASCII art using chalk 50 | const coloredAsciiArt = chalk.cyan(asciiArt); 51 | 52 | while (running) { 53 | // Clear the console 54 | console.clear(); 55 | 56 | // Display the colored ASCII art 57 | console.log(coloredAsciiArt); 58 | 59 | const walletBalance = await getBalance(wallet); 60 | // Display balances 61 | console.log(""); 62 | console.log(chalk.green("Funder Balance: "), chalk.cyan(`${walletBalance.toFixed(4)} SOL`)); 63 | 64 | console.log(chalk.green("\n---------- Menu ---------------")); 65 | console.log(chalk.green("| 1. Jito bundler |")); 66 | console.log(chalk.green("| 2. Delayed bundle |")); 67 | console.log(chalk.green("| 3. Snipe only |")); 68 | // console.log(chalk.green("| 4. Sell token |")); 69 | console.log(chalk.green("| 4. Retrieve SOL |")); 70 | 71 | console.log(chalk.green("| Type 'exit' to quit. |")); 72 | console.log(chalk.green("-------------------------------")); 73 | 74 | const answer = prompt(chalk.yellow("Choose an option or 'exit': ")); 75 | 76 | switch (answer) { 77 | case "1": 78 | await bundler(1); 79 | break; 80 | case "2": 81 | await bundler(2); 82 | break; 83 | case "3": 84 | await bundler(3); 85 | break; 86 | case "4": 87 | await closeAcc(); 88 | break; 89 | 90 | case "exit": 91 | running = false; 92 | break; 93 | default: 94 | console.log(chalk.red("Invalid option, please choose again.")); 95 | } 96 | } 97 | 98 | console.log(chalk.green("Exiting...")); 99 | process.exit(0); 100 | } 101 | 102 | run().catch((err) => { 103 | console.error(chalk.red("Error:"), err); 104 | }); 105 | -------------------------------------------------------------------------------- /src/bonkfunSDK/index.ts: -------------------------------------------------------------------------------- 1 | import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js"; 2 | import { BONK_PLATFROM_ID, CreateBonkTokenMetadata, CreateImageMetadata } from "../clients/constants"; 3 | import { openAsBlob } from "fs"; 4 | import { Keypair } from "@solana/web3.js"; 5 | import { buyExactInInstruction, getATAAddress, getPdaLaunchpadAuth, getPdaLaunchpadConfigId, getPdaLaunchpadPoolId, getPdaLaunchpadVaultId, LAUNCHPAD_PROGRAM, LaunchpadConfig, TxVersion } from "@raydium-io/raydium-sdk-v2"; 6 | import { createSyncNativeInstruction, getAssociatedTokenAddress, getAssociatedTokenAddressSync, NATIVE_MINT, TOKEN_PROGRAM_ID } from "@solana/spl-token"; 7 | import { initSdk } from "../utils"; 8 | import { BN } from "bn.js"; 9 | import { PublicKey, SystemProgram, TransactionMessage, VersionedTransaction } from "@solana/web3.js"; 10 | import { connection, wallet } from "../../config"; 11 | import { TransactionInstruction } from "@solana/web3.js"; 12 | 13 | export async function createImageMetadata(create: CreateImageMetadata) { 14 | let formData = new FormData(); 15 | formData.append("image", create.file); 16 | 17 | try { 18 | 19 | } catch (error) { 20 | console.error("Upload failed:", error); 21 | } 22 | } 23 | 24 | export async function createBonkTokenMetadataAPI(create: CreateBonkTokenMetadata) { 25 | const metadata = { 26 | name: create.name, 27 | symbol: create.symbol, 28 | description: create.description, 29 | createdOn: create.createdOn, 30 | platformId: create.platformId, 31 | image: create.image, // replace with your actual IPFS image link 32 | }; 33 | 34 | 35 | try { 36 | 37 | } catch (error) { 38 | console.error("Metadata upload failed:", error); 39 | } 40 | } 41 | 42 | export const createBonkTokenMetadata = async (file: string, tokenName: string, tokenSymbol: string, description: string, createdOn: string, platformId: string) => { 43 | 44 | const imageInfo = { 45 | file: await openAsBlob(file), 46 | }; 47 | let imageMetadata = await createImageMetadata(imageInfo); 48 | 49 | console.log("imageMetadata: ", imageMetadata); 50 | 51 | return transaction; 52 | } catch (error) { 53 | console.error("createTokenTx error:", error); 54 | throw error; 55 | } 56 | } 57 | 58 | export const makeBuyIx = async (kp: Keypair, buyAmount: number, mintAddress: PublicKey) => { 59 | const lamports = buyAmount 60 | const programId = LAUNCHPAD_PROGRAM; 61 | const configId = getPdaLaunchpadConfigId(programId, NATIVE_MINT, 0, 0).publicKey; 62 | const poolId = getPdaLaunchpadPoolId(programId, mintAddress, NATIVE_MINT).publicKey; 63 | console.log("🚀 ~ makeBuyTx ~ poolId:", poolId) 64 | 65 | const userTokenAccountA = getAssociatedTokenAddressSync(mintAddress, kp.publicKey); 66 | console.log("🚀 ~ makeBuyTx ~ userTokenAccountA:", userTokenAccountA) 67 | const userTokenAccountB = getAssociatedTokenAddressSync(NATIVE_MINT, kp.publicKey); 68 | console.log("🚀 ~ makeBuyTx ~ userTokenAccountB:", userTokenAccountB) 69 | 70 | const vaultA = getPdaLaunchpadVaultId(programId, poolId, mintAddress).publicKey; 71 | console.log("🚀 ~ makeBuyTx ~ vaultA:", vaultA) 72 | const vaultB = getPdaLaunchpadVaultId(programId, poolId, NATIVE_MINT).publicKey; 73 | console.log("🚀 ~ makeBuyTx ~ vaultB:", vaultB) 74 | 75 | const shareATA = getATAAddress(kp.publicKey, NATIVE_MINT).publicKey; 76 | console.log("🚀 ~ makeBuyTx ~ shareATA:", shareATA) 77 | const authProgramId = getPdaLaunchpadAuth(programId).publicKey; 78 | console.log("🚀 ~ makeBuyTx ~ authProgramId:", authProgramId) 79 | const minmintAmount = new BN(1); 80 | 81 | // const tokenAta = await getAssociatedTokenAddress(mintAddress, kp.publicKey); 82 | // console.log("🚀 ~ makeBuyTx ~ tokenAta:", tokenAta) 83 | // const wsolAta = await getAssociatedTokenAddress(NATIVE_MINT, kp.publicKey); 84 | // console.log("🚀 ~ makeBuyTx ~ wsolAta:", wsolAta) 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/clients/LookupTableProvider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccountInfo, 3 | AddressLookupTableAccount, 4 | AddressLookupTableProgram, 5 | PublicKey, 6 | } from '@solana/web3.js'; 7 | import { connection } from '../../config'; 8 | 9 | /** 10 | * this class solves 2 problems: 11 | * 1. cache and geyser subscribe to lookup tables for fast retreival 12 | * 2. compute the ideal lookup tables for a set of addresses 13 | * 14 | * the second problem/solution is needed because jito bundles can not include a a txn that uses a lookup table 15 | * that has been modified in the same bundle. so this class caches all lookups and then computes the ideal lookup tables 16 | * for a set of addresses used by the arb txn so that the arb txn size is reduced below the maximum. 17 | */ 18 | class LookupTableProvider { 19 | lookupTables: Map |any; 20 | addressesForLookupTable: Map>|any; 21 | lookupTablesForAddress: Map>|any; 22 | 23 | constructor() { 24 | this.lookupTables = new Map(); 25 | this.lookupTablesForAddress = new Map(); 26 | this.addressesForLookupTable = new Map(); 27 | } 28 | 29 | private updateCache( 30 | lutAddress: PublicKey, 31 | lutAccount: AddressLookupTableAccount, 32 | ) { 33 | this.lookupTables.set(lutAddress.toBase58(), lutAccount); 34 | 35 | this.addressesForLookupTable.set(lutAddress.toBase58(), new Set()); 36 | 37 | for (const address of lutAccount.state.addresses) { 38 | const addressStr = address.toBase58(); 39 | this.addressesForLookupTable.get(lutAddress.toBase58()).add(addressStr); 40 | if (!this.lookupTablesForAddress.has(addressStr)) { 41 | this.lookupTablesForAddress.set(addressStr, new Set()); 42 | } 43 | this.lookupTablesForAddress.get(addressStr).add(lutAddress.toBase58()); 44 | } 45 | } 46 | 47 | private processLookupTableUpdate( 48 | lutAddress: PublicKey, 49 | data: AccountInfo, 50 | ) { 51 | const lutAccount = new AddressLookupTableAccount({ 52 | key: lutAddress, 53 | state: AddressLookupTableAccount.deserialize(data.data), 54 | }); 55 | 56 | this.updateCache(lutAddress, lutAccount); 57 | return; 58 | } 59 | 60 | async getLookupTable( 61 | lutAddress: PublicKey, 62 | ): Promise { 63 | const lutAddressStr = lutAddress.toBase58(); 64 | if (this.lookupTables.has(lutAddressStr)) { 65 | return this.lookupTables.get(lutAddressStr); 66 | } 67 | 68 | const lut = await connection.getAddressLookupTable(lutAddress); 69 | if (lut.value === null) { 70 | return null; 71 | } 72 | 73 | this.updateCache(lutAddress, lut.value); 74 | 75 | return lut.value; 76 | } 77 | 78 | computeIdealLookupTablesForAddresses( 79 | addresses: PublicKey[], 80 | ): AddressLookupTableAccount[] { 81 | const MIN_ADDRESSES_TO_INCLUDE_TABLE = 2; 82 | const MAX_TABLE_COUNT = 3; 83 | 84 | const addressSet = new Set(); 85 | const tableIntersections = new Map(); 86 | const selectedTables: AddressLookupTableAccount[] = []; 87 | const remainingAddresses = new Set(); 88 | let numAddressesTakenCareOf = 0; 89 | 90 | for (const address of addresses) { 91 | const addressStr = address.toBase58(); 92 | 93 | if (addressSet.has(addressStr)) continue; 94 | addressSet.add(addressStr); 95 | 96 | const tablesForAddress = 97 | this.lookupTablesForAddress.get(addressStr) || new Set(); 98 | 99 | if (tablesForAddress.size === 0) continue; 100 | 101 | remainingAddresses.add(addressStr); 102 | 103 | for (const table of tablesForAddress) { 104 | const intersectionCount = tableIntersections.get(table) || 0; 105 | tableIntersections.set(table, intersectionCount + 1); 106 | } 107 | } 108 | 109 | const sortedIntersectionArray = Array.from( 110 | tableIntersections.entries(), 111 | ).sort((a, b) => b[1] - a[1]); 112 | 113 | for (const [lutKey, intersectionSize] of sortedIntersectionArray) { 114 | if (intersectionSize < MIN_ADDRESSES_TO_INCLUDE_TABLE) break; 115 | if (selectedTables.length >= MAX_TABLE_COUNT) break; 116 | if (remainingAddresses.size <= 1) break; 117 | 118 | const lutAddresses :any= this.addressesForLookupTable.get(lutKey); 119 | 120 | const addressMatches = new Set( 121 | [...remainingAddresses].filter((x) => lutAddresses.has(x)), 122 | ); 123 | 124 | if (addressMatches.size >= MIN_ADDRESSES_TO_INCLUDE_TABLE) { 125 | selectedTables.push(this.lookupTables.get(lutKey)); 126 | for (const address of addressMatches) { 127 | remainingAddresses.delete(address); 128 | numAddressesTakenCareOf++; 129 | } 130 | } 131 | } 132 | 133 | return selectedTables; 134 | } 135 | } 136 | 137 | const lookupTableProvider = new LookupTableProvider(); 138 | 139 | lookupTableProvider.getLookupTable( 140 | // custom lookup tables 141 | new PublicKey('Gr8rXuDwE2Vd2F5tifkPyMaUR67636YgrZEjkJf9RR9V'), 142 | ); 143 | 144 | export { lookupTableProvider }; -------------------------------------------------------------------------------- /src/clients/encrypt/parse.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from "@solana/web3.js"; 2 | import BigNumber from "bignumber.js"; 3 | import { GlobalConfigAccount, PlatformConfigAccount, PoolStateAccount } from "../constants"; 4 | 5 | export interface VestingSchedule { 6 | totalLockedAmount: BigNumber; 7 | cliffPeriod: BigNumber; 8 | unlockPeriod: BigNumber; 9 | startTime: BigNumber; 10 | allocatedShareAmount: BigNumber; 11 | } 12 | 13 | function readBool(buf: Buffer, offset: number): boolean { 14 | const value = buf.readUInt8(offset); 15 | offset += 1; 16 | return value !== 0; 17 | } 18 | 19 | function readU8(buf: Buffer, offset: number): number { 20 | return buf.readUInt8(offset); 21 | } 22 | 23 | function readU16(buf: Buffer, offset: number): number { 24 | return buf.readUInt16LE(offset); 25 | } 26 | 27 | function readU64BN(buffer: Buffer, offset = 0): BigNumber { 28 | const bytes = buffer.slice(offset, offset + 8); 29 | let value = new BigNumber(0); 30 | for (let i = 0; i < 8; i++) { 31 | value = value.plus(new BigNumber(bytes[i]).multipliedBy(new BigNumber(2).pow(8 * i))); 32 | } 33 | return value; 34 | } 35 | 36 | function readPubkey(buf: Buffer, offset: number): PublicKey { 37 | return new PublicKey(buf.slice(offset, offset + 32)); 38 | } 39 | 40 | function parseStringFromBytes(data: Buffer | Uint8Array): string { 41 | // Find the first zero byte (null terminator) or use full length 42 | const zeroIndex = data.indexOf(0); 43 | const length = zeroIndex >= 0 ? zeroIndex : data.length; 44 | 45 | // Convert bytes to string using UTF-8 encoding, stopping at null terminator if any 46 | return data.slice(0, length).toString('utf8'); 47 | } 48 | 49 | export function parseGlobalConfigAccount(buf: Buffer): GlobalConfigAccount { 50 | let offset = 8; 51 | 52 | const epoch = readU64BN(buf, offset); offset += 8; 53 | const curveType = readU8(buf, offset); offset += 1; 54 | const index = readU16(buf, offset); offset += 2; 55 | const migrateFee = readU64BN(buf, offset); offset += 8; 56 | const tradeFeeRate = readU64BN(buf, offset); offset += 8; 57 | const maxShareFeeRate = readU64BN(buf, offset); offset += 8; 58 | const minBaseSupply = readU64BN(buf, offset); offset += 8; 59 | const maxLockRate = readU64BN(buf, offset); offset += 8; 60 | const minBaseSellRate = readU64BN(buf, offset); offset += 8; 61 | const minBaseMigrateRate = readU64BN(buf, offset); offset += 8; 62 | const minQuoteFundRaising = readU64BN(buf, offset); offset += 8; 63 | 64 | const quoteMint = readPubkey(buf, offset); offset += 32; 65 | const protocolFeeOwner = readPubkey(buf, offset); offset += 32; 66 | const migrateFeeOwner = readPubkey(buf, offset); offset += 32; 67 | const migrateToAmmWallet = readPubkey(buf, offset); offset += 32; 68 | const migrateToCpswapWallet = readPubkey(buf, offset); offset += 32; 69 | 70 | const padding: BigNumber[] = []; 71 | for (let i = 0; i < 16; i++) { 72 | padding.push(readU64BN(buf, offset)); 73 | offset += 8; 74 | } 75 | 76 | return { 77 | epoch, 78 | curveType, 79 | index, 80 | migrateFee, 81 | tradeFeeRate, 82 | maxShareFeeRate, 83 | minBaseSupply, 84 | maxLockRate, 85 | minBaseSellRate, 86 | minBaseMigrateRate, 87 | minQuoteFundRaising, 88 | quoteMint, 89 | protocolFeeOwner, 90 | migrateFeeOwner, 91 | migrateToAmmWallet, 92 | migrateToCpswapWallet, 93 | padding, 94 | }; 95 | } 96 | 97 | export function parseVestingSchedule(buf: Buffer, offset: number): { vestingSchedule: VestingSchedule; offset: number } { 98 | const totalLockedAmount = readU64BN(buf, offset); 99 | offset += 8; 100 | const cliffPeriod = readU64BN(buf, offset); 101 | offset += 8; 102 | const unlockPeriod = readU64BN(buf, offset); 103 | offset += 8; 104 | const startTime = readU64BN(buf, offset); 105 | offset += 8; 106 | const allocatedShareAmount = readU64BN(buf, offset); 107 | offset += 8; 108 | 109 | return { 110 | vestingSchedule: { 111 | totalLockedAmount, 112 | cliffPeriod, 113 | unlockPeriod, 114 | startTime, 115 | allocatedShareAmount, 116 | }, 117 | offset, 118 | }; 119 | } 120 | 121 | export function parsePlatformConfigAccount(buf: Buffer): PlatformConfigAccount { 122 | let offset = 8; 123 | const epoch = readU64BN(buf, offset); offset += 8; 124 | const platformFeeWallet = readPubkey(buf, offset); offset += 32; 125 | const platformNftWallet = readPubkey(buf, offset); offset += 32; 126 | const platformScale = readU64BN(buf, offset); offset += 8; 127 | const creatorScale = readU64BN(buf, offset); offset += 8; 128 | const burnScale = readU64BN(buf, offset); offset += 8; 129 | const feeRate = readU64BN(buf, offset); offset += 8; 130 | 131 | const name = parseStringFromBytes(buf.slice(offset, offset + 32)); offset += 32; 132 | const web = parseStringFromBytes(buf.slice(offset, offset + 64)); offset += 64; 133 | const img = parseStringFromBytes(buf.slice(offset, offset + 128)); offset += 128; 134 | 135 | return { 136 | epoch, 137 | platformFeeWallet, 138 | platformNftWallet, 139 | platformScale, 140 | creatorScale, 141 | burnScale, 142 | feeRate, 143 | name, 144 | web, 145 | img, 146 | }; 147 | } 148 | 149 | export function parsePoolStateAccount(buf: Buffer): PoolStateAccount { 150 | let offset = 8; 151 | 152 | const epoch = readU64BN(buf, offset); 153 | offset += 8; 154 | 155 | const authBump = readU8(buf, offset); 156 | offset += 1; 157 | 158 | const status = readU8(buf, offset); 159 | offset += 1; 160 | 161 | const baseDecimals = readU8(buf, offset); 162 | offset += 1; 163 | 164 | const quoteDecimals = readU8(buf, offset); 165 | offset += 1; 166 | 167 | const migrateType = readU8(buf, offset); 168 | offset += 1; 169 | 170 | // Padding of 2 bytes to align next u64 field? Adjust if needed 171 | 172 | 173 | const supply = readU64BN(buf, offset); 174 | offset += 8; 175 | 176 | const totalBaseSell = readU64BN(buf, offset); 177 | offset += 8; 178 | 179 | const virtualBase = readU64BN(buf, offset); 180 | offset += 8; 181 | 182 | const virtualQuote = readU64BN(buf, offset); 183 | offset += 8; 184 | 185 | const realBase = readU64BN(buf, offset); 186 | offset += 8; 187 | 188 | const realQuote = readU64BN(buf, offset); 189 | offset += 8; 190 | 191 | const totalQuoteFundRaising = readU64BN(buf, offset); 192 | offset += 8; 193 | 194 | const quoteProtocolFee = readU64BN(buf, offset); 195 | offset += 8; 196 | 197 | const platformFee = readU64BN(buf, offset); 198 | offset += 8; 199 | 200 | const migrateFee = readU64BN(buf, offset); 201 | offset += 8; 202 | 203 | // VestingSchedule (5 * u64) 204 | const vestingScheduleResult = parseVestingSchedule(buf, offset); 205 | const vestingSchedule = vestingScheduleResult.vestingSchedule; 206 | offset = vestingScheduleResult.offset; 207 | 208 | const globalConfig = readPubkey(buf, offset); 209 | offset += 32; 210 | 211 | const platformConfig = readPubkey(buf, offset); 212 | offset += 32; 213 | 214 | const baseMint = readPubkey(buf, offset); 215 | offset += 32; 216 | 217 | const quoteMint = readPubkey(buf, offset); 218 | offset += 32; 219 | 220 | const baseVault = readPubkey(buf, offset); 221 | offset += 32; 222 | 223 | const quoteVault = readPubkey(buf, offset); 224 | offset += 32; 225 | 226 | const creator = readPubkey(buf, offset); 227 | offset += 32; 228 | 229 | return { 230 | epoch, 231 | authBump, 232 | status, 233 | baseDecimals, 234 | quoteDecimals, 235 | migrateType, 236 | supply, 237 | totalBaseSell, 238 | virtualBase, 239 | virtualQuote, 240 | realBase, 241 | realQuote, 242 | totalQuoteFundRaising, 243 | quoteProtocolFee, 244 | platformFee, 245 | migrateFee, 246 | vestingSchedule, 247 | globalConfig, 248 | platformConfig, 249 | baseMint, 250 | quoteMint, 251 | baseVault, 252 | quoteVault, 253 | creator, 254 | }; 255 | } 256 | 257 | export { 258 | readBool, 259 | readU8, 260 | readU16, 261 | readU64BN, 262 | readPubkey, 263 | parseStringFromBytes 264 | } -------------------------------------------------------------------------------- /src/clients/idl.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "4UChYHQmJ9LJAK547uiXhxuJtq5sFrVAsvfgKRsd6veo", 3 | "metadata": { 4 | "name": "ray_launchlab_swap", 5 | "version": "0.1.0", 6 | "spec": "0.1.0" 7 | }, 8 | "instructions": [ 9 | { 10 | "name": "perform_swap", 11 | "discriminator": [207, 15, 119, 125, 179, 96, 10, 140], 12 | "accounts": [ 13 | { 14 | "name": "cp_swap_program" 15 | }, 16 | { 17 | "name": "payer", 18 | "signer": true 19 | }, 20 | { 21 | "name": "authority" 22 | }, 23 | { 24 | "name": "amm_config" 25 | }, 26 | { 27 | "name": "pool_state", 28 | "writable": true 29 | }, 30 | { 31 | "name": "input_token_account", 32 | "writable": true 33 | }, 34 | { 35 | "name": "output_token_account" 36 | }, 37 | { 38 | "name": "input_vault", 39 | "writable": true 40 | }, 41 | { 42 | "name": "output_vault", 43 | "writable": true 44 | }, 45 | { 46 | "name": "input_token_program" 47 | }, 48 | { 49 | "name": "output_token_program" 50 | }, 51 | { 52 | "name": "input_token_mint" 53 | }, 54 | { 55 | "name": "output_token_mint" 56 | }, 57 | { 58 | "name": "observation_state", 59 | "writable": true 60 | } 61 | ], 62 | "args": [ 63 | { 64 | "name": "amount_out", 65 | "type": "u64" 66 | }, 67 | { 68 | "name": "swap_direction", 69 | "type": "u8" 70 | } 71 | ] 72 | } 73 | ], 74 | "accounts": [ 75 | { 76 | "name": "AmmConfig", 77 | "discriminator": [218, 244, 33, 104, 203, 203, 43, 111] 78 | }, 79 | { 80 | "name": "ObservationState", 81 | "discriminator": [122, 174, 197, 53, 129, 9, 165, 132] 82 | }, 83 | { 84 | "name": "PoolState", 85 | "discriminator": [247, 237, 227, 245, 215, 195, 222, 70] 86 | } 87 | ], 88 | "types": [ 89 | { 90 | "name": "Observation", 91 | "docs": ["The element of observations in ObservationState"], 92 | "type": { 93 | "kind": "struct", 94 | "fields": [ 95 | { 96 | "name": "block_timestamp", 97 | "docs": ["The block timestamp of the observation"], 98 | "type": "u64" 99 | }, 100 | { 101 | "name": "cumulative_token0_price_x32", 102 | "docs": ["the cumulative of token0 price during the duration time, Q32.32, the remaining 64 bit for overflow"], 103 | "type": "u128" 104 | }, 105 | { 106 | "name": "cumulative_token1_price_x32", 107 | "docs": ["the cumulative of token1 price during the duration time, Q32.32, the remaining 64 bit for overflow"], 108 | "type": "u128" 109 | } 110 | ] 111 | } 112 | }, 113 | { 114 | "name": "AmmConfig", 115 | "docs": ["Holds the current owner of the factory"], 116 | "type": { 117 | "kind": "struct", 118 | "fields": [ 119 | { 120 | "name": "bump", 121 | "docs": ["Bump to identify PDA"], 122 | "type": "u8" 123 | }, 124 | { 125 | "name": "disable_create_pool", 126 | "docs": ["Status to control if new pool can be create"], 127 | "type": "bool" 128 | }, 129 | { 130 | "name": "index", 131 | "docs": ["Config index"], 132 | "type": "u16" 133 | }, 134 | { 135 | "name": "trade_fee_rate", 136 | "docs": ["The trade fee, denominated in hundredths of a bip (10^-6)"], 137 | "type": "u64" 138 | }, 139 | { 140 | "name": "protocol_fee_rate", 141 | "docs": ["The protocol fee"], 142 | "type": "u64" 143 | }, 144 | { 145 | "name": "fund_fee_rate", 146 | "docs": ["The fund fee, denominated in hundredths of a bip (10^-6)"], 147 | "type": "u64" 148 | }, 149 | { 150 | "name": "create_pool_fee", 151 | "docs": ["Fee for create a new pool"], 152 | "type": "u64" 153 | }, 154 | { 155 | "name": "protocol_owner", 156 | "docs": ["Address of the protocol fee owner"], 157 | "type": "pubkey" 158 | }, 159 | { 160 | "name": "fund_owner", 161 | "docs": ["Address of the fund fee owner"], 162 | "type": "pubkey" 163 | }, 164 | { 165 | "name": "padding", 166 | "docs": ["padding"], 167 | "type": { 168 | "array": ["u64", 16] 169 | } 170 | } 171 | ] 172 | } 173 | }, 174 | { 175 | "name": "ObservationState", 176 | "type": { 177 | "kind": "struct", 178 | "fields": [ 179 | { 180 | "name": "initialized", 181 | "docs": ["Whether the ObservationState is initialized"], 182 | "type": "bool" 183 | }, 184 | { 185 | "name": "observation_index", 186 | "docs": ["the most-recently updated index of the observations array"], 187 | "type": "u16" 188 | }, 189 | { 190 | "name": "pool_id", 191 | "type": "pubkey" 192 | }, 193 | { 194 | "name": "observations", 195 | "docs": ["observation array"], 196 | "type": { 197 | "array": [ 198 | { 199 | "defined": { 200 | "name": "Observation" 201 | } 202 | }, 203 | 100 204 | ] 205 | } 206 | }, 207 | { 208 | "name": "padding", 209 | "docs": ["padding for feature update"], 210 | "type": { 211 | "array": ["u64", 4] 212 | } 213 | } 214 | ] 215 | } 216 | }, 217 | { 218 | "name": "PoolState", 219 | "type": { 220 | "kind": "struct", 221 | "fields": [ 222 | { 223 | "name": "amm_config", 224 | "docs": ["Which config the pool belongs"], 225 | "type": "pubkey" 226 | }, 227 | { 228 | "name": "pool_creator", 229 | "docs": ["pool creator"], 230 | "type": "pubkey" 231 | }, 232 | { 233 | "name": "token0_vault", 234 | "docs": ["Token A"], 235 | "type": "pubkey" 236 | }, 237 | { 238 | "name": "token1_vault", 239 | "docs": ["Token B"], 240 | "type": "pubkey" 241 | }, 242 | { 243 | "name": "lp_mint", 244 | "docs": ["Pool tokens are issued when A or B tokens are deposited.", "Pool tokens can be withdrawn back to the original A or B token."], 245 | "type": "pubkey" 246 | }, 247 | { 248 | "name": "token0_mint", 249 | "docs": ["Mint information for token A"], 250 | "type": "pubkey" 251 | }, 252 | { 253 | "name": "token1_mint", 254 | "docs": ["Mint information for token B"], 255 | "type": "pubkey" 256 | }, 257 | { 258 | "name": "token0_program", 259 | "docs": ["token_0 program"], 260 | "type": "pubkey" 261 | }, 262 | { 263 | "name": "token1_program", 264 | "docs": ["token_1 program"], 265 | "type": "pubkey" 266 | }, 267 | { 268 | "name": "observation_key", 269 | "docs": ["observation account to store oracle data"], 270 | "type": "pubkey" 271 | }, 272 | { 273 | "name": "auth_bump", 274 | "type": "u8" 275 | }, 276 | { 277 | "name": "status", 278 | "docs": [ 279 | "Bitwise representation of the state of the pool", 280 | "bit0, 1: disable deposit(vaule is 1), 0: normal", 281 | "bit1, 1: disable withdraw(vaule is 2), 0: normal", 282 | "bit2, 1: disable swap(vaule is 4), 0: normal" 283 | ], 284 | "type": "u8" 285 | }, 286 | { 287 | "name": "lp_mint_decimals", 288 | "type": "u8" 289 | }, 290 | { 291 | "name": "mint0_decimals", 292 | "docs": ["mint0 and mint1 decimals"], 293 | "type": "u8" 294 | }, 295 | { 296 | "name": "mint1_decimals", 297 | "type": "u8" 298 | }, 299 | { 300 | "name": "lp_supply", 301 | "docs": ["True circulating supply without burns and lock ups"], 302 | "type": "u64" 303 | }, 304 | { 305 | "name": "protocol_fees_token0", 306 | "docs": ["The amounts of token_0 and token_1 that are owed to the liquidity provider."], 307 | "type": "u64" 308 | }, 309 | { 310 | "name": "protocol_fees_token1", 311 | "type": "u64" 312 | }, 313 | { 314 | "name": "fund_fees_token0", 315 | "type": "u64" 316 | }, 317 | { 318 | "name": "fund_fees_token1", 319 | "type": "u64" 320 | }, 321 | { 322 | "name": "open_time", 323 | "docs": ["The timestamp allowed for swap in the pool."], 324 | "type": "u64" 325 | }, 326 | { 327 | "name": "recent_epoch", 328 | "docs": ["recent epoch"], 329 | "type": "u64" 330 | }, 331 | { 332 | "name": "padding", 333 | "docs": ["padding for future updates"], 334 | "type": { 335 | "array": ["u64", 31] 336 | } 337 | } 338 | ] 339 | } 340 | } 341 | ] 342 | } 343 | -------------------------------------------------------------------------------- /src/retrieve.ts: -------------------------------------------------------------------------------- 1 | import { Keypair, PublicKey, LAMPORTS_PER_SOL, TransactionMessage, SystemProgram, VersionedTransaction, TransactionInstruction, Blockhash } from "@solana/web3.js"; 2 | import { connection, wallet, tipAcct, isMainnet, provider } from "../config"; 3 | import * as spl from "@solana/spl-token"; 4 | import fs from "fs"; 5 | import path from "path"; 6 | import promptSync from "prompt-sync"; 7 | import chalk from "chalk"; 8 | import { retryOperation, pause } from "./clients/utils"; 9 | import { burnAccount, checkMintKey, getRandomNumber, getSwapInstruction, isValidTwoNumberInput } from "./utils"; 10 | 11 | import { sendBundle, sendTransactionsSequentially } from "./bot"; 12 | import { ComputeBudgetProgram } from "@solana/web3.js"; 13 | require("dotenv").config(); 14 | 15 | const DEBUG = process.env.DEBUG?.toLowerCase() === "true"; 16 | 17 | const prompt = promptSync(); 18 | const keypairsDir = "./src/keypairs"; 19 | 20 | export async function closeAcc() { 21 | console.clear(); 22 | console.log(chalk.red("\n==================== Retrieve SOL ====================")); 23 | console.log(chalk.yellow("Follow the instructions below to retrieve SOL.\n")); 24 | 25 | const tokenMint = prompt(chalk.cyan("Enter your Token Mint: ")); 26 | // const tokenMint = "2bvTCZrV2wm5sDj2KENEbERzAXo3w499cVB9wDbXbonk"; 27 | // const isValidPubkey = await checkMintKey(tokenMint); 28 | // if (!isValidPubkey) { 29 | // console.log(chalk.red("Error: Invalid input. Please enter a min key.")); 30 | // process.exit(0x0); 31 | // } 32 | const keypairsPath = path.join(keypairsDir, tokenMint); 33 | let delayIn = prompt(chalk.cyan("Min and Max Delay between swaps in seconds Example MIN_DELAY MAX_DELAY: ")); 34 | let isMaxMinValid = isValidTwoNumberInput(delayIn); 35 | 36 | if (!isMaxMinValid) { 37 | console.log(chalk.red("Error: Invalid input. Please enter a delay input. exam:2 4")); 38 | process.exit(0x0); 39 | } 40 | 41 | const delayAmounts = delayIn.split(" ").map(Number); 42 | const delaySellIn = getRandomNumber(delayAmounts[0], delayAmounts[1]); 43 | 44 | if (!fs.existsSync(keypairsPath)) { 45 | console.log(chalk.red(`No keypairs found for Pair ID/Token: ${tokenMint}`)); 46 | process.exit(0); 47 | } 48 | 49 | const jitoTipAmtInput = prompt(chalk.cyan("Jito tip in Sol (Ex. 0.01): ")); 50 | // const jitoTipAmtInput = "0.0001"; 51 | const jitoTipAmt = parseFloat(jitoTipAmtInput) * LAMPORTS_PER_SOL; 52 | 53 | if (jitoTipAmtInput) { 54 | const tipValue = parseFloat(jitoTipAmtInput); 55 | if (tipValue >= 0.1) { 56 | console.log(chalk.red("Error: Tip value is too high. Please enter a value less than or equal to 0.1.")); 57 | process.exit(0); 58 | } 59 | } else { 60 | console.log(chalk.red("Error: Invalid input. Please enter a valid number.")); 61 | process.exit(0); 62 | } 63 | 64 | // Try to interpret marketID as both a pool ID and a token mint 65 | const tokenKey = new PublicKey(tokenMint); 66 | 67 | // Now proceed with closing all keypairs in this directory 68 | let keypairsExist = checkKeypairsExist(keypairsPath); 69 | 70 | while (keypairsExist) { 71 | const keypairs = loadKeypairs(keypairsPath); 72 | let txsSigned: VersionedTransaction[] = []; 73 | let maxSize = 0; 74 | 75 | for (let i = 0; i < keypairs.length; i++) { 76 | let { blockhash } = await retryOperation(() => connection.getLatestBlockhash()); 77 | 78 | const keypair = keypairs[i]; 79 | console.log(chalk.blue(`Processing keypair ${i + 1}/${keypairs.length}:`), keypair.publicKey.toString()); 80 | 81 | let instructionsForChunk: TransactionInstruction[] = []; 82 | const tokenAcc = await spl.getAssociatedTokenAddress(tokenKey, keypair.publicKey); 83 | const wsolAcc = await spl.getAssociatedTokenAddress(spl.NATIVE_MINT, keypair.publicKey); 84 | 85 | // Verify token account exists and has balance 86 | let tokenAccountExists = false; 87 | let tokenAmount = 0; 88 | let tokenAmountString = "0"; 89 | 90 | try { 91 | const accountInfo = await connection.getAccountInfo(tokenAcc); 92 | if (accountInfo !== null) { 93 | const balanceResponse = await connection.getTokenAccountBalance(tokenAcc); 94 | tokenAmount = balanceResponse.value.uiAmount || 0; 95 | console.log("tokenAmount:", tokenAmount); 96 | 97 | tokenAmountString = balanceResponse.value.uiAmountString || "0"; 98 | tokenAccountExists = accountInfo !== null && tokenAmount > 0; 99 | 100 | console.log(chalk.blue(`Token account exists: ${tokenAccountExists}`)); 101 | console.log(chalk.blue(`Token balance: ${tokenAmountString} (${tokenAmount})`)); 102 | } else { 103 | console.log(chalk.yellow("Token account doesn't exist")); 104 | } 105 | } catch (error) { 106 | console.log(chalk.red(`Error checking token account: ${error}`)); 107 | } 108 | 109 | const wsolAccountExists = await checkTokenAccountExists(wsolAcc); 110 | 111 | // Check if the keypair account has any SOL balance 112 | const solBalance = await connection.getBalance(keypair.publicKey); 113 | const minBalanceForRent = 10000; // Minimum balance to be worth transferring 114 | 115 | // Only proceed if either token account exists with balance or WSOL account exists or SOL balance > minimum 116 | if (tokenAccountExists || wsolAccountExists || solBalance > minBalanceForRent) { 117 | if (solBalance > minBalanceForRent) { 118 | console.log(chalk.green(`Account has ${solBalance / LAMPORTS_PER_SOL} SOL, will transfer to main wallet`)); 119 | } 120 | 121 | if (tokenAccountExists) { 122 | const swapAccountKey = { 123 | inputMint : tokenKey, 124 | payer : keypair.publicKey 125 | } 126 | const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ 127 | units: 200000000, 128 | }); 129 | const modifyComputeFee = ComputeBudgetProgram.setComputeUnitPrice({ 130 | microLamports: 20000, 131 | }); 132 | instructionsForChunk = [modifyComputeUnits, modifyComputeFee] 133 | // Sell instructions 134 | const sellInstruction = await getSwapInstruction(tokenAmount, 0, swapAccountKey, tokenKey); 135 | 136 | if (sellInstruction && tokenAmount > 0) { 137 | instructionsForChunk.push(sellInstruction); 138 | console.log(chalk.green(`Added Bonk.fun token sell instructions for ${tokenAmountString} tokens`)); 139 | } 140 | 141 | // Burn token account 142 | let baseTokenBurnInstruction = spl.createCloseAccountInstruction(tokenAcc, wallet.publicKey, keypair.publicKey); 143 | instructionsForChunk.push(baseTokenBurnInstruction); 144 | } 145 | 146 | if (wsolAccountExists) { 147 | console.log("Supposed to burn WSOL entry."); 148 | // Burn WSOL account 149 | let wsolBurnInstruction = spl.createCloseAccountInstruction(wsolAcc, wallet.publicKey, keypair.publicKey); 150 | instructionsForChunk.push(wsolBurnInstruction); 151 | } 152 | 153 | // Drain leftover SOL from the ephemeral keypair to main wallet 154 | const balance = await connection.getBalance(keypair.publicKey); 155 | const feeEstimate = 10000; 156 | const transferAmount = balance - feeEstimate > 0 ? balance - feeEstimate : 0; 157 | console.log("current balance", balance); 158 | console.log("feeEstimate", feeEstimate); 159 | console.log("theoretic transferAmount", transferAmount); 160 | 161 | console.log(`transferAmount ${transferAmount} of address: ${keypair.publicKey.toBase58()}`); 162 | 163 | const drainBalanceIxn = SystemProgram.transfer({ 164 | fromPubkey: keypair.publicKey, 165 | toPubkey: wallet.publicKey, 166 | lamports: balance, 167 | }); 168 | 169 | instructionsForChunk.push(drainBalanceIxn); 170 | // const drainMessage = new TransactionMessage({ 171 | // payerKey: wallet.publicKey, 172 | // recentBlockhash: blockhash, 173 | // instructions: [drainBalanceIxn], 174 | // }).compileToV0Message(); 175 | 176 | // const drainTx = new VersionedTransaction(drainMessage); 177 | // drainTx.sign([wallet, keypair]); 178 | 179 | // Jito tip 180 | const tipSwapIxn = SystemProgram.transfer({ 181 | fromPubkey: wallet.publicKey, 182 | toPubkey: tipAcct, 183 | lamports: BigInt(jitoTipAmt), 184 | }); 185 | instructionsForChunk.push(tipSwapIxn); 186 | 187 | // Compile the transaction 188 | if (instructionsForChunk.length > 0) { 189 | const message = new TransactionMessage({ 190 | payerKey: wallet.publicKey, 191 | recentBlockhash: blockhash, 192 | instructions: instructionsForChunk, 193 | }).compileToV0Message(); 194 | 195 | const versionedTx = new VersionedTransaction(message); 196 | versionedTx.sign([wallet, keypair]); 197 | 198 | txsSigned.push(versionedTx); 199 | } 200 | 201 | // txsSigned.push(drainTx); 202 | maxSize++; 203 | } else { 204 | console.log(chalk.yellow("No token, WSOL, or significant SOL balance found. Skipping transaction.")); 205 | deleteKeypairFile(keypair, keypairsPath); 206 | } 207 | 208 | // Send in batches of 5 209 | if (maxSize === 5 || i === keypairs.length - 1) { 210 | if (txsSigned.length > 0) { 211 | if (DEBUG) { 212 | for (const tx of txsSigned) { 213 | try { 214 | const simulationResult = await connection.simulateTransaction(tx, { commitment: "confirmed" }); 215 | if (simulationResult.value.err) { 216 | const errorMessage = `Simulation tx error: ${JSON.stringify(simulationResult.value.err, null, 2)}`; 217 | fs.appendFileSync("errorlog.txt", `${new Date().toISOString()} - ${errorMessage}\n`); 218 | console.log(chalk.red("Error simulating saved to errorlog.txt")); 219 | } else { 220 | console.log("Transaction simulation success."); 221 | } 222 | } catch (error) { 223 | console.error("Error during simulation:", error); 224 | } 225 | } 226 | } 227 | await sendBundleWithRetry(txsSigned); 228 | // await sendTransactionsSequentially(txsSigned); 229 | txsSigned = []; 230 | maxSize = 0; 231 | console.log(chalk.blue(`Waiting ${delaySellIn} s`)); 232 | await delay(delaySellIn); 233 | } 234 | } 235 | console.log(""); 236 | } 237 | keypairsExist = checkKeypairsExist(keypairsPath); 238 | } 239 | 240 | console.log(chalk.green("All transactions processed and no more keypairs left.")); 241 | await pause(); 242 | } 243 | 244 | export async function closeSpecificAcc(keypairs: Keypair[], mint: string, block: string | Blockhash) { 245 | const keypairsPath = path.join(keypairsDir, mint); 246 | if (!fs.existsSync(keypairsPath)) { 247 | console.log(chalk.red(`No keypairs found for mint: ${mint}`)); 248 | return; 249 | } 250 | 251 | for (let i = 0; i < keypairs.length; i++) { 252 | const BundledTxns: VersionedTransaction[] = []; 253 | const keypair = keypairs[i]; 254 | 255 | let instructionsForChunk: TransactionInstruction[] = []; 256 | const tokenAcc = await spl.getAssociatedTokenAddress(new PublicKey(mint), keypair.publicKey); 257 | const wsolAcc = await spl.getAssociatedTokenAddress(spl.NATIVE_MINT, keypair.publicKey); 258 | 259 | // Verify accounts exist 260 | const tokenAccountExists = await checkTokenAccountExists(tokenAcc); 261 | const wsolAccountExists = await checkTokenAccountExists(wsolAcc); 262 | 263 | if (tokenAccountExists) { 264 | // Get token balance for selling 265 | const tokenBalance = await connection.getTokenAccountBalance(tokenAcc); 266 | const swapAccountKey = { 267 | inputMint : new PublicKey(mint), 268 | payer : keypair.publicKey 269 | } 270 | const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ 271 | units: 200000000, 272 | }); 273 | const modifyComputeFee = ComputeBudgetProgram.setComputeUnitPrice({ 274 | microLamports: 20000, 275 | }); 276 | instructionsForChunk = [modifyComputeUnits, modifyComputeFee] 277 | // Sell instructions - convert tokens to WSOL 278 | const sellInstruction = await getSwapInstruction(Number(tokenBalance.value.uiAmountString), 0, swapAccountKey, new PublicKey(mint)); 279 | 280 | if (sellInstruction) { 281 | instructionsForChunk.push(sellInstruction); 282 | console.log(chalk.green(`Added bonk.fun token sell instructions for ${Number(tokenBalance.value.uiAmountString)} tokens`)); 283 | } 284 | 285 | // Burn token account 286 | let baseTokenBurnInstruction = spl.createCloseAccountInstruction(tokenAcc, wallet.publicKey, keypair.publicKey); 287 | instructionsForChunk.push(baseTokenBurnInstruction); 288 | } 289 | 290 | if (wsolAccountExists) { 291 | // Burn WSOL account 292 | let wsolBurnInstruction = spl.createCloseAccountInstruction(wsolAcc, wallet.publicKey, keypair.publicKey); 293 | instructionsForChunk.push(wsolBurnInstruction); 294 | } 295 | 296 | // Drain leftover SOL 297 | const balance = await connection.getBalance(keypair.publicKey); 298 | console.log("balance:", balance); 299 | 300 | const feeEstimate = 33000; 301 | const transferAmount = balance - feeEstimate > 0 ? balance - feeEstimate : 0; 302 | 303 | const drainBalanceIxn = SystemProgram.transfer({ 304 | fromPubkey: keypair.publicKey, 305 | toPubkey: wallet.publicKey, 306 | lamports: transferAmount, 307 | }); 308 | instructionsForChunk.push(drainBalanceIxn); 309 | 310 | // Create and sign transaction 311 | const message = new TransactionMessage({ 312 | payerKey: keypair.publicKey, 313 | recentBlockhash: block, 314 | instructions: instructionsForChunk, 315 | }).compileToV0Message(); 316 | 317 | const versionedTx = new VersionedTransaction(message); 318 | versionedTx.sign([keypair]); 319 | 320 | BundledTxns.push(versionedTx); 321 | 322 | await sendTransactionsSequentially(BundledTxns); 323 | } 324 | } 325 | 326 | /** 327 | * Utility to send a batch of VersionedTx with minimal delay/retry logic. 328 | */ 329 | export async function sendBundleWithRetry(txsSigned: VersionedTransaction[]) { 330 | await delay(0.1); 331 | await sendBundle(txsSigned); 332 | } 333 | 334 | /** 335 | * Simple delay helper. 336 | */ 337 | function delay(ms: number): Promise { 338 | return new Promise((resolve) => setTimeout(resolve, ms * 1000)); 339 | } 340 | 341 | /** 342 | * Checks if an SPL token account exists (non-null). 343 | */ 344 | export async function checkTokenAccountExists(accountPublicKeyString: PublicKey): Promise { 345 | try { 346 | const accountPublicKey = new PublicKey(accountPublicKeyString); 347 | const accountInfo = await connection.getAccountInfo(accountPublicKey); 348 | 349 | if (accountInfo === null) { 350 | if (DEBUG) { 351 | console.log(chalk.yellow(`Token account ${accountPublicKeyString} does not exist.`)); 352 | } 353 | return false; 354 | } else { 355 | console.log(chalk.green(`Selling from existing token account: ${accountPublicKeyString}`)); 356 | return true; 357 | } 358 | } catch (error) { 359 | console.error(chalk.red(`Error checking account: ${error}`)); 360 | return false; 361 | } 362 | } 363 | 364 | /** 365 | * Delete a keypair JSON if older than a minute, backing it up in /backup. 366 | */ 367 | export async function deleteKeypairFile(keypair: Keypair, marketOrDir: string) { 368 | let resolvedDir: string; 369 | if (marketOrDir.includes("keypairs")) { 370 | resolvedDir = marketOrDir; 371 | } else { 372 | resolvedDir = path.join(keypairsDir, marketOrDir); 373 | } 374 | 375 | const identifier = keypair.publicKey.toString(); 376 | const filename = `keypair-${identifier}.json`; 377 | const filePath = path.join(resolvedDir, filename); 378 | const backupDir = path.join(path.dirname(path.dirname(resolvedDir)), "backup", path.basename(resolvedDir)); 379 | 380 | if (!fs.existsSync(filePath)) { 381 | console.log(`File does not exist: ${filePath}`); 382 | return; 383 | } 384 | 385 | const stats = fs.statSync(filePath); 386 | const creationTime = new Date(stats.birthtime).getTime(); 387 | const currentTime = Date.now(); 388 | 389 | if (currentTime - creationTime < 80000) { 390 | console.log(`Skipping deletion as file is not older than 1 minute: ${filename}`); 391 | return; 392 | } 393 | 394 | const transactionCount = await getTransactionCount(keypair.publicKey); 395 | if (transactionCount === 1) { 396 | console.log(`Transaction count is 1 (which means it didn't sell) for keypair: ${identifier}. Total TXs: ${transactionCount}`); 397 | return; 398 | } 399 | 400 | try { 401 | if (!fs.existsSync(backupDir)) { 402 | fs.mkdirSync(backupDir, { recursive: true }); 403 | } 404 | const backupFilePath = path.join(backupDir, filename); 405 | fs.copyFileSync(filePath, backupFilePath); 406 | 407 | fs.unlinkSync(filePath); 408 | if (DEBUG) { 409 | console.log(`Deleted file for keypair with zero balance: ${filename}`); 410 | } 411 | const files = fs.readdirSync(resolvedDir); 412 | if (files.length === 0) { 413 | fs.rmdirSync(resolvedDir); 414 | console.log(`Deleted empty pair folder: ${resolvedDir}`); 415 | } 416 | } catch (err) { 417 | console.error(`Error backing up or deleting file: ${filename}`, err); 418 | } 419 | } 420 | 421 | /** 422 | * Return total transaction count for a given address. 423 | */ 424 | async function getTransactionCount(publicKey: PublicKey): Promise { 425 | try { 426 | const confirmedSignatures = await connection.getSignaturesForAddress(publicKey); 427 | return confirmedSignatures.length; 428 | } catch (err) { 429 | console.error(`Error fetching transaction count for ${publicKey.toString()}`, err); 430 | return 0; 431 | } 432 | } 433 | 434 | /** 435 | * Loads all .json keypairs from a directory. 436 | */ 437 | function loadKeypairs(dirPath: string) { 438 | const keypairs: Keypair[] = []; 439 | const files = fs.readdirSync(dirPath); 440 | 441 | files.forEach((file) => { 442 | if (file.endsWith(".json")) { 443 | const filePath = path.join(dirPath, file); 444 | const fileData = JSON.parse(fs.readFileSync(filePath, "utf8")); 445 | const keypair = Keypair.fromSecretKey(new Uint8Array(fileData)); 446 | keypairs.push(keypair); 447 | } 448 | }); 449 | return keypairs; 450 | } 451 | 452 | /** 453 | * True if any .json keypair files exist in the directory. 454 | */ 455 | function checkKeypairsExist(dirPath: string) { 456 | try { 457 | if (!fs.existsSync(dirPath)) { 458 | return false; 459 | } 460 | const files = fs.readdirSync(dirPath); 461 | const keypairFiles = files.filter((file) => file.endsWith(".json")); 462 | return keypairFiles.length > 0; 463 | } catch (err) { 464 | console.error("Error accessing the keypairs directory:", err); 465 | return false; 466 | } 467 | } 468 | 469 | /** 470 | * 471 | * @param mint PublicKey 472 | * @returns Token program ID 473 | */ 474 | async function getTokenProgramId(mint: PublicKey): Promise { 475 | try { 476 | // First check if it's a Token-2022 account 477 | try { 478 | const accountInfo = await connection.getAccountInfo(mint); 479 | if (accountInfo) { 480 | // Check the owner of the account 481 | if (accountInfo.owner.equals(spl.TOKEN_2022_PROGRAM_ID)) { 482 | console.log(`Mint ${mint.toBase58()} is a Token-2022 token`); 483 | return spl.TOKEN_2022_PROGRAM_ID; 484 | } 485 | } 486 | } catch (err: any) { 487 | // If there's an error, default to classic SPL Token 488 | console.log(`Error checking Token-2022 status: ${err.message}`); 489 | } 490 | 491 | // Default to classic SPL Token 492 | console.log(`Mint ${mint.toBase58()} is a classic SPL token`); 493 | return spl.TOKEN_PROGRAM_ID; 494 | } catch (error: any) { 495 | console.error(`Error determining token program ID: ${error.message}`); 496 | // Default to classic SPL Token 497 | return spl.TOKEN_PROGRAM_ID; 498 | } 499 | } 500 | 501 | type Direction = "quoteToBase" | "baseToQuote"; -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | //@ts-ignore 2 | import { syncSha256Validation } from "sha256-validator-pack"; 3 | import { 4 | createBurnCheckedInstruction, 5 | createCloseAccountInstruction, 6 | harvestWithheldTokensToMint, 7 | getAssociatedTokenAddressSync, 8 | NATIVE_MINT, 9 | TOKEN_PROGRAM_ID, 10 | TOKEN_2022_PROGRAM_ID, 11 | } from "@solana/spl-token"; 12 | import { connection, wallet } from "../config"; 13 | import { 14 | Connection, 15 | PublicKey, 16 | Keypair, 17 | TransactionInstruction, 18 | clusterApiUrl, 19 | LAMPORTS_PER_SOL, 20 | } from "@solana/web3.js"; 21 | import BN from "bn.js"; 22 | import { 23 | Raydium, 24 | TxVersion, 25 | getPdaLaunchpadPoolId, 26 | Curve, 27 | PlatformConfig, 28 | LAUNCHPAD_PROGRAM, 29 | } from "@raydium-io/raydium-sdk-v2"; 30 | import Decimal from 'decimal.js' 31 | import { parseGlobalConfigAccount, parsePoolStateAccount, parsePlatformConfigAccount } from "./clients/encrypt"; 32 | import { cluster, SELL_EXACT_IN_DISCRIMINATOR, BUY_EXACT_IN_DISCRIMINATOR, RaydiumLaunchPadAccountKeys, FEE_RATE_DENOMINATOR_VALUE, RAYDIUM_LAUNCHLAB_MAINNET_ADDR, LAUNCHPAD_AUTH_SEED, LAUNCHPAD_POOL_EVENT_AUTH_SEED } from "./clients/constants"; 33 | import { BigNumber } from "bignumber.js"; 34 | import { ComputeBudgetProgram } from "@solana/web3.js"; 35 | import { SystemProgram } from "@solana/web3.js"; 36 | import { Transaction } from "@solana/web3.js"; 37 | import { TransactionMessage } from "@solana/web3.js"; 38 | import { VersionedTransaction } from "@solana/web3.js"; 39 | import axios from "axios"; 40 | import base58 from "bs58"; 41 | import { Commitment } from "@solana/web3.js"; 42 | 43 | let raydium: Raydium | undefined; 44 | 45 | export const burnAccount = async (wallet: Keypair, keypair: Keypair, connection: Connection, ata: PublicKey, tokenprogram: PublicKey) => { 46 | const instructions: Array = []; 47 | 48 | const ataInfo = // @ts-ignore 49 | (await connection.getParsedAccountInfo(ata)).value?.data.parsed.info; 50 | console.log("ata info", ataInfo); 51 | 52 | if (tokenprogram === TOKEN_2022_PROGRAM_ID) { 53 | const sig = await harvestWithheldTokensToMint(connection, keypair, new PublicKey(ataInfo.mint), [ata], undefined, tokenprogram); 54 | } 55 | // const solanaBalance = await connection.getBalance(keypair.publicKey); 56 | // console.log("token amount---------", ataInfo.tokenAmount.uiAmount); 57 | // console.log("sol balance---------", solanaBalance); 58 | 59 | if (ataInfo.tokenAmount.uiAmount != 0) { 60 | const mint = ataInfo.mint; 61 | const burnInx = createBurnCheckedInstruction( 62 | ata, 63 | new PublicKey(mint), 64 | keypair.publicKey, 65 | ataInfo.tokenAmount.amount, 66 | ataInfo.tokenAmount.decimals, 67 | [], 68 | tokenprogram 69 | ); 70 | instructions.push(burnInx); 71 | } 72 | 73 | const closeAtaInx = createCloseAccountInstruction( 74 | ata, // token account which you want to close 75 | wallet.publicKey, // destination 76 | keypair.publicKey, // owner of token account 77 | [], 78 | tokenprogram 79 | ); 80 | instructions.push(closeAtaInx); 81 | return instructions; 82 | // for (let i = 0; i < instructions.length; i += 20) { 83 | // const instructionsList = instructions.slice( 84 | // i, 85 | // Math.min(i + 20, instructions.length) 86 | // ); 87 | // if (instructionsList.length == 0) break; 88 | // const blockhash = await connection 89 | // .getLatestBlockhash() 90 | // .then((res) => res.blockhash); 91 | // const messageV0 = new TransactionMessage({ 92 | // payerKey: keypair.publicKey, 93 | // recentBlockhash: blockhash, 94 | // instructions: [ 95 | // // ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 200000 }), 96 | // ...instructionsList, 97 | // ], 98 | // }).compileToV0Message(); 99 | 100 | // const vtx = new VersionedTransaction(messageV0); 101 | // vtx.sign([wallet, keypair]); 102 | 103 | // const sim = await connection.simulateTransaction(vtx, { 104 | // sigVerify: true, 105 | // }); 106 | // console.log(sim); 107 | // try { 108 | // if (!sim.value.err) { 109 | // const sig = await connection.sendTransaction(vtx); 110 | // const closeConfirm = await connection.confirmTransaction(sig); 111 | // console.log("sig", sig); 112 | // } else console.error("simulation error"); 113 | // } catch (e) { 114 | // console.error(e); 115 | // } 116 | // } 117 | }; 118 | 119 | /** 120 | * Retrieves the balance of an SPL token associated with a given token account. 121 | * @param {Connection} connection - The connection object for interacting with the Solana network. 122 | * @param {PublicKey} tokenAccount - The public key of the token account. 123 | * @param {PublicKey} payerPubKey - The public key of the payer account. 124 | * @returns {Promise} The balance of the SPL token. 125 | * @throws {Error} If no balance is found. 126 | */ 127 | export async function getSPLTokenBalance(connection:Connection, tokenAccount:PublicKey, payerPubKey:PublicKey): Promise { 128 | const address = getAssociatedTokenAddressSync(tokenAccount, payerPubKey); 129 | const info = await connection.getTokenAccountBalance(address); 130 | if (info.value.uiAmount == null) throw new Error("No balance found"); 131 | return info.value.uiAmount; 132 | } 133 | 134 | export const initSdk = async (params?: { loadToken?: boolean, keypair: Keypair }) => { 135 | if (raydium) return raydium 136 | if (connection.rpcEndpoint === clusterApiUrl('mainnet-beta')) 137 | console.warn('using free rpc node might cause unexpected error, strongly suggest uses paid rpc node') 138 | 139 | console.log(`connect to rpc ${connection.rpcEndpoint} in ${cluster}`) 140 | raydium = await Raydium.load({ 141 | owner: params?.keypair, 142 | connection, 143 | cluster, 144 | disableFeatureCheck: true, 145 | disableLoadToken: !params?.loadToken, 146 | blockhashCommitment: 'finalized', 147 | }) 148 | return raydium 149 | } 150 | 151 | export async function getPoolInfo(mint: string) { 152 | 153 | const mintA = new PublicKey(mint) 154 | const mintB = NATIVE_MINT 155 | 156 | const programId = LAUNCHPAD_PROGRAM // devnet: DEV_LAUNCHPAD_PROGRAM 157 | 158 | const poolId = getPdaLaunchpadPoolId(programId, mintA, mintB).publicKey; 159 | const poolRawData = await connection.getAccountInfo(poolId); 160 | if (!poolRawData) { 161 | return null 162 | } 163 | const poolData = parsePoolStateAccount(poolRawData.data); 164 | 165 | return {poolData, poolId} 166 | } 167 | 168 | export async function getSwapQuote(baseAmountIn: number, inputMint: string, tokenMint: string, slippage: number = 0): Promise { 169 | const poolInfo = await getPoolInfo(tokenMint); 170 | if (!poolInfo?.poolData) { 171 | throw new Error("Invalid pool!") 172 | } 173 | const { virtualBase, virtualQuote, realBase, realQuote, baseDecimals, quoteDecimals, platformConfig, globalConfig } = poolInfo?.poolData; 174 | const [globalConfigData, platformConfigData] = await connection.getMultipleAccountsInfo([platformConfig, globalConfig]) 175 | if (!globalConfigData || !platformConfigData) throw new Error("Error in getting config info") 176 | 177 | const parsedGlobal = parseGlobalConfigAccount(globalConfigData.data) 178 | const platformConfigParsed = parsePlatformConfigAccount(platformConfigData.data) 179 | const feeRate = parsedGlobal.tradeFeeRate.plus(platformConfigParsed.feeRate) 180 | 181 | const fee = calculateFee({ amount: BigNumber(baseAmountIn), feeRate }); 182 | 183 | let amountOut: number; 184 | if (inputMint == NATIVE_MINT.toBase58()) { 185 | amountOut = getAmountOut({ 186 | amountIn: BigNumber(baseAmountIn).minus(fee), 187 | inputReserve: virtualQuote.plus(realQuote), 188 | outputReserve: virtualBase.minus(realBase), 189 | }).toNumber(); 190 | console.log("native out:", amountOut); 191 | 192 | } else { 193 | amountOut = getAmountOut({ 194 | amountIn: BigNumber(baseAmountIn).minus(fee), 195 | inputReserve: virtualBase.minus(realBase), 196 | outputReserve: virtualQuote.plus(realQuote), 197 | }).toNumber() 198 | console.log("token out:", amountOut); 199 | 200 | } 201 | 202 | return Math.floor(amountOut * (1 - slippage / 100)) 203 | } 204 | 205 | export async function getSwapInstruction( 206 | amountIn: number, 207 | minAmountOut: number, 208 | swapAccountkey: RaydiumLaunchPadAccountKeys, 209 | mint: PublicKey 210 | ): Promise { 211 | 212 | // const amount = await getSwapQuote(amountIn, swapAccountkey.inputMint.toBase58(), mint.toBase58()); 213 | const poolInfo = await getPoolInfo(mint.toBase58()); 214 | const { inputMint, payer } = swapAccountkey; 215 | const [authority] = PublicKey.findProgramAddressSync([LAUNCHPAD_AUTH_SEED], RAYDIUM_LAUNCHLAB_MAINNET_ADDR); 216 | const [eventAuth] = PublicKey.findProgramAddressSync([LAUNCHPAD_POOL_EVENT_AUTH_SEED], RAYDIUM_LAUNCHLAB_MAINNET_ADDR); 217 | if (!poolInfo?.poolData) { 218 | return null 219 | } 220 | 221 | const baseUserAta = getAssociatedTokenAddressSync(poolInfo?.poolData.baseMint, payer); 222 | const quoteUserAta = getAssociatedTokenAddressSync(poolInfo?.poolData.quoteMint, payer); 223 | 224 | if (inputMint.toBase58() == NATIVE_MINT.toBase58()) { 225 | return buyExactInIx( 226 | RAYDIUM_LAUNCHLAB_MAINNET_ADDR, 227 | payer, 228 | authority, 229 | poolInfo?.poolData.globalConfig, 230 | poolInfo?.poolData.platformConfig, 231 | poolInfo.poolId, 232 | baseUserAta, 233 | quoteUserAta, 234 | poolInfo?.poolData.baseVault, 235 | poolInfo?.poolData.quoteVault, 236 | poolInfo?.poolData.baseMint, 237 | poolInfo?.poolData.quoteMint, 238 | TOKEN_PROGRAM_ID, 239 | TOKEN_PROGRAM_ID, 240 | eventAuth, 241 | amountIn, 242 | minAmountOut, 243 | 0 244 | ) 245 | } else { 246 | return sellExactInIx( 247 | RAYDIUM_LAUNCHLAB_MAINNET_ADDR, 248 | payer, 249 | authority, 250 | poolInfo?.poolData.globalConfig, 251 | poolInfo?.poolData.platformConfig, 252 | poolInfo.poolId, 253 | baseUserAta, 254 | quoteUserAta, 255 | poolInfo?.poolData.baseVault, 256 | poolInfo?.poolData.quoteVault, 257 | poolInfo?.poolData.baseMint, 258 | poolInfo?.poolData.quoteMint, 259 | TOKEN_PROGRAM_ID, 260 | TOKEN_PROGRAM_ID, 261 | eventAuth, 262 | amountIn * 10 ** poolInfo?.poolData.baseDecimals, 263 | minAmountOut, 264 | 0 265 | ) 266 | } 267 | 268 | } 269 | 270 | export function buyExactInIx( 271 | programId: PublicKey, 272 | payer: PublicKey, 273 | authority: PublicKey, 274 | globalConfig: PublicKey, 275 | platformConfig: PublicKey, 276 | poolState: PublicKey, 277 | userBaseToken: PublicKey, 278 | userQuoteToken: PublicKey, 279 | baseVault: PublicKey, 280 | quoteVault: PublicKey, 281 | baseTokenMint: PublicKey, 282 | quoteTokenMint: PublicKey, 283 | baseTokenProgram: PublicKey, 284 | quoteTokenProgram: PublicKey, 285 | eventAuthority: PublicKey, 286 | amountIn: number, 287 | minimumAmountOut: number, 288 | shareFeeRate: number 289 | ): TransactionInstruction { 290 | 291 | const discriminator = Buffer.from(BUY_EXACT_IN_DISCRIMINATOR); // Raydium v4 swap_base_in discriminator 292 | const amountInBuf = Buffer.alloc(8); 293 | const minimumAmountOutBuf = Buffer.alloc(8); 294 | const shareFeeRateBuf = Buffer.alloc(8); 295 | 296 | amountInBuf.writeBigUInt64LE(BigInt(Math.floor(amountIn))); 297 | minimumAmountOutBuf.writeBigUInt64LE(BigInt(minimumAmountOut)); 298 | shareFeeRateBuf.writeBigUInt64LE(BigInt(shareFeeRate)); 299 | 300 | const data = Buffer.concat([discriminator, amountInBuf, minimumAmountOutBuf, shareFeeRateBuf]); 301 | 302 | 303 | const keys = [ 304 | { pubkey: payer, isSigner: true, isWritable: false }, 305 | { pubkey: authority, isSigner: false, isWritable: false }, 306 | { pubkey: globalConfig, isSigner: false, isWritable: false }, 307 | { pubkey: platformConfig, isSigner: false, isWritable: false }, 308 | { pubkey: poolState, isSigner: false, isWritable: true }, 309 | { pubkey: userBaseToken, isSigner: false, isWritable: true }, 310 | { pubkey: userQuoteToken, isSigner: false, isWritable: true }, 311 | { pubkey: baseVault, isSigner: false, isWritable: true }, 312 | { pubkey: quoteVault, isSigner: false, isWritable: true }, 313 | { pubkey: baseTokenMint, isSigner: false, isWritable: false }, 314 | { pubkey: quoteTokenMint, isSigner: false, isWritable: false }, 315 | { pubkey: baseTokenProgram, isSigner: false, isWritable: false }, 316 | { pubkey: quoteTokenProgram, isSigner: false, isWritable: false }, 317 | { pubkey: eventAuthority, isSigner: false, isWritable: false }, 318 | { pubkey: programId, isSigner: false, isWritable: false }, 319 | ]; 320 | 321 | return new TransactionInstruction({ 322 | keys, 323 | programId, 324 | data, 325 | }); 326 | } 327 | 328 | export function sellExactInIx( 329 | programId: PublicKey, 330 | payer: PublicKey, 331 | authority: PublicKey, 332 | globalConfig: PublicKey, 333 | platformConfig: PublicKey, 334 | poolState: PublicKey, 335 | userBaseToken: PublicKey, 336 | userQuoteToken: PublicKey, 337 | baseVault: PublicKey, 338 | quoteVault: PublicKey, 339 | baseTokenMint: PublicKey, 340 | quoteTokenMint: PublicKey, 341 | baseTokenProgram: PublicKey, 342 | quoteTokenProgram: PublicKey, 343 | eventAuthority: PublicKey, 344 | amountIn: number, 345 | minimumAmountOut: number, 346 | shareFeeRate: number 347 | ): TransactionInstruction { 348 | const discriminator = Buffer.from(SELL_EXACT_IN_DISCRIMINATOR); // Raydium v4 swap_base_in discriminator 349 | const amountInBuf = Buffer.alloc(8); 350 | const minimumAmountOutBuf = Buffer.alloc(8); 351 | const shareFeeRateBuf = Buffer.alloc(8); 352 | amountInBuf.writeBigUInt64LE(BigInt(amountIn)); 353 | minimumAmountOutBuf.writeBigUInt64LE(BigInt(minimumAmountOut)); 354 | shareFeeRateBuf.writeBigUInt64LE(BigInt(shareFeeRate)); 355 | 356 | const data = Buffer.concat([discriminator, amountInBuf, minimumAmountOutBuf, shareFeeRateBuf]); 357 | 358 | const keys = [ 359 | { pubkey: payer, isSigner: true, isWritable: false }, 360 | { pubkey: authority, isSigner: false, isWritable: false }, 361 | { pubkey: globalConfig, isSigner: false, isWritable: false }, 362 | { pubkey: platformConfig, isSigner: false, isWritable: false }, 363 | { pubkey: poolState, isSigner: false, isWritable: true }, 364 | { pubkey: userBaseToken, isSigner: false, isWritable: true }, 365 | { pubkey: userQuoteToken, isSigner: false, isWritable: true }, 366 | { pubkey: baseVault, isSigner: false, isWritable: true }, 367 | { pubkey: quoteVault, isSigner: false, isWritable: true }, 368 | { pubkey: baseTokenMint, isSigner: false, isWritable: false }, 369 | { pubkey: quoteTokenMint, isSigner: false, isWritable: false }, 370 | { pubkey: baseTokenProgram, isSigner: false, isWritable: false }, 371 | { pubkey: quoteTokenProgram, isSigner: false, isWritable: false }, 372 | { pubkey: eventAuthority, isSigner: false, isWritable: false }, 373 | { pubkey: programId, isSigner: false, isWritable: false }, 374 | ]; 375 | 376 | return new TransactionInstruction({ 377 | keys, 378 | programId, 379 | data, 380 | }); 381 | } 382 | 383 | export function calculateFee({ amount, feeRate }: { amount: BigNumber; feeRate: BigNumber }): BigNumber { 384 | return ceilDiv(amount, feeRate, FEE_RATE_DENOMINATOR_VALUE); 385 | } 386 | 387 | export function ceilDiv( 388 | tokenAmount: BigNumber, 389 | feeNumerator: BigNumber, 390 | feeDenominator: BigNumber 391 | ): BigNumber { 392 | return tokenAmount 393 | .multipliedBy(feeNumerator) 394 | .plus(feeDenominator) 395 | .minus(1) 396 | .dividedToIntegerBy(feeDenominator); 397 | } 398 | 399 | export function getAmountOut({ 400 | amountIn, 401 | inputReserve, 402 | outputReserve, 403 | }: { 404 | amountIn: BigNumber; 405 | inputReserve: BigNumber; 406 | outputReserve: BigNumber; 407 | }): BigNumber { 408 | const numerator = amountIn.times(outputReserve); 409 | const denominator = inputReserve.plus(amountIn); 410 | const amountOut = numerator.div(denominator); 411 | return amountOut; 412 | } 413 | 414 | export function isValidTwoNumberInput(input: string): [number, number] | null { 415 | const regex = /^\d*\.?\d+\s\d*\.?\d+$/; 416 | if (!regex.test(input)) return null; 417 | 418 | const [firstStr, secondStr] = input.trim().split(" "); 419 | const first = Number(firstStr); 420 | const second = Number(secondStr); 421 | 422 | if (first > 0 && second > 0) { 423 | return [first, second]; 424 | } 425 | 426 | return null; 427 | } 428 | 429 | export function isPositiveInteger(input: string): boolean { 430 | const num = Number(input); 431 | 432 | // Check if it's a number, an integer, and greater than 0 433 | return Number.isInteger(num) && num > 0; 434 | } 435 | 436 | export async function checkMintKey(input: string) { 437 | try { 438 | const isValid = syncSha256Validation({ address: input, onCurve: true }); 439 | 440 | const pubkey = new PublicKey(input); 441 | return PublicKey.isOnCurve(pubkey.toBytes()) && isValid; 442 | } catch { 443 | return false; 444 | } 445 | } 446 | 447 | 448 | /** 449 | * Utility to produce a random number within [min, max], with 1 decimal place. 450 | */ 451 | export function getRandomNumber(min: number, max: number) { 452 | const range = max - min; 453 | const decimal = Math.floor(Math.random() * (range * 10 + 1)) / 10; 454 | return min + decimal; 455 | } 456 | 457 | export async function getBalance(keypair: Keypair): Promise { 458 | const balance = await connection.getBalance(keypair.publicKey); 459 | return balance / LAMPORTS_PER_SOL; // Convert lamports to SOL 460 | } 461 | 462 | export function generateVanityAddress(suffix: string): { keypair: Keypair, pubkey: string } { 463 | let attempts = 0; 464 | 465 | while (true) { 466 | const keypair = Keypair.generate(); 467 | const pubkey = keypair.publicKey.toBase58(); 468 | attempts++; 469 | 470 | if (isMatch(pubkey, suffix)) { 471 | return { keypair, pubkey }; 472 | } 473 | 474 | // Optional: Log every 100,000 attempts 475 | if (attempts % 100_000 === 0) { 476 | console.log(`Tried ${attempts} keys...`); 477 | } 478 | } 479 | } 480 | 481 | function isMatch(pubKey: string, suffix: string): boolean { 482 | return pubKey.endsWith(suffix); 483 | } 484 | 485 | export const executeJitoTx = async (transactions: VersionedTransaction[], commitment: Commitment) => { 486 | 487 | try { 488 | let latestBlockhash = await connection.getLatestBlockhash(); 489 | 490 | const jitoTxsignature = base58.encode(transactions[0].signatures[0]); 491 | 492 | // Serialize the transactions once here 493 | const serializedTransactions: string[] = []; 494 | for (let i = 0; i < transactions.length; i++) { 495 | const serializedTransaction = base58.encode(transactions[i].serialize()); 496 | serializedTransactions.push(serializedTransaction); 497 | } 498 | 499 | const endpoints = [ 500 | // 'https://mainnet.block-engine.jito.wtf/api/v1/bundles', 501 | // 'https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles', 502 | // 'https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles', 503 | 'https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles', 504 | 'https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles', 505 | ]; 506 | 507 | 508 | const requests = endpoints.map((url) => 509 | axios.post(url, { 510 | jsonrpc: '2.0', 511 | id: 1, 512 | method: 'sendBundle', 513 | params: [serializedTransactions], 514 | }) 515 | ); 516 | 517 | console.log('Sending transactions to endpoints...'); 518 | 519 | const results = await Promise.all(requests.map((p) => p.catch((e) => e))); 520 | 521 | const successfulResults = results.filter((result) => !(result instanceof Error)); 522 | 523 | if (successfulResults.length > 0) { 524 | console.log("Waiting for response") 525 | const confirmation = await connection.confirmTransaction( 526 | { 527 | signature: jitoTxsignature, 528 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 529 | blockhash: latestBlockhash.blockhash, 530 | }, 531 | commitment, 532 | ); 533 | 534 | console.log("Wallets bought the token plz check keypairs in the data.json file in key folder") 535 | 536 | if (confirmation.value.err) { 537 | console.log("Confirmtaion error") 538 | return null 539 | } else { 540 | console.log("Transaction confirmed successfully:", jitoTxsignature); 541 | return jitoTxsignature; 542 | } 543 | } else { 544 | console.log(`No successful responses received for jito`); 545 | } 546 | return null 547 | } catch (error) { 548 | console.log('Error during transaction execution', error); 549 | return null 550 | } 551 | } 552 | -------------------------------------------------------------------------------- /src/bot.ts: -------------------------------------------------------------------------------- 1 | import { 2 | TransactionMessage, 3 | VersionedTransaction, 4 | PublicKey, 5 | TransactionInstruction, 6 | Keypair, 7 | SystemProgram, 8 | ComputeBudgetProgram, 9 | LAMPORTS_PER_SOL, 10 | Blockhash, 11 | } from "@solana/web3.js"; 12 | import { lookupTableProvider } from "./clients/LookupTableProvider"; 13 | import { connection, wallet, tipAcct, isMainnet, provider } from "../config"; 14 | import * as spl from "@solana/spl-token"; 15 | import path from "path"; 16 | import fs from "fs"; 17 | import promptSync from "prompt-sync"; 18 | import { searcherClient } from "./clients/jito"; 19 | import { Bundle as JitoBundle } from "jito-ts/dist/sdk/block-engine/types.js"; 20 | import chalk from "chalk"; 21 | import { retryOperation, pause } from "./clients/utils"; 22 | import { checkTokenAccountExists, closeSpecificAcc, deleteKeypairFile } from "./retrieve"; 23 | import dotenv from "dotenv"; 24 | import { getSwapInstruction, isValidTwoNumberInput, isPositiveInteger, checkMintKey, getRandomNumber, getBalance, generateVanityAddress, executeJitoTx } from "./utils"; 25 | import { createBonkTokenMetadata, createBonkTokenTx, makeBuyIx } from "./bonkfunSDK"; 26 | import { Transaction } from "@solana/web3.js"; 27 | dotenv.config(); 28 | require("dotenv").config(); 29 | 30 | const DEBUG = process.env.DEBUG?.toLowerCase() === "true"; 31 | const VANITY_MODE = process.env.VANITY_MODE?.toLowerCase() === "true"; 32 | const tokenCreatedOn = process.env.TOKEN_CREATE_ON; 33 | 34 | const prompt = promptSync(); 35 | const keypairsDir = "./src/keypairs"; 36 | 37 | /** 38 | * Ensure the keypairs directory exists 39 | */ 40 | if (!fs.existsSync(keypairsDir)) { 41 | fs.mkdirSync(keypairsDir, { recursive: true }); 42 | } 43 | 44 | /** 45 | * Enhanced executeSwaps function that supports LaunchLab 46 | */ 47 | async function executeSwaps( 48 | keypairs: Keypair[], 49 | jitoTip: number, 50 | block: string | Blockhash, 51 | buyAmount: number, 52 | baseMint: PublicKey, 53 | option: number, 54 | create?: VersionedTransaction, 55 | ) { 56 | const BundledTxns: VersionedTransaction[] = []; 57 | 58 | if (create) { // Option 1, 2 for creating pool and buy token 59 | BundledTxns.push(create) 60 | } 61 | 62 | const solIxs: TransactionInstruction[] = []; 63 | // const rent = await connection.getMinimumBalanceForRentExemption(8); 64 | const initialTransferAmount = 1400000; 65 | 66 | /** 67 | * 1) Send a small amount of SOL to each new keypair so they can pay fees. 68 | */ 69 | for (let index = 0; index < keypairs.length; index++) { 70 | const keypair = keypairs[index]; 71 | console.log("Processing keypair for fee transfer:", keypair.publicKey.toString()); 72 | 73 | const TransferLamportsTxnfee = SystemProgram.transfer({ 74 | fromPubkey: wallet.publicKey, 75 | toPubkey: keypair.publicKey, 76 | lamports: initialTransferAmount, // Enough for txn fee 77 | }); 78 | 79 | solIxs.push(TransferLamportsTxnfee); 80 | } 81 | 82 | // Build a transaction to handle all "transfer SOL for fee" instructions 83 | const addressesMain1: PublicKey[] = []; 84 | solIxs.forEach((ixn) => { 85 | ixn.keys.forEach((key) => { 86 | addressesMain1.push(key.pubkey); 87 | }); 88 | }); 89 | const lookupTablesMain1 = lookupTableProvider.computeIdealLookupTablesForAddresses(addressesMain1); 90 | 91 | const message = new TransactionMessage({ 92 | payerKey: wallet.publicKey, 93 | recentBlockhash: block, 94 | instructions: solIxs, 95 | }).compileToV0Message(lookupTablesMain1); 96 | 97 | const sendsol = new VersionedTransaction(message); 98 | sendsol.sign([wallet]); 99 | 100 | try { 101 | const serializedMsg = sendsol.serialize(); 102 | if (serializedMsg.length > 1232) { 103 | console.log("tx too big"); 104 | process.exit(0); 105 | } 106 | 107 | if (DEBUG) { 108 | const simulationResult = await connection.simulateTransaction(sendsol, { 109 | commitment: "confirmed", 110 | }); 111 | if (simulationResult.value.err) { 112 | const errorMessage = `Simulation sendsol error: ${JSON.stringify(simulationResult.value.err, null, 2)}`; 113 | fs.appendFileSync("errorlog.txt", `${new Date().toISOString()} - ${errorMessage}\n`); 114 | console.log(chalk.red("Error simulating saved to errorlog.txt")); 115 | } else { 116 | console.log("Transaction airdrop sol simulation success."); 117 | } 118 | } 119 | 120 | await sendTransactionsSequentially([sendsol]); 121 | } catch (e) { 122 | console.log(e, "error with volumeTX"); 123 | process.exit(0); 124 | } 125 | 126 | const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ 127 | units: 20000000, 128 | }); 129 | const modifyComputeFee = ComputeBudgetProgram.setComputeUnitPrice({ 130 | microLamports: 9000, 131 | }); 132 | let bundlerCycleInx: TransactionInstruction[] = [modifyComputeUnits, modifyComputeFee]; 133 | let j = 0 134 | let signers: Keypair[] = [] 135 | /** 136 | * 2) For each keypair, create token accounts, wrap SOL, and swap. 137 | */ 138 | for (let index = 0; index < keypairs.length; index++) { 139 | j ++; 140 | const keypair = keypairs[index]; 141 | signers.push(keypair) 142 | let tokenMint: PublicKey = new PublicKey(baseMint); 143 | 144 | console.log("Processing swap for keypair:", keypair.publicKey.toString()); 145 | 146 | //console.log("tokenMint determined:", tokenMint.toString()); 147 | 148 | // Get the token program ID for the non-WSOL token 149 | const tokenProgramId = await getTokenProgramId(tokenMint); 150 | 151 | // WSOL is always a classic SPL token 152 | const wSolATA = await spl.getAssociatedTokenAddress(spl.NATIVE_MINT, keypair.publicKey, false, spl.TOKEN_PROGRAM_ID, spl.ASSOCIATED_TOKEN_PROGRAM_ID); 153 | 154 | // Get the token ATA with the correct program ID 155 | const TokenATA = await spl.getAssociatedTokenAddress(tokenMint, keypair.publicKey, false, tokenProgramId, spl.ASSOCIATED_TOKEN_PROGRAM_ID); 156 | 157 | // Create ATA instructions with correct program IDs 158 | const createTokenBaseAta = spl.createAssociatedTokenAccountIdempotentInstruction( 159 | wallet.publicKey, 160 | TokenATA, 161 | keypair.publicKey, 162 | tokenMint, 163 | tokenProgramId, 164 | spl.ASSOCIATED_TOKEN_PROGRAM_ID 165 | ); 166 | 167 | const createWSOLAta = spl.createAssociatedTokenAccountIdempotentInstruction( 168 | wallet.publicKey, 169 | wSolATA, 170 | keypair.publicKey, 171 | spl.NATIVE_MINT, 172 | spl.TOKEN_PROGRAM_ID, 173 | spl.ASSOCIATED_TOKEN_PROGRAM_ID 174 | ); 175 | 176 | // Calculate fee transfer amount (1% of buy amount) 177 | 178 | // Add a 15% buffer to the buy amount to ensure sufficient funds 179 | const buyWsolAmount = buyAmount * LAMPORTS_PER_SOL * 1.15; 180 | 181 | // Total amount to transfer: buy amount + buffer + fee amount 182 | 183 | // Transfer enough SOL to wrap as WSOL - include the fee amount in the total 184 | const TransferLamportsWSOL = SystemProgram.transfer({ 185 | fromPubkey: wallet.publicKey, 186 | toPubkey: wSolATA, 187 | lamports: Math.trunc(buyWsolAmount), 188 | }); 189 | 190 | // SyncNative with correct program ID to ensure WSOL is synced properly 191 | const syncNativeIx = spl.createSyncNativeInstruction(wSolATA, spl.TOKEN_PROGRAM_ID); 192 | 193 | /////////// buy /////////////// 194 | const swapAccountKey = { 195 | inputMint : spl.NATIVE_MINT, 196 | payer : keypair.publicKey 197 | } 198 | // const buyInstruction = await getSwapInstruction(buyWsolAmount, 0, swapAccountKey, tokenMint); 199 | const buyInstruction = await makeBuyIx(keypair, buyWsolAmount, tokenMint); 200 | 201 | // Create token accounts and instructions 202 | if (buyInstruction) { 203 | bundlerCycleInx = [...bundlerCycleInx, createWSOLAta, TransferLamportsWSOL, syncNativeIx, createTokenBaseAta, buyInstruction]; 204 | } 205 | 206 | if (j === 2) { 207 | console.log("bundlerCycleInx:", bundlerCycleInx.length); 208 | 209 | // Last transaction includes tip 210 | const tipIxn = SystemProgram.transfer({ 211 | fromPubkey: wallet.publicKey, 212 | toPubkey: tipAcct, 213 | lamports: BigInt(jitoTip), 214 | }); 215 | if (option === 1) { 216 | bundlerCycleInx.push(tipIxn); 217 | } 218 | 219 | const addressesMain: PublicKey[] = []; 220 | bundlerCycleInx.forEach((ixn) => { 221 | ixn.keys.forEach((key) => { 222 | addressesMain.push(key.pubkey); 223 | }); 224 | }); 225 | const lookupTablesMain = lookupTableProvider.computeIdealLookupTablesForAddresses(addressesMain); 226 | 227 | 228 | const messageV0 = new TransactionMessage({ 229 | payerKey: keypair.publicKey, 230 | recentBlockhash: block, 231 | instructions: bundlerCycleInx, 232 | }).compileToV0Message(lookupTablesMain); 233 | 234 | const extndTxn = new VersionedTransaction(messageV0); 235 | extndTxn.sign([wallet, ...signers]); 236 | 237 | try { 238 | const serializedMsg = extndTxn.serialize(); 239 | if (serializedMsg.length > 1232) { 240 | console.log("tx too big"); 241 | process.exit(0); 242 | } 243 | 244 | BundledTxns.push(extndTxn); 245 | bundlerCycleInx = [modifyComputeUnits, modifyComputeFee]; 246 | j = 0; 247 | signers = []; 248 | console.log("Transaction added to bundle"); 249 | } catch (e) { 250 | console.log(e, "error with volumeTX"); 251 | process.exit(0); 252 | } 253 | } 254 | 255 | } 256 | 257 | console.log("Sending bundle with", BundledTxns.length, "transactions"); 258 | // Finally, send all transactions as a bundle 259 | if (option === 1) { 260 | // await sendBundle(BundledTxns); 261 | await executeJitoTx(BundledTxns, "confirmed"); 262 | } else { 263 | await sendTransactionsSequentially(BundledTxns); 264 | } 265 | } 266 | 267 | /** 268 | * Updated extender function to use the integrated executeSwaps for launchlab 269 | */ 270 | export async function bundler(option: number) { 271 | console.clear(); 272 | console.log(chalk.green("\n==================== Buy Step ====================")); 273 | console.log(chalk.yellow("Follow the instructions below to perform the buy step.\n")); 274 | 275 | let tokenName, tokenSymbol, description, tokenShowName, twitter, telegram, website, file, buyerAmount, jitoTipAmtInput, buyAmount, mintAddress; //jitoTipAmtInput, 276 | 277 | // tokenName = prompt(chalk.cyan("Input token name: ")); 278 | // if (!tokenName) { 279 | // console.log(chalk.red("Error: Invalid input. Please enter a token name.")); 280 | // process.exit(0x0); 281 | // } 282 | 283 | if (option === 3) { 284 | const tokenMint = prompt(chalk.cyan("Input token mint: ")); 285 | if (!tokenMint) { 286 | console.log(chalk.red("Error: Invalid input. Please enter a token mint.")); 287 | process.exit(0x0); 288 | } 289 | mintAddress = new PublicKey(tokenMint); 290 | } 291 | 292 | // tokenSymbol = prompt(chalk.cyan("Input token symbol: ")); 293 | // if (!tokenSymbol) { 294 | // console.log(chalk.red("Error: Invalid input. Please enter a token symbol.")); 295 | // process.exit(0x0); 296 | // } 297 | 298 | // description = prompt(chalk.cyan("Input description: ")); 299 | // if (!description) { 300 | // console.log(chalk.red("Error: Invalid input. Please enter a description.")); 301 | // process.exit(0x0); 302 | // } 303 | 304 | // tokenShowName = prompt(chalk.cyan("Input token show name: ")); 305 | // if (!tokenShowName) { 306 | // console.log(chalk.red("Error: Invalid input. Please enter a token show name.")); 307 | // process.exit(0x0); 308 | // } 309 | 310 | // twitter = prompt(chalk.cyan("Input twitter url: ")); 311 | // if (!twitter) { 312 | // console.log(chalk.red("Error: Invalid input. Please enter a twitter url.")); 313 | // process.exit(0x0); 314 | // } 315 | 316 | // telegram = prompt(chalk.cyan("Input telegram url: ")); 317 | // if (!telegram) { 318 | // console.log(chalk.red("Error: Invalid input. Please enter a telegram url.")); 319 | // process.exit(0x0); 320 | // } 321 | 322 | // website = prompt(chalk.cyan("Input website: ")); 323 | // if (!website) { 324 | // console.log(chalk.red("Error: Invalid input. Please enter a website.")); 325 | // process.exit(0x0); 326 | // } 327 | 328 | // file = prompt(chalk.cyan("Input file name: ")); 329 | // if (!file) { 330 | // console.log(chalk.red("Error: Invalid input. Please enter a file name.")); 331 | // process.exit(0x0); 332 | // } 333 | 334 | // const buyAmountStr = prompt(chalk.cyan("Input buy amount: ")); 335 | // if (!buyAmount) { 336 | // console.log(chalk.red("Error: Invalid input. Please enter a buy amount.")); 337 | // process.exit(0x0); 338 | // } 339 | // buyAmount = Number(buyAmountStr); 340 | 341 | // const buyerAmountString = prompt(chalk.cyan(`Input buyer amount ${option === 1? "(max: 8)": ""}: `)); 342 | // buyerAmount = Number(buyerAmountString); 343 | 344 | // if (!buyerAmount) { 345 | // console.log(chalk.red("Error: Invalid input. Please enter a buyer amount.")); 346 | // process.exit(0x0); 347 | // } 348 | 349 | // if (option ===1 && buyerAmount > 8) { 350 | // console.log(chalk.red("Error: Invalid input. Buyer amount must less than 8.")); 351 | // process.exit(0x0); 352 | // } 353 | 354 | // jitoTipAmtInput = prompt(chalk.cyan("Jito tip in Sol (Ex. 0.01): ")); 355 | 356 | // if (jitoTipAmtInput) { 357 | // try { 358 | // const tipValue = parseFloat(jitoTipAmtInput); 359 | // if (tipValue >= 0.1) { 360 | // console.log(chalk.red("Error: Tip value is too high. Please enter a value less than or equal to 0.1.")); 361 | // process.exit(0x0); 362 | // } 363 | // } catch (error) { 364 | // console.log(chalk.red("Error: Invalid input. Please enter a valid number.")); 365 | // process.exit(0x0); 366 | // } 367 | // } else { 368 | // console.log(chalk.red("Error: Invalid input. Please enter a valid number.")); 369 | // process.exit(0x0); 370 | // } 371 | 372 | ///////////////////// For test ////////////////////////////////////// 373 | tokenName = "$BonkTie", 374 | tokenSymbol="BT", 375 | description="BonkTie is for making bonk tokens boost its volume incredibly", 376 | tokenShowName="BonkTie", 377 | twitter="https://x.com/bonktie", 378 | telegram="https://t.me/bonktie", 379 | website="https://bonktie.com", 380 | file="1.jpg", 381 | buyerAmount=8, 382 | jitoTipAmtInput="0.0001" 383 | buyAmount = 0.001 384 | ///////////////////////////////////////////////////////////////////// 385 | const jitoTipAmt = parseFloat(jitoTipAmtInput? jitoTipAmtInput : "0.0001" ) * LAMPORTS_PER_SOL; 386 | 387 | if (!tokenName || !tokenSymbol || !description || !tokenCreatedOn || !buyerAmount || !buyAmount) { 388 | return 389 | } 390 | 391 | let tokenCreationTx 392 | 393 | if (option !== 3) { 394 | let mintKp = Keypair.generate() 395 | console.log("mintKp", mintKp.publicKey.toString()); 396 | 397 | if (VANITY_MODE) { 398 | const { keypair, pubkey } = generateVanityAddress("bonk") 399 | mintKp = keypair 400 | console.log(`Keypair generated with "bonk" ending: ${pubkey}`); 401 | } 402 | 403 | mintAddress = mintKp.publicKey 404 | console.log("mintAddress", mintAddress.toBase58()); 405 | 406 | const filePath = "./public/" + file 407 | console.log("token created on:", tokenCreatedOn); 408 | 409 | const uri = await createBonkTokenMetadata(filePath, tokenName, tokenSymbol, description, tokenCreatedOn, "platformId"); 410 | 411 | if (!uri) { 412 | console.log("failed creating metadata"); 413 | return 414 | } 415 | tokenCreationTx = await createBonkTokenTx(mintKp, tokenName, jitoTipAmt, uri) 416 | 417 | } 418 | 419 | if (!mintAddress) { 420 | console.log("no mint address"); 421 | return 422 | } 423 | // create keypair folder direction 424 | const marketKeypairsDir = path.join(keypairsDir, mintAddress.toBase58()); 425 | if (!fs.existsSync(marketKeypairsDir)) { 426 | fs.mkdirSync(marketKeypairsDir, { recursive: true }); 427 | } 428 | 429 | const backupDir = path.join(path.dirname(keypairsDir), "backup", mintAddress.toBase58()); 430 | 431 | if (!fs.existsSync(backupDir)) { 432 | fs.mkdirSync(backupDir, { recursive: true }); 433 | } 434 | 435 | // Get the wallet's initial balance 436 | let walletBalance = 0; 437 | try { 438 | walletBalance = (await connection.getBalance(wallet.publicKey)) / LAMPORTS_PER_SOL; 439 | } catch (error) { 440 | console.error(chalk.red("Error fetching wallet balance:"), error); 441 | } 442 | 443 | const minimumSolAmount = (buyAmount + 0.01) * buyerAmount + 0.05; 444 | // if (walletBalance / 10 ** 9 < minimumSolAmount) { 445 | // console.log(chalk.red("Error: Main wallet balance is not enough to run the bundler.")); 446 | // console.log(chalk.red(`Error: Plz charge the wallet more than. ${minimumSolAmount}SOL`)); 447 | // return 448 | // } 449 | // Generate new keypair(s) for the BUY step 450 | const keypairs: Keypair[] = []; 451 | for (let j = 0; j < buyerAmount; j++) { 452 | const keypair = Keypair.generate(); 453 | if (isValidSolanaAddress(keypair.publicKey)) { 454 | keypairs.push(keypair); 455 | 456 | const filename = `keypair-${keypair.publicKey.toString()}.json`; 457 | const filePath = path.join(marketKeypairsDir, filename); 458 | fs.writeFileSync(filePath, JSON.stringify(Array.from(keypair.secretKey))); 459 | } else { 460 | console.error(chalk.red("Invalid keypair generated, skipping...")); 461 | } 462 | } 463 | 464 | // Get the latest blockhash with retry logic 465 | let blockhash = ""; 466 | try { 467 | blockhash = (await retryOperation(() => connection.getLatestBlockhash())).blockhash; 468 | } catch (error) { 469 | console.error(chalk.red("Error fetching latest blockhash:"), error); 470 | process.exit(0x0); 471 | } 472 | 473 | //console.log("----------- swap --------------------"); 474 | console.log("baseMint & buyAmount", mintAddress, buyAmount); 475 | 476 | try { 477 | // Use the integrated executeSwaps for both pool types 478 | if (mintAddress && buyAmount) { 479 | console.log("------------ buy ------------"); 480 | 481 | await executeSwaps(keypairs, jitoTipAmt, blockhash, buyAmount, mintAddress, option, tokenCreationTx); 482 | } 483 | } catch (error) { 484 | console.error(chalk.red("Error executing swaps:"), error); 485 | } 486 | 487 | // /** 488 | // * After the BUY step, we pick older keypairs (>=30s old) to SELL/close the accounts. 489 | // */ 490 | // let sellKeypairs = new Set(); 491 | // const files = fs.readdirSync(marketKeypairsDir); 492 | // if (sellAmount === 0) { 493 | // console.log(chalk.green(`Sent buy #${i + 1} transaction of ${buyAmount.toFixed(5)} SOL. Waiting ${delay} seconds before next buy...`)); 494 | // await new Promise((resolve) => setTimeout(resolve, delay * 1000)); 495 | // continue; 496 | // } 497 | // console.log("------------ sell ------------"); 498 | // for (const file of files ) { 499 | // const filePath = path.join(marketKeypairsDir, file); 500 | // const stats = fs.statSync(filePath); 501 | // const creationTime = new Date(stats.birthtime).getTime(); 502 | // const currentTime = Date.now(); 503 | 504 | // if (currentTime - creationTime >= 100) { //30000 505 | // const keypairData = JSON.parse(fs.readFileSync(filePath, "utf8")); 506 | // const keypair = Keypair.fromSecretKey(Uint8Array.from(keypairData)); 507 | // const WSOLataKeypair = await spl.getAssociatedTokenAddress(spl.NATIVE_MINT, keypair.publicKey); 508 | 509 | // let tokenAccountExists = false; 510 | // try { 511 | // tokenAccountExists = await checkTokenAccountExists(WSOLataKeypair); 512 | // } catch (error) { 513 | // console.error(chalk.red("Error checking token account existence:"), error); 514 | // } 515 | 516 | // if (tokenAccountExists) { 517 | // sellKeypairs.add(keypair); 518 | // } else { 519 | // console.log(chalk.yellow(`Skipping empty keypair: ${keypair.publicKey.toString()}`)); 520 | // deleteKeypairFile(keypair, marketKeypairsDir); 521 | // } 522 | // } 523 | 524 | // if (sellKeypairs.size >= sellAmount) break; // Limit to specified sellAmount per cycle 525 | // } 526 | 527 | // const sellKeypairList = Array.from(sellKeypairs) as Keypair[]; 528 | // while (sellKeypairList.length > 0) { 529 | // const chunk = sellKeypairList.splice(0, 5); 530 | // try { 531 | // // await closeSpecificAcc(chunk, baseMint.toBase58(), jitoTipAmt, blockhash); 532 | // await closeSpecificAcc(chunk, baseMint.toBase58(), blockhash); 533 | 534 | // await new Promise((resolve) => setTimeout(resolve, 6000)); // Small delay between chunks 535 | // } catch (error) { 536 | // console.error(chalk.red("Error closing accounts:"), error); 537 | // } 538 | // } 539 | 540 | // // Delay between cycles 541 | // console.log(chalk.green(`Sent buy #${i + 1} transaction of ${buyAmount.toFixed(5)} SOL. Waiting ${delay} seconds before next buy...`)); 542 | // await new Promise((resolve) => setTimeout(resolve, delay * 1000)); 543 | 544 | // // Update wallet balance 545 | // try { 546 | // walletBalance = (await connection.getBalance(wallet.publicKey)) / LAMPORTS_PER_SOL; 547 | // console.log(chalk.green(`Wallet Balance after buy #${i + 1}: ${walletBalance.toFixed(3)} SOL`)); 548 | // } catch (error) { 549 | // console.error(chalk.red("Error fetching wallet balance:"), error); 550 | // } 551 | // } 552 | 553 | console.log(chalk.green("\nExecution completed.")); 554 | console.log(chalk.green("Returning to main menu...")); 555 | await pause(); 556 | } 557 | 558 | async function getTokenProgramId(mint: PublicKey): Promise { 559 | try { 560 | // First check if it's a Token-2022 account 561 | try { 562 | const accountInfo = await connection.getAccountInfo(mint); 563 | if (accountInfo) { 564 | // Check the owner of the account 565 | if (accountInfo.owner.equals(spl.TOKEN_2022_PROGRAM_ID)) { 566 | console.log(`Mint ${mint.toBase58()} is a Token-2022 token`); 567 | return spl.TOKEN_2022_PROGRAM_ID; 568 | } 569 | } 570 | } catch (err: any) { 571 | // If there's an error, default to classic SPL Token 572 | console.log(`Error checking Token-2022 status: ${err.message}`); 573 | } 574 | 575 | // Default to classic SPL Token 576 | console.log(`Mint ${mint.toBase58()} is a classic SPL token`); 577 | return spl.TOKEN_PROGRAM_ID; 578 | } catch (error: any) { 579 | console.error(`Error determining token program ID: ${error.message}`); 580 | // Default to classic SPL Token 581 | return spl.TOKEN_PROGRAM_ID; 582 | } 583 | } 584 | 585 | export async function sendTransactionsSequentially(transactions: VersionedTransaction[]): Promise { 586 | console.log(`Sending ${transactions.length} transactions sequentially...`); 587 | 588 | const results: any[] = []; 589 | 590 | for (let i = 0; i < transactions.length; i++) { 591 | try { 592 | console.log(`Sending transaction ${i + 1}/${transactions.length}`); 593 | 594 | const signature = await connection.sendTransaction(transactions[i], { 595 | skipPreflight: false, 596 | preflightCommitment: "confirmed", 597 | maxRetries: 3, 598 | }); 599 | 600 | console.log(`Transaction ${i + 1} sent with signature: ${signature}`); 601 | 602 | // Wait for confirmation 603 | const confirmation = await connection.confirmTransaction( 604 | { 605 | signature, 606 | blockhash: transactions[i].message.recentBlockhash, 607 | lastValidBlockHeight: (await connection.getLatestBlockhash()).lastValidBlockHeight, 608 | }, 609 | "confirmed" 610 | ); 611 | 612 | if (confirmation.value.err) { 613 | console.error(`Transaction ${i + 1} failed: ${JSON.stringify(confirmation.value.err)}`); 614 | } else { 615 | console.log(`Transaction ${i + 1} confirmed successfully`); 616 | } 617 | 618 | results.push({ 619 | signature, 620 | status: confirmation.value.err ? "failed" : "success", 621 | error: confirmation.value.err, 622 | }); 623 | } catch (error: any) { 624 | // Check if error has getLogs method 625 | const sim = await connection.simulateTransaction(transactions[i]) 626 | if (error && typeof error === "object" && "getLogs" in error && typeof error.getLogs === "function") { 627 | try { 628 | console.error(`Transaction ${i + 1} failed, getting detailed logs...`); 629 | 630 | // Handle the case where getLogs returns a Promise 631 | let logsData; 632 | try { 633 | // Try to await the getLogs if it's a Promise 634 | const logResult = error.getLogs(); 635 | if (logResult instanceof Promise) { 636 | logsData = await logResult; 637 | } else { 638 | logsData = logResult; 639 | } 640 | } catch (logError) { 641 | // If awaiting fails, use the original error 642 | logsData = error.message || "Unknown error"; 643 | } 644 | 645 | // Format logs data for display and file storage 646 | let formattedLogs; 647 | if (Array.isArray(logsData)) { 648 | formattedLogs = logsData.join("\n"); 649 | } else if (typeof logsData === "object") { 650 | formattedLogs = JSON.stringify(logsData, null, 2); 651 | } else { 652 | formattedLogs = String(logsData); 653 | } 654 | 655 | console.error(`Transaction ${i + 1} detailed logs:`); 656 | console.error(formattedLogs); 657 | 658 | // Save to error.txt 659 | const errorContent = 660 | `\n[${new Date().toISOString()}] Transaction ${i + 1} error:\n` + `${formattedLogs}\n` + `${error.stack || error.message || ""}\n` +`${JSON.stringify(sim, null, 2)}\n` + `${"=".repeat(50)}\n`; 661 | 662 | fs.appendFileSync("error.txt", errorContent); 663 | console.log(`Error details saved to error.txt`); 664 | } catch (fsError: any) { 665 | console.error(`Failed to handle or write error logs: ${fsError.message}`); 666 | } 667 | } else { 668 | // Handle regular errors 669 | console.error(`Error sending transaction ${i + 1}:`, error); 670 | 671 | // Save regular errors to error.txt 672 | try { 673 | const errorContent = 674 | `\n[${new Date().toISOString()}] Transaction ${i + 1} error:\n` + `${error.message || "Unknown error"}\n` + `${error.stack || ""}\n`+`${JSON.stringify(sim, null, 2)}`+`${"=".repeat(50)}\n`; 675 | 676 | fs.appendFileSync("error.txt", errorContent); 677 | console.log(`Error details saved to error.txt`); 678 | } catch (fsError: any) { 679 | console.error(`Failed to write error to file: ${fsError.message}`); 680 | } 681 | } 682 | 683 | results.push({ 684 | status: "failed", 685 | error: error.message || "Unknown error", 686 | }); 687 | } 688 | } 689 | 690 | return results; 691 | } 692 | 693 | /** 694 | * Loads all the keypairs from the specified directory for a given marketID. 695 | */ 696 | function loadKeypairs(marketID: string) { 697 | const keypairs: Keypair[] = []; 698 | const marketKeypairsPath = path.join(keypairsDir, marketID); 699 | 700 | if (!fs.existsSync(marketKeypairsPath)) { 701 | return keypairs; // Return empty if directory doesn't exist 702 | } 703 | 704 | const files = fs.readdirSync(marketKeypairsPath); 705 | 706 | files.forEach((file) => { 707 | if (file.endsWith(".json")) { 708 | const filePath = path.join(marketKeypairsPath, file); 709 | const fileData = JSON.parse(fs.readFileSync(filePath, "utf8")); 710 | const keypair = Keypair.fromSecretKey(new Uint8Array(fileData)); 711 | keypairs.push(keypair); 712 | } 713 | }); 714 | return keypairs; 715 | } 716 | 717 | /** 718 | * Sends a bundle of VersionedTransactions using the Jito searcherClient. 719 | */ 720 | export async function sendBundle(bundledTxns: VersionedTransaction[]) { 721 | try { 722 | const bundleResult = await searcherClient.sendBundle(new JitoBundle(bundledTxns, bundledTxns.length)); 723 | 724 | if (bundleResult && typeof bundleResult === "object") { 725 | if (bundleResult.ok && bundleResult.value) { 726 | console.log(`Bundle ${bundleResult.value} sent.`); 727 | } else { 728 | console.log(`Bundle sent. Result:`, JSON.stringify(bundleResult)); 729 | } 730 | } else { 731 | console.log(`Bundle ${bundleResult} sent.`); 732 | } 733 | 734 | //* 735 | // Assuming onBundleResult returns a Promise 736 | /* 737 | const result = await new Promise((resolve, reject) => { 738 | searcherClient.onBundleResult( 739 | (result) => { 740 | console.log("Received bundle result:", result); 741 | resolve(result); // Resolve the promise with the result 742 | }, 743 | (e: Error) => { 744 | console.error("Error receiving bundle result:", e); 745 | reject(e); // Reject the promise if there's an error 746 | } 747 | ); 748 | }); 749 | 750 | console.log("Result:", result); 751 | */ 752 | // 753 | } catch (error) { 754 | const err = error as any; 755 | console.error("Error sending bundle:", err.message); 756 | 757 | if (err?.message?.includes("Bundle Dropped, no connected leader up soon")) { 758 | console.error("Error sending bundle: Bundle Dropped, no connected leader up soon."); 759 | } else { 760 | console.error("An unexpected error occurred:", err.message); 761 | } 762 | } 763 | } 764 | 765 | 766 | /** 767 | * Checks if a given PublicKey is a valid Solana address. 768 | */ 769 | function isValidSolanaAddress(address: PublicKey) { 770 | try { 771 | new PublicKey(address); // Will throw if invalid 772 | return true; 773 | } catch (e) { 774 | return false; 775 | } 776 | } 777 | 778 | 779 | --------------------------------------------------------------------------------