-
Notifications
You must be signed in to change notification settings - Fork 80
/
trade.py
157 lines (135 loc) · 6.57 KB
/
trade.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import asyncio
import json
import base64
import struct
import base58
import hashlib
import websockets
import os
import argparse
from datetime import datetime
from solana.rpc.async_api import AsyncClient
from solana.transaction import Transaction
from solana.rpc.commitment import Confirmed
from solana.rpc.types import TxOpts
from solders.pubkey import Pubkey
from solders.keypair import Keypair
from solders.instruction import Instruction, AccountMeta
from solders.system_program import TransferParams, transfer
from solders.transaction import VersionedTransaction
from spl.token.instructions import get_associated_token_address
import spl.token.instructions as spl_token
from config import *
# Import functions from buy.py
from buy import get_pump_curve_state, calculate_pump_curve_price, buy_token, listen_for_create_transaction
# Import functions from sell.py
from sell import sell_token
def log_trade(action, token_data, price, tx_hash):
os.makedirs("trades", exist_ok=True)
log_entry = {
"timestamp": datetime.utcnow().isoformat(),
"action": action,
"token_address": token_data['mint'],
"price": price,
"tx_hash": tx_hash
}
with open("trades/trades.log", 'a') as log_file:
json.dump(log_entry, log_file)
log_file.write("\n")
async def trade(websocket=None, match_string=None, bro_address=None, marry_mode=False, yolo_mode=False):
if websocket is None:
async with websockets.connect(WSS_ENDPOINT) as websocket:
await _trade(websocket, match_string, bro_address, marry_mode, yolo_mode)
else:
await _trade(websocket, match_string, bro_address, marry_mode, yolo_mode)
async def _trade(websocket, match_string=None, bro_address=None, marry_mode=False, yolo_mode=False):
while True:
print("Waiting for a new token creation...")
token_data = await listen_for_create_transaction(websocket)
print("New token created:")
print(json.dumps(token_data, indent=2))
if match_string and not (match_string.lower() in token_data['name'].lower() or match_string.lower() in token_data['symbol'].lower()):
print(f"Token does not match the criteria '{match_string}'. Skipping...")
if not yolo_mode:
break
continue
if bro_address and token_data['user'] != bro_address:
print(f"Token not created by the specified user '{bro_address}'. Skipping...")
if not yolo_mode:
break
continue
# Save token information to a .txt file in the "trades" directory
mint_address = token_data['mint']
os.makedirs("trades", exist_ok=True)
file_name = os.path.join("trades", f"{mint_address}.txt")
with open(file_name, 'w') as file:
file.write(json.dumps(token_data, indent=2))
print(f"Token information saved to {file_name}")
print("Waiting for 15 seconds for things to stabilize...")
await asyncio.sleep(15)
mint = Pubkey.from_string(token_data['mint'])
bonding_curve = Pubkey.from_string(token_data['bondingCurve'])
associated_bonding_curve = Pubkey.from_string(token_data['associatedBondingCurve'])
# Fetch the token price
async with AsyncClient(RPC_ENDPOINT) as client:
curve_state = await get_pump_curve_state(client, bonding_curve)
token_price_sol = calculate_pump_curve_price(curve_state)
print(f"Bonding curve address: {bonding_curve}")
print(f"Token price: {token_price_sol:.10f} SOL")
print(f"Buying {BUY_AMOUNT:.6f} SOL worth of the new token with {BUY_SLIPPAGE*100:.1f}% slippage tolerance...")
buy_tx_hash = await buy_token(mint, bonding_curve, associated_bonding_curve, BUY_AMOUNT, BUY_SLIPPAGE)
if buy_tx_hash:
log_trade("buy", token_data, token_price_sol, str(buy_tx_hash))
else:
print("Buy transaction failed.")
if not marry_mode:
print("Waiting for 20 seconds before selling...")
await asyncio.sleep(20)
print(f"Selling tokens with {SELL_SLIPPAGE*100:.1f}% slippage tolerance...")
sell_tx_hash = await sell_token(mint, bonding_curve, associated_bonding_curve, SELL_SLIPPAGE)
if sell_tx_hash:
log_trade("sell", token_data, token_price_sol, str(sell_tx_hash))
else:
print("Sell transaction failed or no tokens to sell.")
else:
print("Marry mode enabled. Skipping sell operation.")
if not yolo_mode:
break
async def main(yolo_mode=False, match_string=None, bro_address=None, marry_mode=False):
if yolo_mode:
while True:
try:
async with websockets.connect(WSS_ENDPOINT) as websocket:
while True:
try:
await trade(websocket, match_string, bro_address, marry_mode, yolo_mode)
except websockets.exceptions.ConnectionClosed:
print("WebSocket connection closed. Reconnecting...")
break
except Exception as e:
print(f"An error occurred: {e}")
print("Waiting for 5 seconds before looking for the next token...")
await asyncio.sleep(5)
except Exception as e:
print(f"Connection error: {e}")
print("Reconnecting in 5 seconds...")
await asyncio.sleep(5)
else:
# For non-YOLO mode, create a websocket connection and close it after one trade
async with websockets.connect(WSS_ENDPOINT) as websocket:
await trade(websocket, match_string, bro_address, marry_mode, yolo_mode)
async def ping_websocket(websocket):
while True:
try:
await websocket.ping()
await asyncio.sleep(20) # Send a ping every 20 seconds
except:
break
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Trade tokens on Solana.")
parser.add_argument("--yolo", action="store_true", help="Run in YOLO mode (continuous trading)")
parser.add_argument("--match", type=str, help="Only trade tokens with names or symbols matching this string")
parser.add_argument("--bro", type=str, help="Only trade tokens created by this user address")
parser.add_argument("--marry", action="store_true", help="Only buy tokens, skip selling")
args = parser.parse_args()
asyncio.run(main(yolo_mode=args.yolo, match_string=args.match, bro_address=args.bro, marry_mode=args.marry))