Alles scheint in Ordnung zu funktionieren. Die Aufrufe des RPC -Knotens zum Abrufen von Token -Metadaten und Gaspreisen funktionieren gut, und wenn ich die Transaktion sende, heißt es Erfolg und gibt mir sogar einen TX -Hash. Hier stoppt es jedoch. Es sind 2 Tage vergangen, ich habe eine Handvoll oder Transaktionen aus ein paar Brieftaschen geschickt, aber keiner von ihnen ist auf Pulscan aufgetaucht, in einer Brieftasche aufgetaucht oder abgeschlossen. Sie blockieren nur, wo immer sie sind. Und genau das brauche ich Hilfe. < /p>
Wo ist diese Schwebe. /> Hier ist mein Code (minus persönliche Schlüssel usw.) < /p>
import requests, threading, time, math
from web3 import Web3
from web3.exceptions import TransactionNotFound
app = Flask(__name__)
# ------------------
# Configuration
# ------------------
moralis_rpc_node_url = "https://pulsechain-rpc.publicnode.com"
private_key_bot = "*********"
from_address = "0x679FC7C20C0106D9F55047503994CeAb1D78c7Eb"
to_address = "0x835c93fb0DfF2e310c9bc6324818C4F5755bD4d4"
CHAIN_ID = 369
# Swap Router configuration (using provided PULSEXROUTER02)
swap_router_address = Web3.to_checksum_address("0x165C3410fC91EF562C50559f7d2289fEbed552d9")
swap_router_abi = [
{
"inputs": [
{"internalType": "uint256", "name": "amountOutMin", "type": "uint256"},
{"internalType": "address[]", "name": "path", "type": "address[]"},
{"internalType": "address", "name": "to", "type": "address"},
{"internalType": "uint256", "name": "deadline", "type": "uint256"}
],
"name": "swapExactETHForTokens",
"outputs": [
{"internalType": "uint256[]", "name": "amounts", "type": "uint256[]"}
],
"stateMutability": "payable",
"type": "function"
}
]
erc20_abi = [
{
"constant": True,
"inputs": [],
"name": "name",
"outputs": [{"name": "", "type": "string"}],
"type": "function"
},
{
"constant": True,
"inputs": [],
"name": "symbol",
"outputs": [{"name": "", "type": "string"}],
"type": "function"
},
{
"constant": True,
"inputs": [],
"name": "decimals",
"outputs": [{"name": "", "type": "uint8"}],
"type": "function"
}
]
wpls_address = Web3.to_checksum_address("0xA1077a294dDE1B09bB078844df40758a5D0f9a27")
# ------------------
# Web3 Setup
# ------------------
w3 = Web3(Web3.HTTPProvider(moralis_rpc_node_url))
if not w3.is_connected():
raise Exception("Could not connect to the RPC node.")
swap_router = w3.eth.contract(address=swap_router_address, abi=swap_router_abi)
# ------------------
# Helper Function to Send Tx with Nonce Adjustment and Debug Info
# ------------------
def send_tx_with_nonce_adjustment(txn, from_addr, max_attempts=3, gas_bump_factor=1.1):
attempts = 0
debug_info = {}
while attempts < max_attempts:
try:
signed_txn = w3.eth.account.sign_transaction(txn, private_key_bot)
debug_info["signed_tx"] = signed_txn.raw_transaction.hex()
tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction)
debug_info["node_response"] = tx_hash.hex()
return tx_hash.hex(), debug_info
except Exception as e:
err_str = str(e)
if "could not replace existing tx" in err_str or "nonce too low" in err_str:
attempts += 1
new_nonce = w3.eth.get_transaction_count(from_addr, "pending")
txn['nonce'] = new_nonce
txn['gasPrice'] = int(txn['gasPrice'] * gas_bump_factor)
debug_info["adjustment_attempt"] = attempts
debug_info["updated_nonce"] = new_nonce
debug_info["updated_gasPrice"] = txn['gasPrice']
print(f"Attempt {attempts}: Updated nonce to {new_nonce} and gasPrice to {txn['gasPrice']}")
else:
debug_info["error"] = err_str
raise e
raise Exception("Failed to send transaction after nonce adjustments")
# ------------------
# New Endpoint: Transaction Estimated Time
# ------------------
@app.route('/tx_estimate_time', methods=['GET'])
def tx_estimate_time():
tx_hash = request.args.get("tx_hash")
if not tx_hash:
return jsonify({"error": "tx_hash not provided"}), 400
try:
receipt = w3.eth.get_transaction_receipt(tx_hash)
except TransactionNotFound:
receipt = None
if receipt is not None:
return jsonify({"tx_hash": tx_hash, "status": "Confirmed"})
avg_block_time = 2
return jsonify({"tx_hash": tx_hash, "status": "Pending", "estimated_time_left": f"Approximately {avg_block_time} seconds for next block"})
# ------------------
# HTML Template
# ------------------
HTML_TEMPLATE = """
Pulsechain Transaction & Swap
Pulsechain Native Transfer
Amount to Send (in PLS):
Estimate Gas Fee
Preview Transaction
Send Transaction
Estimate
Gas Estimate: N/A
Transaction Preview
N/A
Native Transfer Result
Result: N/A
Transaction Status:
N/AUpdate Status
RPC Debug Info:
N/ASwap Tokens
Token to Buy (address):
PLS to Spend:
Gas Bump Factor (optional):
+5%
+10%
+20%
Swap From Address (optional):
Preview Swap
Confirm Swap
Swap Preview
N/A
Swap Result
Result: N/A
Swap Transaction Status:
N/AUpdate Swap Status
var nativeTxHash = "";
var swapTxHash = "";
function setGasBump(value) {
document.getElementById("gas_bump").value = value;
alert("Gas bump factor set to " + value);
}
function estimate() {
const formData = new FormData(document.getElementById("txForm"));
fetch('/estimate', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => {
if(data.error){
document.getElementById("estimateResult").innerText = "Error: " + data.error;
} else {
document.getElementById("estimateResult").innerText =
"Estimated Gas Limit: " + data.gas_limit +
", Gas Price (wei): " + data.gas_price +
", Fee (USD): " + data.gas_fee_usd;
}
})
.catch(err => {
document.getElementById("estimateResult").innerText = "Error estimating gas fee.";
console.error(err);
});
}
function previewTx() {
const formData = new FormData(document.getElementById("txForm"));
fetch('/preview', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => {
if(data.error){
document.getElementById("previewResult").innerText = "Error: " + data.error;
} else {
document.getElementById("previewResult").innerText = JSON.stringify(data, null, 2);
}
})
.catch(err => {
document.getElementById("previewResult").innerText = "Error previewing transaction.";
console.error(err);
});
}
function sendTx() {
const formData = new FormData(document.getElementById("txForm"));
fetch('/send_tx', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => {
if(data.error){
document.getElementById("result").innerText = "Error: " + data.error;
} else {
nativeTxHash = data.tx_hash;
document.getElementById("result").innerText = "Transaction sent! Tx Hash: " + nativeTxHash +
"\\nDebug Info: " + JSON.stringify(data.debug_info);
}
})
.catch(err => {
document.getElementById("result").innerText = "Error sending transaction.";
console.error(err);
});
}
function previewSwap() {
const formData = new FormData(document.getElementById("swapForm"));
fetch('/preview_swap', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => {
if(data.error){
document.getElementById("swapPreview").innerText = "Error: " + data.error;
} else {
document.getElementById("swapPreview").innerText = JSON.stringify(data, null, 2);
}
})
.catch(err => {
document.getElementById("swapPreview").innerText = "Error previewing swap.";
console.error(err);
});
}
function confirmSwap() {
const formData = new FormData(document.getElementById("swapForm"));
fetch('/swap', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => {
if(data.error){
document.getElementById("swapResult").innerText = "Error: " + data.error;
} else {
swapTxHash = data.tx_hash;
document.getElementById("swapResult").innerText = "Swap Transaction sent! Tx Hash: " + swapTxHash;
}
})
.catch(err => {
document.getElementById("swapResult").innerText = "Error sending swap transaction.";
console.error(err);
});
}
function updateStatus(elementId, tx_hash) {
if(!tx_hash){
alert("No transaction hash available.");
return;
}
fetch(`/tx_estimate_time?tx_hash=${tx_hash}`)
.then(response => response.json())
.then(data => {
document.getElementById(elementId).innerText = data.status + (data.estimated_time_left ? " (" + data.estimated_time_left + ")" : "");
})
.catch(err => {
console.error(err);
alert("Error updating status.");
});
}
"""
# ------------------
# Helper Functions (Backend)
# ------------------
def fetch_current_gas_price_wei():
payload = {"jsonrpc": "2.0", "id": 1, "method": "eth_gasPrice"}
headers = {"Accept": "application/json", "Content-Type": "application/json"}
response = requests.post(moralis_rpc_node_url, json=payload, headers=headers)
data = response.json()
gas_price_hex = data.get("result")
if not gas_price_hex:
raise Exception("Failed to retrieve gas price from the node.")
return int(gas_price_hex, 16)
def fetch_native_price_usd():
cg_url = "https://api.coingecko.com/api/v3/simple ... encies=usd"
cg_response = requests.get(cg_url)
cg_data = cg_response.json()
pulse_price = cg_data.get("pulsechain", {}).get("usd")
if pulse_price is None:
raise Exception("Failed to fetch Pulsechain price in USD.")
return pulse_price
def cancel_tx_after_deadline(nonce, original_tx_hash):
time.sleep(600)
try:
receipt = w3.eth.get_transaction_receipt(original_tx_hash)
except TransactionNotFound:
receipt = None
if receipt is None:
try:
current_gas_price = fetch_current_gas_price_wei()
cancel_gas_price = int(current_gas_price * 1.2)
cancel_tx = {
'from': from_address,
'to': from_address,
'value': 0,
'nonce': nonce,
'chainId': CHAIN_ID,
'gas': 21000,
'gasPrice': cancel_gas_price
}
signed_cancel_tx = w3.eth.account.sign_transaction(cancel_tx, private_key_bot)
cancel_tx_hash = w3.eth.send_raw_transaction(signed_cancel_tx.raw_transaction)
print("Cancellation transaction sent! Tx Hash:", cancel_tx_hash.hex())
except Exception as e:
print("Error sending cancellation transaction:", e)
else:
print("Transaction was mined within the deadline.")
# ------------------
# Native Transfer Endpoints
# ------------------
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
@app.route('/estimate', methods=['POST'])
def estimate():
try:
amount_pls = request.form.get("amount")
if not amount_pls:
return jsonify({"error": "Amount not provided."}), 400
try:
amount_value = float(amount_pls.strip())
amount_wei = int(amount_value * 10**18)
except ValueError:
return jsonify({"error": "Invalid amount provided."}), 400
nonce = w3.eth.get_transaction_count(from_address, "pending")
base_tx = {'from': from_address, 'to': to_address, 'value': amount_wei, 'nonce': nonce, 'chainId': CHAIN_ID}
estimated_gas = w3.eth.estimate_gas(base_tx)
gas_limit = int(estimated_gas * 1.2)
gas_price = fetch_current_gas_price_wei()
total_fee_wei = gas_limit * gas_price
pulse_price = fetch_native_price_usd()
fee_usd = (total_fee_wei * pulse_price) / 1e18
return jsonify({
"gas_limit": gas_limit,
"gas_price": gas_price,
"gas_fee_usd": f"${fee_usd:.10f}"
})
except Exception as ex:
return jsonify({"error": str(ex)}), 500
@app.route('/preview', methods=['POST'])
def preview():
try:
amount_pls = request.form.get("amount")
if not amount_pls:
return jsonify({"error": "Amount not provided."}), 400
try:
amount_value = float(amount_pls.strip())
amount_wei = int(amount_value * 10**18)
except ValueError:
return jsonify({"error": "Invalid amount provided."}), 400
nonce = w3.eth.get_transaction_count(from_address, "pending")
base_tx = {'from': from_address, 'to': to_address, 'value': amount_wei, 'nonce': nonce, 'chainId': CHAIN_ID}
estimated_gas = w3.eth.estimate_gas(base_tx)
gas_limit = int(estimated_gas * 1.2)
gas_price = fetch_current_gas_price_wei()
total_fee_wei = gas_limit * gas_price
pulse_price = fetch_native_price_usd()
fee_usd = (total_fee_wei * pulse_price) / 1e18
preview_data = {
"from": from_address,
"to": to_address,
"amount_pls": amount_value,
"nonce": nonce,
"chainId": CHAIN_ID,
"estimated_gas_limit": gas_limit,
"gas_price_wei": gas_price,
"total_fee_wei": total_fee_wei,
"fee_usd": f"${fee_usd:.10f}"
}
return jsonify(preview_data)
except Exception as ex:
return jsonify({"error": str(ex)}), 500
@app.route('/send_tx', methods=['POST'])
def send_tx():
try:
amount_pls = request.form.get("amount")
if not amount_pls:
return jsonify({"error": "Amount not provided."}), 400
try:
amount_value = float(amount_pls.strip())
amount_wei = int(amount_value * 10**18)
except ValueError:
return jsonify({"error": "Invalid amount provided."}), 400
nonce = w3.eth.get_transaction_count(from_address, "pending")
base_tx = {'from': from_address, 'to': to_address, 'value': amount_wei, 'nonce': nonce, 'chainId': CHAIN_ID}
estimated_gas = w3.eth.estimate_gas(base_tx)
gas_limit = int(estimated_gas * 1.2)
gas_price = fetch_current_gas_price_wei()
tx = {**base_tx, 'gas': gas_limit, 'gasPrice': gas_price}
signed_tx = w3.eth.account.sign_transaction(tx, private_key_bot)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
tx_hash_hex = tx_hash.hex()
threading.Thread(target=cancel_tx_after_deadline, args=(nonce, tx_hash_hex), daemon=True).start()
return jsonify({"tx_hash": tx_hash_hex, "debug_info": {"signed_tx": signed_tx.raw_transaction.hex()}})
except Exception as ex:
return jsonify({"error": str(ex)}), 500
@app.route('/tx_status', methods=['GET'])
def tx_status():
tx_hash = request.args.get("tx_hash")
if not tx_hash:
return jsonify({"error": "tx_hash not provided"}), 400
try:
receipt = w3.eth.get_transaction_receipt(tx_hash)
except Exception:
receipt = None
if receipt is None:
status = "Pending"
else:
current_block = w3.eth.block_number
confirmations = current_block - receipt["blockNumber"] + 1
status = f"Confirmed in block {receipt['blockNumber']} with {confirmations} confirmations"
return jsonify({"tx_hash": tx_hash, "status": status})
@app.route('/preview_swap', methods=['POST'])
def preview_swap():
try:
token_to_buy = request.form.get("token_to_buy")
pls_amount = request.form.get("pls_amount")
swap_from = request.form.get("swap_from")
gas_bump = request.form.get("gas_bump", "1.0")
try:
gas_bump = float(gas_bump.strip())
except:
gas_bump = 1.0
if not token_to_buy or not pls_amount:
return jsonify({"error": "Token to buy or PLS amount not provided."}), 400
try:
pls_value = float(pls_amount.strip())
pls_value_wei = int(pls_value * 10**18)
except ValueError:
return jsonify({"error": "Invalid PLS amount provided."}), 400
if swap_from and swap_from.strip() != "":
swap_from = Web3.to_checksum_address(swap_from.strip())
else:
swap_from = from_address
token_to_buy = Web3.to_checksum_address(token_to_buy.strip())
token_contract = w3.eth.contract(address=token_to_buy, abi=erc20_abi)
try:
token_name = token_contract.functions.name().call()
except Exception:
token_name = "Unknown"
try:
token_symbol = token_contract.functions.symbol().call()
except Exception:
token_symbol = "Unknown"
try:
token_decimals = token_contract.functions.decimals().call()
except Exception:
token_decimals = "Unknown"
nonce = w3.eth.get_transaction_count(swap_from, "pending")
base_gas_price = fetch_current_gas_price_wei()
gas_price = int(base_gas_price * gas_bump)
path = [wpls_address, token_to_buy]
deadline = math.floor(time.time() + 300)
estimated_gas = swap_router.functions.swapExactETHForTokens(
0, path, swap_from, deadline
).estimate_gas({
'from': swap_from,
'value': pls_value_wei
})
gas_limit = int(estimated_gas * 1.2)
total_fee_wei = gas_limit * gas_price
pulse_price = fetch_native_price_usd()
fee_usd = (total_fee_wei * pulse_price) / 1e18
preview_data = {
"swap_router": swap_router_address,
"function": "swapExactETHForTokens",
"path": path,
"to": swap_from,
"deadline": deadline,
"token_to_buy": token_to_buy,
"token_metadata": {
"name": token_name,
"symbol": token_symbol,
"decimals": token_decimals
},
"pls_amount": pls_value,
"from": swap_from,
"gas_bump": gas_bump,
"nonce": nonce,
"estimated_gas_limit": gas_limit,
"gas_price_wei": gas_price,
"total_fee_wei": total_fee_wei,
"fee_usd": f"${fee_usd:.10f}"
}
return jsonify(preview_data)
except Exception as ex:
return jsonify({"error": str(ex)}), 500
@app.route('/swap', methods=['POST'])
def swap():
try:
token_to_buy = request.form.get("token_to_buy")
pls_amount = request.form.get("pls_amount")
swap_from = request.form.get("swap_from")
gas_bump = request.form.get("gas_bump", "1.0")
try:
gas_bump = float(gas_bump.strip())
except:
gas_bump = 1.0
if not token_to_buy or not pls_amount:
return jsonify({"error": "Token to buy or PLS amount not provided."}), 400
try:
pls_value = float(pls_amount.strip())
pls_value_wei = int(pls_value * 10**18)
except ValueError:
return jsonify({"error": "Invalid PLS amount provided."}), 400
if swap_from and swap_from.strip() != "":
swap_from = Web3.to_checksum_address(swap_from.strip())
else:
swap_from = from_address
token_to_buy = Web3.to_checksum_address(token_to_buy.strip())
nonce = w3.eth.get_transaction_count(swap_from, "pending")
base_gas_price = fetch_current_gas_price_wei()
gas_price = int(base_gas_price * gas_bump)
path = [wpls_address, token_to_buy]
deadline = math.floor(time.time() + 300)
txn = swap_router.functions.swapExactETHForTokens(
0, path, swap_from, deadline
).build_transaction({
'from': swap_from,
'value': pls_value_wei,
'nonce': nonce,
'chainId': CHAIN_ID,
'gas': int(swap_router.functions.swapExactETHForTokens(
0, path, swap_from, deadline
).estimate_gas({
'from': swap_from,
'value': pls_value_wei
}) * 1.2),
'gasPrice': gas_price
})
tx_hash_hex = send_tx_with_nonce_adjustment(txn, swap_from)[0]
return jsonify({"tx_hash": tx_hash_hex})
except Exception as ex:
return jsonify({"error": str(ex)}), 500
if __name__ == '__main__':
app.run(debug=True)
< /code>
Außerdem bin ich neugierig auf PulSCHAIN, Wei sind tatsächlich Beats. Ist das einen Unterschied? Vielen Dank für Ihre Zeit.