Dogecoin Spend Script

Dogecoin Spend Script

I created this python script to send Doge from a wallet in which you only have a private key because you I couldn't find wallets that let you do that. They all required a seed phrase. Enjoy

import requests
import hashlib
import ecdsa
import base58
import struct
from bitcoin.core import lx, COIN, CMutableTransaction, CMutableTxOut, CMutableTxIn, b2x
from bitcoin.wallet import P2PKHBitcoinAddress

# Dogecoin network constants
DOGE_NETWORK = {
    'pubKeyHash': 0x1e,
    'wif': 0x9e,
}

API_URL = 'https://api.blockcypher.com/v1/doge/main'

def get_balance(address):
    try:
        response = requests.get(f'{API_URL}/addrs/{address}?unspentOnly=true')
        response.raise_for_status()
        utxos = response.json().get('txrefs', [])
        total_balance = sum(utxo['value'] for utxo in utxos) / 1e8
        return total_balance, utxos
    except requests.RequestException as e:
        print(f'Error fetching balance: {e}')
        return 0, []

def wif_to_private_key(wif):
    decoded = base58.b58decode(wif)
    if decoded[0] != DOGE_NETWORK['wif']:
        raise ValueError("Invalid WIF version byte for Dogecoin.")
    private_key = decoded[1:-4]
    if len(private_key) == 33 and private_key[-1] == 0x01:  # Compressed key
        private_key = private_key[:-1]
    if len(private_key) != 32:
        raise ValueError("Invalid length of private key.")
    return private_key

def private_key_to_public_key(private_key_bytes):
    sk = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1)
    vk = sk.verifying_key
    public_key_bytes = b'\x04' + vk.to_string()  # Uncompressed public key
    return public_key_bytes

def public_key_to_address(public_key_bytes):
    sha256 = hashlib.sha256(public_key_bytes).digest()
    ripemd160 = hashlib.new('ripemd160', sha256).digest()
    versioned_payload = bytes([DOGE_NETWORK['pubKeyHash']]) + ripemd160
    checksum = hashlib.sha256(hashlib.sha256(versioned_payload).digest()).digest()[:4]
    address_bytes = versioned_payload + checksum
    return base58.b58encode(address_bytes).decode()

def create_and_send_transaction(private_key_wif, to_address, amount):
    try:
        private_key_bytes = wif_to_private_key(private_key_wif)
        public_key_bytes = private_key_to_public_key(private_key_bytes)
        from_address = public_key_to_address(public_key_bytes)
        balance, utxos = get_balance(from_address)

        if balance == 0:
            raise ValueError("No UTXOs available")
        
        if balance < amount:
            raise ValueError("Insufficient balance")

        tx_ins = [
            CMutableTxIn(lx(utxo['tx_hash']), utxo['tx_output_n'])
            for utxo in utxos
        ]

        tx_out = CMutableTxOut(int(amount * COIN), P2PKHBitcoinAddress(to_address).to_scriptPubKey())

        tx = CMutableTransaction(tx_ins, [tx_out])
        raw_tx = b2x(tx.serialize())

        response = requests.post(f'{API_URL}/txs/push', json={'tx': raw_tx})
        response.raise_for_status()
        tx_hash = response.json().get('tx', {}).get('hash')
        print(f'Transaction sent! TXID: {tx_hash}')
    except Exception as e:
        print(f'Error: {e}')

if __name__ == "__main__":
    private_key = input("Enter your private key (WIF format): ")
    private_key_bytes = wif_to_private_key(private_key)
    public_key_bytes = private_key_to_public_key(private_key_bytes)
    from_address = public_key_to_address(public_key_bytes)
    balance, _ = get_balance(from_address)
    print(f'Wallet balance: {balance} DOGE')
    print(f'Receiving Address: {from_address}')
    
    to_address = input("Enter the recipient's address: ")
    amount = float(input("Enter the amount to send (in Doge): "))
    create_and_send_transaction(private_key, to_address, amount)

Read more