Only tech topics about Waves: dev tools, libs, RIDE, dApps, Nodes Github: http://tiny.cc/github-waves IDE: https://ide.wavesplatform.com/ Online Course: https://stepik.org/course/54415 StackOverflow: #wavesplatform Jobs: https://t.me/wavesridejobs
probably that is the problem no one wants to work on it
Читать полностью…an old node release will not work with the current blockchain
Читать полностью…ok so ill probably need an older node release in my script?
Читать полностью…so im trying to do something too advanced for pywaves?
Читать полностью…soo close its frustrating and i gotta wait 2 hours before i get another 15 questions for grok lol
Читать полностью…my test bot gives this: C:\Users\brian\PycharmProjects\PythonProject\.venv\Scripts\python.exe C:\Users\brian\PycharmProjects\PythonProject\test_bot.py
Caught exception from sendAsset: 'int' object has no attribute 'status'
Likely received an integer response from sendAsset()
Inner error from wrapper: Expecting value: line 1 column 1 (char 0)
Process finished with exit code 0
in debug mode with full updated script i get this: import sys; print('Python %s on %s' % (sys.version, sys.platform))
C:\Users\brian\PycharmProjects\PythonProject\.venv\Scripts\python.exe -X pycache_prefix=C:\Users\brian\AppData\Local\JetBrains\PyCharm2024.3\cpython-cache "C:/Program Files/JetBrains/PyCharm 2024.3.3/plugins/python-ce/helpers/pydev/pydevd.py" --multiprocess --qt-support=auto --client 127.0.0.1 --port 63122 --file C:\Users\brian\PycharmProjects\PythonProject\fishing_bot.py
Connected to pydev debugger (build 243.24978.54)
[ERROR] Token distribution failed: 'int' object has no attribute 'status' - tx type: None, tx value: None
ok i have a test script for trying to send tokens
Читать полностью…try and go haed with debug. May be there i s a problem in PyWaves
Читать полностью…change the method to collect more debug info as for the attachment
Читать полностью…yes and im using grok 3 beta and it keeps trying to fix it but its stuck in an infinite loop of the same problem
Читать полностью…like it works and i can link my address and then i can fish but i get a stupid int error on sending tokens
Читать полностью…with get_db_connection() as conn:
c = conn.cursor()
c.execute(f"SELECT fish_type, quantity FROM {TABLE_INVENTORY} WHERE user_id = ?", (user_id,))
items = c.fetchall()
user_wallet = pw.Address(user_address)
krill_balance = user_wallet.balance(TOKEN_IDS['krill']) / 10 8
inventory_text = f"Krill Balance: {krill_balance:.2f}\n"
if items:
inventory_text += "Your Catches:\n" + "\n".join([f"{item[0]}: {item[1]}" for item in items])
else:
inventory_text += "Your inventory is empty."
await update.message.reply_text(inventory_text)
except Exception as e:
logging.error(f"Error in inventory: {e}")
await update.message.reply_text("Error checking inventory!")
async def leaderboard(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
with get_db_connection() as conn:
c = conn.cursor()
c.execute(
f"SELECT user_id, SUM(quantity) FROM {TABLE_INVENTORY} GROUP BY user_id ORDER BY SUM(quantity) DESC LIMIT 5")
leaderboard_data = c.fetchall()
if leaderboard_data:
leaderboard_text = "Top Fishers:\n" + "\n".join(
[f"{i + 1}. User {user_id}: {total}" for i, (user_id, total) in enumerate(leaderboard_data)])
await update.message.reply_text(leaderboard_text)
else:
await update.message.reply_text("No one has caught fish yet!")
except Exception as e:
logging.error(f"Error in leaderboard: {e}")
await update.message.reply_text("Error generating leaderboard!")
async def button(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
direction = query.data
user_id = query.from_user.id
now = datetime.now()
timestamp = now.strftime('%Y-%m-%d %H:%M:%S')
try:
if now - fishing_cooldowns[user_id] < timedelta(minutes=COOLDOWN_MINUTES):
remaining = int((timedelta(minutes=COOLDOWN_MINUTES) - (now - fishing_cooldowns[user_id])).total_seconds())
await query.edit_message_text(f"Please wait {remaining} seconds before fishing again!")
return
user_address = get_waves_address(user_id)
if not user_address:
await query.edit_message_text("Please link your Waves address first with /link!")
return
user_wallet = pw.Address(user_address)
krill_balance = user_wallet.balance(TOKEN_IDS['krill'])
if krill_balance < KRILL_COST:
await query.edit_message_text(
f"You need {KRILL_COST} Krill to fish! Balance: {krill_balance / 10 8:.2f}")
return
fishing_cooldowns[user_id] = now
with get_db_connection() as conn:
c = conn.cursor()
c.execute(f"INSERT INTO {TABLE_FISHING_LOG} (user_id, fish_timestamp) VALUES (?, ?)",
(user_id, timestamp))
conn.commit()
await query.edit_message_text(f"Fishing in direction {direction}...")
fish_caught = calculate_catch(direction)
if fish_caught and fish_caught != 'nothing':
quantity = calculate_catch_quantity(fish_caught)
await distribute_tokens(user_id, fish_caught, quantity, update, context)
else:
await query.message.reply_text("You caught nothing this time!")
except Exception as e:
logging.error(f"Error in button callback: {e}")
await query.edit_message_text("An error occurred while fishing!")
def calculate_catch(direction):
probabilities = FISH_CATCH_PROBABILITIES.get(direction, {})
return random.choices(list(probabilities.keys()), weights=list(probabilities.values()), k=1)[
0] if probabilities else None
def calculate_catch_quantity(fish_type):
min_catch, max_catch = CATCH_RANGES.get(fish_type, (0, 0))
return random.randint(min_catch, max_catch)
import logging
import random
import sqlite3
import os
import pywaves as pw
from telegram import Bot, Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
from dotenv import load_dotenv
from datetime import datetime, timedelta
from collections import defaultdict
# Constants
DATABASE_FILE = 'user_addresses.db'
TABLE_USERS = 'user_addresses'
TABLE_INVENTORY = 'user_inventory'
TABLE_FISHING_LOG = 'fishing_log'
COOLDOWN_MINUTES = 1
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(message)s',
handlers=[
logging.FileHandler('fishing_bot.log'),
logging.StreamHandler()
]
)
# Load environment variables
load_dotenv()
TOKEN = os.getenv('BOT_TOKEN')
CHAT_ID = os.getenv('CHAT_ID')
SENDER_ADDRESS = os.getenv('SENDER_ADDRESS')
SENDER_PRIVATE_KEY = os.getenv('SENDER_PRIVATE_KEY')
logging.info(f"Environment loaded - TOKEN: {TOKEN[:5] if TOKEN else None}..., "
f"ADDRESS: {SENDER_ADDRESS}, KEY: {SENDER_PRIVATE_KEY[:5] if SENDER_PRIVATE_KEY else None}...")
TOKEN_IDS = {
'sculpin': '9Rv2rf2Aia7itjaXfs27t51JBwKwyP29Thy6F8qdZXLk',
'crab': 'rtQ8rMRPLeTtFAFFAa3vrYGfpp5jvm3VPKXivhQSwXM',
'haddock': '3GmnizcybRQwLtku3AdQcmrJnyR4xgpDQygcSvEi7UPN',
'halibut': '8FpCUVrRNGG4tyJqknguzCdeW8ArcskP37Fz6eUhZSvk',
'swordfish': '4FNvaVD92yLn9xwXN94RfX1TsMWn2ennS4iw4Swsaptu',
'tuna': '3xipSS6JctxvmfWjbzUSpigDgqEneXZZpHTZAWxs3Hp2',
'krill': 'HrPA8VBPGicVukmy52EsgkGr5Appup4bfcoDjhioFkRE'
}
FISH_CATCH_PROBABILITIES = {
'1': {'sculpin': 0.25, 'crab': 0.20, 'haddock': 0.15, 'halibut': 0.10, 'swordfish': 0.05, 'tuna': 0.03,
'nothing': 0.22},
'2': {'sculpin': 0.27, 'crab': 0.22, 'haddock': 0.16, 'halibut': 0.11, 'swordfish': 0.04, 'tuna': 0.02,
'nothing': 0.18},
'3': {'sculpin': 0.23, 'crab': 0.18, 'haddock': 0.14, 'halibut': 0.09, 'swordfish': 0.06, 'tuna': 0.04,
'nothing': 0.26},
'4': {'sculpin': 0.28, 'crab': 0.23, 'haddock': 0.17, 'halibut': 0.12, 'swordfish': 0.05, 'tuna': 0.03,
'nothing': 0.12},
'5': {'sculpin': 0.24, 'crab': 0.19, 'haddock': 0.13, 'halibut': 0.10, 'swordfish': 0.06, 'tuna': 0.03,
'nothing': 0.25},
'6': {'sculpin': 0.26, 'crab': 0.21, 'haddock': 0.15, 'halibut': 0.11, 'swordfish': 0.04, 'tuna': 0.02,
'nothing': 0.21},
'7': {'sculpin': 0.22, 'crab': 0.17, 'haddock': 0.14, 'halibut': 0.08, 'swordfish': 0.07, 'tuna': 0.05,
'nothing': 0.27},
'8': {'sculpin': 0.29, 'crab': 0.24, 'haddock': 0.16, 'halibut': 0.13, 'swordfish': 0.05, 'tuna': 0.03,
'nothing': 0.10}
}
CATCH_RANGES = {
'sculpin': (500, 2000),
'crab': (250, 1000),
'haddock': (100, 500),
'halibut': (50, 250),
'swordfish': (20, 100),
'tuna': (5, 25)
}
KRILL_COST = 100
fishing_cooldowns = defaultdict(lambda: datetime.min)
# Waves setup
pw.setNode('https://nodes.wavesnodes.com', 'mainnet')
sender = pw.Address(privateKey=SENDER_PRIVATE_KEY)
def validate_config():
required_vars = {
'BOT_TOKEN': TOKEN,
'SENDER_PRIVATE_KEY': SENDER_PRIVATE_KEY,
'SENDER_ADDRESS': SENDER_ADDRESS
}
missing = [key for key, value in required_vars.items() if not value]
if missing:
raise ValueError(f"Missing required environment variables: {', '.join(missing)}")
logging.info("Configuration validated successfully")
def get_db_connection():
return sqlite3.connect(DATABASE_FILE, timeout=10)
is there an alternative like using a different language than python?
Читать полностью…oh ok so kinda need an updated pywaves
Читать полностью…thank you though i appreciate it
Читать полностью…maybe pyWaves now doesn t work with new nodes release. i have no time to test it, but in the past it worked great
Читать полностью…/channel/waves_ride_dapps_dev/61582
Читать полностью…im assuming problem is in pywaves its been hinting to that alot
Читать полностью…that had encountered same problem though
Читать полностью…try a simple program to send tokens to an address using pywaves. If it works come back
Читать полностью…C:\Users\brian\PycharmProjects\PythonProject\.venv\Scripts\python.exe C:\Users\brian\PycharmProjects\PythonProject\fishing_bot.py
[ERROR] Error in button callback: cannot access local variable 'tx' where it is not associated with a value
i need someone who understands what to do to fix the code
Читать полностью…DeepSeek shows this:
The error you're encountering, 'int' object has no attribute 'status', suggests that the sendAsset method from the pywaves library is returning an integer instead of the expected transaction object or dictionary. This typically happens when the transaction fails, and the library returns an HTTP status code (e.g., 400, 403, 404) instead of the transaction details.
To fix this issue, you need to handle the case where sendAsset returns an integer (indicating an error) and provide appropriate error handling.
async def distribute_tokens(user_id, fish_type, quantity, update, context):
try:
user_address = get_waves_address(user_id)
if not user_address:
await update.callback_query.message.reply_text("Link your Waves address first with /link!")
return
if fish_type not in TOKEN_IDS:
raise ValueError(f"Invalid fish type: {fish_type}")
recipient = pw.Address(user_address)
logging.info(f"Attempting to send {quantity} {fish_type} (Asset ID: {TOKEN_IDS[fish_type]}) to {user_address}")
tx = sender.sendAsset(recipient, quantity, TOKEN_IDS[fish_type])
logging.info(f"Raw transaction response: {tx}, type: {type(tx)}")
# Handle the response
if isinstance(tx, int):
error_msg = {
400: "Bad request - check asset ID or quantity",
403: "Insufficient funds or permission denied",
404: "Asset or address not found",
}.get(tx, f"Unknown error code: {tx}")
raise Exception(f"Transaction failed with status code {tx}: {error_msg}")
elif isinstance(tx, dict):
if 'id' not in tx:
raise Exception(f"Transaction dict missing 'id': {tx}")
tx_id = tx['id']
else:
raise Exception(f"Unexpected transaction response type: {type(tx)}, value: {tx}")
# If we reach here, tx is a dict with an 'id'
with get_db_connection() as conn:
c = conn.cursor()
c.execute(f"""
INSERT INTO {TABLE_INVENTORY} (user_id, fish_type, quantity)
VALUES (?, ?, ?)
ON CONFLICT(user_id, fish_type)
DO UPDATE SET quantity = quantity + ?""",
(user_id, fish_type, quantity, quantity))
conn.commit()
await update.callback_query.message.reply_text(
f"Caught {quantity} {fish_type}! Tokens sent to {user_address}.\nTxID: {tx_id}"
)
except Exception as e:
logging.error(f"Token distribution failed: {str(e)}")
await update.callback_query.message.reply_text(f"Failed to send {fish_type} tokens: {str(e)}")
def get_waves_address(user_id):
with get_db_connection() as conn:
c = conn.cursor()
c.execute(f"SELECT waves_address FROM {TABLE_USERS} WHERE user_id = ?", (user_id,))
result = c.fetchone()
return result[0] if result else None
def main():
validate_config()
setup_database()
bot = Bot(token=TOKEN)
app = Application.builder().token(TOKEN).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("help", start))
app.add_handler(CommandHandler("link", link_address))
app.add_handler(CommandHandler("fish", fish))
app.add_handler(CommandHandler("inventory", inventory))
app.add_handler(CommandHandler("leaderboard", leaderboard))
app.add_handler(CallbackQueryHandler(button))
logging.info("Bot initialized, starting polling...")
app.run_polling(allowed_updates=Update.ALL_TYPES)
logging.info("Polling stopped unexpectedly")
if name == 'main':
logging.info("Starting bot execution...")
main()
def setup_database():
with get_db_connection() as conn:
c = conn.cursor()
c.execute(f'''CREATE TABLE IF NOT EXISTS {TABLE_USERS}
(user_id INTEGER PRIMARY KEY, waves_address TEXT)''')
c.execute(f'''CREATE TABLE IF NOT EXISTS {TABLE_INVENTORY}
(user_id INTEGER, fish_type TEXT, quantity INTEGER,
FOREIGN KEY (user_id) REFERENCES {TABLE_USERS}(user_id))''')
c.execute(f'''CREATE TABLE IF NOT EXISTS {TABLE_FISHING_LOG}
(user_id INTEGER, fish_timestamp TEXT,
PRIMARY KEY (user_id, fish_timestamp))''')
conn.commit()
logging.info("Database setup completed")
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(
"Welcome to Fishing Bot!\n"
"Commands:\n"
"/link <address> - Link your Waves address\n"
"/fish - Start fishing\n"
"/inventory - Check your catches\n"
"/leaderboard - See top fishers\n"
"/help - Show this message"
)
async def link_address(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
if not context.args:
await update.message.reply_text("Please provide a Waves address. Example: /link 3P...")
return
waves_address = context.args[0]
if not waves_address.startswith('3P') or len(waves_address) != 35:
await update.message.reply_text("Invalid Waves address format!")
return
user_id = update.message.from_user.id
with get_db_connection() as conn:
c = conn.cursor()
c.execute(f"INSERT OR REPLACE INTO {TABLE_USERS} (user_id, waves_address) VALUES (?, ?)",
(user_id, waves_address))
conn.commit()
await update.message.reply_text("Your Waves address is linked successfully!")
except Exception as e:
logging.error(f"Error in link_address: {e}")
await update.message.reply_text("An error occurred while linking your address.")
async def fish(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
user_id = update.message.from_user.id
now = datetime.now()
if now - fishing_cooldowns[user_id] < timedelta(minutes=COOLDOWN_MINUTES):
remaining = int((timedelta(minutes=COOLDOWN_MINUTES) - (now - fishing_cooldowns[user_id])).total_seconds())
await update.message.reply_text(f"Please wait {remaining} seconds before fishing again!")
return
user_address = get_waves_address(user_id)
if not user_address:
await update.message.reply_text("Please link your Waves address first with /link!")
return
keyboard = [
[InlineKeyboardButton("North", callback_data='1'), InlineKeyboardButton("North-East", callback_data='2')],
[InlineKeyboardButton("East", callback_data='3'), InlineKeyboardButton("South-East", callback_data='4')],
[InlineKeyboardButton("South", callback_data='5'), InlineKeyboardButton("South-West", callback_data='6')],
[InlineKeyboardButton("West", callback_data='7'), InlineKeyboardButton("North-West", callback_data='8')]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(f"Fishing costs {KRILL_COST} Krill. Choose a direction:",
reply_markup=reply_markup)
except Exception as e:
logging.error(f"Error in fish command: {e}")
await update.message.reply_text("An error occurred while processing your fishing request.")
async def inventory(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
user_id = update.message.from_user.id
user_address = get_waves_address(user_id)
if not user_address:
await update.message.reply_text("Please link your Waves address first with /link!")
return