# Sending transactions

We can stand out two kinds of sending transactions from the Terminal. Although from user's point of view, it looks like one wholeness, each functionality is backed by different, complex pieces of code. The two kinds are:

* Sending SOL
* Sending SPL tokens

To perform the transfer user is obligated to make some necessary choices:

* Enter recipient's public key
* Enter amount he/she would like to send
* Select token from menu

<figure><img src="https://3670432737-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwJuUkk9Y24vVhd9jDCn1%2Fuploads%2F1LrZNk2xrtrVxHwdJK06%2FXXX.png?alt=media&#x26;token=e258f02a-3c78-4bb6-bfab-9b33e59a3482" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Using default, public Solana endpoint ("<https://api.mainnet-beta.solana.com>") isn't recommended. This endpoint doesn't allow the program to get the execute confirmation (among others disadvantages), so always make sure before you repeat a transfer. Read more in "Endpoints" section.
{% endhint %}

Part of code responsible for sending Solana:

```python
    def send_solana(self, private_key_base58, recipient_public_key, amount):
        client = Client(self.endpoints['send_solana'])
        try:
            private_key_bytes = base58.b58decode(private_key_base58)
            keypair = Keypair.from_secret_key(private_key_bytes)
            recipient_pubkey = PublicKey(recipient_public_key)
            transaction = Transaction().add(
                transfer(
                    TransferParams(
                        from_pubkey=keypair.public_key,
                        to_pubkey=recipient_pubkey,
                        lamports=int(amount * 1e9)
                    )
                )
            )
            response = client.send_transaction(transaction, keypair, opts=TxOpts(skip_confirmation=False))
            if response.get('result'):
            
            (...)
```

\
Part of code necessary to sending SPL tokens:

```python
def send_token(self, private_key_base58, recipient_public_key, token_mint_address, amount, decimals):
        client = Client(self.endpoints['send_token'])
        try:
            private_key_bytes = base58.b58decode(private_key_base58)
            sender_keypair = Keypair.from_secret_key(private_key_bytes)
            sender_public_key = sender_keypair.public_key
            recipient_public_key = PublicKey(recipient_public_key)
            token_mint = PublicKey(token_mint_address)

            sender_token_account = get_associated_token_address(sender_public_key, token_mint)
            recipient_token_account = get_associated_token_address(recipient_public_key, token_mint)

            recipient_account_info = client.get_account_info(recipient_token_account)
            transaction = Transaction()

            if recipient_account_info['result']['value'] is None:
                create_assoc_instr = create_associated_token_account(
                    payer=sender_public_key,
                    owner=recipient_public_key,
                    mint=token_mint
                )
                transaction.add(create_assoc_instr)

            amount_int = int(amount * (10 ** decimals))

            transfer_params = TransferCheckedParams(
                program_id=TOKEN_PROGRAM_ID,
                source=sender_token_account,
                mint=token_mint,
                dest=recipient_token_account,
                owner=sender_public_key,
                amount=amount_int,
                decimals=decimals
            )

            transfer_instr = transfer_checked(transfer_params)
            transaction.add(transfer_instr)

            response = client.send_transaction(transaction, sender_keypair, opts=TxOpts(skip_confirmation=False))
            if response.get('result'):
            
            (...)
```

\
Universal function:

```python
def send_transaction(self, public_key, private_key_base58):
        recipient = self.recipient_entry.get()
        try:
            amount = float(self.amount_entry.get())
            token_info = self.selected_send_token_info
            if token_info is None:
                self.show_message("Selected token not found.", "Error")
                return

            symbol = token_info['symbol']
            if symbol == 'SOL':
                if amount > token_info['amount']:
                    self.show_message("Insufficient SOL balance. Please enter a valid amount.", "Error")
                    return
                else:
                    self.show_processing_indicator()
                    threading.Thread(target=self.send_solana_thread, args=(private_key_base58, recipient, amount), daemon=True).start()
            else:
                if amount > token_info['amount']:
                    self.show_message("Insufficient token balance. Please enter a valid amount.", "Error")
                    return
                else:
                    self.show_processing_indicator()
                    threading.Thread(target=self.send_token_thread, args=(private_key_base58, recipient, token_info, amount), daemon=True).start()
        except ValueError:
            self.show_message("Invalid amount. Please enter a number.", "Error")
```
