import traceback
from flask import Flask, request, jsonify
from solana.rpc.api import Client
from solana.rpc.api import Keypair
from solana.rpc.commitment import Confirmed
from solana.rpc.types import TokenAccountOpts
from solana.rpc.types import TxOpts
from solana.transaction import Transaction
from solders.keypair import Keypair # type: ignore
from solders.pubkey import Pubkey # type: ignore
from spl.token.client import Token
from spl.token.constants import TOKEN_PROGRAM_ID
from spl.token.instructions import get_associated_token_address
from spl.token.instructions import transfer_checked
from spl.token.instructions import TransferCheckedParams
import spl.token.instructions as spl_token
import base58
import time
import json
import logging
# Constants
LAMPORTS = 1000000000
RPC_URL = 'https://api.mainnet-beta.solana.com' # Hardcoded RPC URL
app = Flask(__name__)
# Configure logging
logging.basicConfig(level=logging.DEBUG)
# Function to get token account details
def get_tkn_acct(wallet_addr, tkn_addr):
client = Client(RPC_URL)
wallet_pubkey = wallet_addr # This should be a bytes object
tkn_pubkey = tkn_addr # This should also be a bytes object
try:
tkn_acct_data = client.get_token_accounts_by_owner(wallet_pubkey, TokenAccountOpts(tkn_pubkey))
# Check if token account data is not empty
if not tkn_acct_data.value:
logging.error("No token accounts found for the given address.")
return {'tkn_acct_pubkey': None, 'tkn_bal': 0, 'tkn_dec': 0}
tkn_acct_pubkey = tkn_acct_data.value[0].pubkey
balance_info = Token(
conn=client,
pubkey=tkn_pubkey,
program_id=TOKEN_PROGRAM_ID,
payer=client
)
balance_info = balance_info.get_balance(tkn_acct_pubkey)
print(balance_info)
return {
'tkn_acct_pubkey': tkn_acct_pubkey,
'tkn_bal': balance_info.value.ui_amount,
'tkn_dec': balance_info.value.decimals
}
except Exception as e:
logging.error("Error getting token account details: %s\n%s", str(e), traceback.format_exc())
return {'tkn_acct_pubkey': None, 'tkn_bal': 0, 'tkn_dec': 0}
# Endpoint to send tokens
@app.route('/send_token', methods=['POST'])
def send_tkn():
data = request.json
try:
src_key = data['src_key']
dest_addr = data['dest_addr']
tkn_addr = data['tkn_addr']
tkn_amt = data['tkn_amt']
client = Client(RPC_URL)
tkn_pubkey = Pubkey.from_string(tkn_addr)
src_keypair = Keypair.from_base58_string(src_key)
src_pubkey = src_keypair.pubkey()
dest_pubkey = Pubkey.from_string(dest_addr)
blockhash = client.get_latest_blockhash().value.blockhash
txn = Transaction(fee_payer=src_pubkey, recent_blockhash=blockhash)
spl_client = Token(conn=client, pubkey=tkn_pubkey, program_id=TOKEN_PROGRAM_ID, payer=src_keypair)
src_bal = client.get_balance(src_pubkey).value / LAMPORTS
src_tkn_data = get_tkn_acct(src_pubkey, tkn_pubkey)
if not src_tkn_data['tkn_acct_pubkey']:
return jsonify({'error': 'Source account does not have that token'}), 400
dest_tkn_acct_pubkey = get_associated_token_address(dest_pubkey, tkn_pubkey)
try:
client.get_token_account_balance(dest_tkn_acct_pubkey)
except Exception as e:
logging.warning("Destination token account does not exist: %s\n%s", str(e), traceback.format_exc())
txn1 = Transaction()
create_txn = spl_token.create_associated_token_account(payer=src_pubkey ,owner=dest_addr,min=tkn_pubkey)
txn1.add(create_txn)
client.send_transaction(txn1, src_keypair) # No opts here, or use correct parameter structure
time.sleep(1)
dest_tkn_acct_pubkey = create_txn.keys[1].pubkey
send_amt_lamps = int(tkn_amt * 10**int(src_tkn_data['tkn_dec']))
xfr_ins = transfer_checked(
TransferCheckedParams(
program_id=TOKEN_PROGRAM_ID,
source=src_tkn_data['tkn_acct_pubkey'],
mint=tkn_pubkey,
dest=dest_tkn_acct_pubkey,
owner=src_pubkey,
amount=send_amt_lamps,
decimals=src_tkn_data['tkn_dec']
)
)
txn.add(xfr_ins)
time.sleep(1)
# Prepare for sending transaction
resp = client.send_transaction(txn, src_keypair,opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
# resp = client.send_transaction(txn,src_keypair)
# Convert response to JSON and handle the response
resp = resp.to_json()
response = json.loads(resp)
if 'error' in response:
logging.error("Error sending transaction: %s\n%s", response['error'], traceback.format_exc())
return jsonify({'error': response['error']}), 400
txn_hash = response['result']
return jsonify({'status': 'success', 'transaction_hash': txn_hash})
except KeyError as ke:
logging.error("Missing key in request data: %s\n%s", str(ke), traceback.format_exc())
return jsonify({'error': f'Missing key: {str(ke)}'}), 400
except Exception as e:
logging.error("An error occurred: %s\n%s", str(e), traceback.format_exc())
return jsonify({'error': str(e)}), 500
# Starting the Flask server
if __name__ == '__main__':
app.run(debug=True, port=5000)
ERROR:root:An error occurred: Client.send_transaction() got multiple values for argument 'opts'
Traceback (most recent call last):
File "C:\Users\Himan\Desktop\API\transfertoken.py", line 125, in send_tkn
resp = client.send_transaction(txn, src_keypair,opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Client.send_transaction() got multiple values for argument 'opts'