from asyncio import run from tonsdk.boc import Cell, begin_cell from tonsdk.utils import Address import pandas as pd from datetime import datetime from pytonapi import AsyncTonapi from _auth import get_or_create_wallet_settings from _core import unpack_wallet, serialize_command, perform_action, print_actions async def main(): print('\n' * 30) wallet_settings = get_or_create_wallet_settings() wallet = unpack_wallet(wallet_settings) wallet_address = wallet.address.to_string(1, 1, 1) print(f"=== Successfully loaded wallet {wallet.address.to_string(1, 1, 0)}") # print(wallet_settings) actions = [] while len(actions) < 4: print_actions(actions) print("Available actions:") print("1) Send TON") print("2) Send Jetton") print("3) Send NFT") print("4) Update wallet contract") print("5) Export mnemonic phrase") print("7) New decentralized note") print("8) Read decentralized note") print("9) View transactions history") print("10) Export transactions history") print("0) View actions and exit | send transactions") choice = input("Select an action (1/2/3/4/0): ") if choice == "0": break elif choice in {"5"}: print("=== Mnemonic phrase:") print(wallet_settings['mnemonic']) continue elif choice in {"9", "10"}: print("=== Transactions history:") tonapi = AsyncTonapi('AEA5YM3PU2YFXJIAAAAH3JWVNWRM57SFIBJGVJHCOK2GGPJ2L2MNKXBYPO7VTTY26ZRLX6I') transactions = [] start_ts = None while not start_ts or events.events: try: events = await tonapi.accounts.get_events(wallet_address, end_date=start_ts or None) except BaseException as e: if "rate limit" in str(e): print("Rate limit exceeded. Please try again later.") time.sleep(1) continue else: print(f"TonAPI error: {e}") print(f"Fetched {len(events.events)} events from {start_ts}") for event in events.events: if event.in_progress is True: continue event_dt = datetime.fromtimestamp(event.timestamp) event_dtf = event_dt.strftime("%Y-%m-%d %H:%M:%S") for event_action in event.actions: transactions.append( (event.event_id, event.lt, event_dtf, event_action.type, event_action) ) if not start_ts or start_ts > event.timestamp: start_ts = event.timestamp if choice == "9": for event_action in reversed(transactions): e_id, e_lt, e_dtf, e_type, e_action = event_action action_formatted = f"TXID: {e_id}, logic time: {e_lt}. {e_dtf} {e_type}:" + '\n' + " " * 6 if e_type == "TonTransfer": e_action = e_action.TonTransfer action_formatted += f"{Address(e_action.sender.address.to_raw()).to_string(1, 1, 1)}" \ + f" sent {round(int(e_action.amount) / 10 ** 9, 3)} TON => {Address(e_action.recipient.address.to_raw()).to_string(1, 1, 1)}" if e_action.comment: action_formatted += f". Comment: {e_action.comment}" elif e_type == "JettonTransfer": e_action = e_action.JettonTransfer action_formatted += f"{Address(e_action.sender.address.to_raw()).to_string(1, 1, 1)}" \ + f" sent {round(int(e_action.amount) / 10 ** e_action.jetton.decimals, 3)} {e_action.jetton.symbol} => {Address(e_action.recipient.address.to_raw()).to_string(1, 1, 1)}" if e_action.comment: action_formatted += f". Comment: {e_action.comment}" elif e_type == "NftItemTransfer": e_action = e_action.NftItemTransfer action_formatted += f"{Address(e_action.sender.address.to_raw()).to_string(1, 1, 1)}" \ + f" sent NFT ({e_action.nft}) => {Address(e_action.recipient.address.to_raw()).to_string(1, 1, 1)}" else: e_action = getattr(e_action, e_type) action_formatted += "unknown action: " + str(e_action) print(action_formatted + '\n') elif choice == "10": dfr = [] for event_action in reversed(transactions): e_id, e_lt, e_dtf, e_type, e_action = event_action if e_type == "TonTransfer": e_action = e_action.TonTransfer dfr.append([ e_id, e_lt, e_dtf, e_type, Address(e_action.sender.address.to_raw()).to_string(1, 1, 1), Address(e_action.recipient.address.to_raw()).to_string(1, 1, 1), str(round(int(e_action.amount) / 10 ** 9, 3)), e_action.comment or '' ]) elif e_type == "JettonTransfer": e_action = e_action.JettonTransfer dfr.append([ e_id, e_lt, e_dtf, e_type, Address(e_action.sender.address.to_raw()).to_string(1, 1, 1), Address(e_action.recipient.address.to_raw()).to_string(1, 1, 1), str(round(int(e_action.amount) / 10 ** e_action.jetton.decimals, 3)), e_action.comment or '' ]) elif e_type == "NftItemTransfer": e_action = e_action.NftItemTransfer dfr.append([ e_id, e_lt, e_dtf, e_type, Address(e_action.sender.address.to_raw()).to_string(1, 1, 1), Address(e_action.recipient.address.to_raw()).to_string(1, 1, 1), e_action.nft, '' ]) df = pd.DataFrame(dfr, columns=[ 'TXID', 'Logic Time', 'Time', 'Type', 'Sender', 'Recipient', 'Amount', 'Comment' ]) df.to_csv('transactions_history.csv', sep=",") print("Transactions history saved to transactions_history.csv") continue elif choice in {"1", "2", "3", "4", "7"}: action_type = int(choice) action = {"type": action_type, "args": []} if action_type == 1: destination = input("Enter the destination address: ") Address(destination).to_string(1, 1, 1) amount = float(input("Enter the amount in TON: ")) comment = input("Enter a comment (or leave it empty): ") if comment: raw_payload = ( begin_cell() .store_uint(0, 32) .store_bytes(comment.encode()) .end_cell() ) else: raw_payload = input("Enter raw_payload in HEX (or leave it empty): ") try: raw_payload = Cell.one_from_boc(raw_payload) except: raw_payload = None action["args"] = { "destination": destination, "amount": int(amount * 10 ** 9), "payload_cell": raw_payload } elif action_type == 2: token_contract = input("Enter the token contract address: ") recipient = input("Enter the recipient address: ") Address(token_contract).to_string(1, 1, 1) Address(recipient).to_string(1, 1, 1) amount = float(input("Enter the amount in tokens: ")) decimals = int(input("Enter token decimals: ")) amount = int(amount * 10 ** decimals) comment = input("Enter a comment: ") action["args"] = { "token_contract": token_contract, "recipient": recipient, "amount": amount, "comment": comment } elif action_type == 3: nft_address = input("Enter the NFT address: ") recipient = input("Enter the recipient address: ") Address(nft_address).to_string(1, 1, 1) Address(recipient).to_string(1, 1, 1) action["args"] = { "nft_address": nft_address, "recipient": recipient } elif action_type == 4: hex_code = input("Enter the smart contract code in HEX: ") hex_data = input("Enter smart contract data in HEX: ") action["args"] = { 'new_code': Cell.one_from_boc(hex_code), 'new_data': Cell.one_from_boc(hex_data) } elif action_type == 7: note_key = input("Enter the note key: ") print(f"""[?] Please, enter plain text & input 0 for write the note:""") plain_text = "" while True: new_input = input() if new_input == '0': break plain_text += new_input + '\n' action['args'] = { 'note_key': note_key.strip(), 'plain_text': plain_text.strip(), 'private_key': bytes.fromhex(wallet_settings['secret_key']) } actions.append(action) if not actions: print("No actions selected") return _commands = begin_cell() for action in actions: _commands = _commands.store_ref( serialize_command(action, response_address=wallet.address) ) await perform_action(wallet_settings, _commands.end_cell()) if __name__ == "__main__": run(main())