3

I am still new to this and have been trying to figure this out for some time now so any help you can offer would really be greatly appreciated.

I see quite a bit of literature and tutorials on how to transfer Sol using Solana.py (which no longer works) and I have been combing through the Solders docs trying to put it together but can't get it.

Does anyone have an idea of how a function to transfer Sol from one wallet to another using Solders would look?

https://kevinheavey.github.io/solders/api_reference/transaction.html

Thank you for all your help!

4 Answers 4

2

Here's an example from the solana-py docs (lightly edited):

from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solana.rpc.api import Client
from solders.system_program import TransferParams, transfer
from solana.transaction import Transaction
sender = Keypair.from_bytes(b"") # replace with a real keypair
receiver = Keypair().pubkey()
transfer_ix = transfer(TransferParams(from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1_000_000))
txn = Transaction().add(transfer_ix)
solana_client = Client("http://localhost:8899") # replace with a real RPC
solana_client.send_transaction(txn, sender)
1
  • Thank you so much. After playing with this for awhile I finally got it to work. I really appreciate your help. Commented Mar 21, 2023 at 8:28
1

I will be changing this message as I can not delete accepted answers

4
  • Thank you so much. I really appreciate your help. Commented Mar 17, 2023 at 4:22
  • Is VSCode giving you trouble with the Solders types or something?
    – KevinH
    Commented Mar 17, 2023 at 13:44
  • not vscode, mypy
    – gattytto
    Commented Mar 17, 2023 at 14:18
  • Yeah, I get "TypeError: Transaction.__new__() missing 3 required positional arguments: 'from_keypairs', 'message', and 'recent_blockhash'" when I run your code. Commented Mar 19, 2023 at 10:09
0

You can use the solders library to send token. Here is a sample code to swap token between SOL and USDC using Jupiter Quote function. This could be useful to anybody who uses the solders library to send a transaction.

import json
import requests
from solders.transaction import Transaction
from solders.pubkey import Pubkey
from solana.rpc.api import Client
from solders.system_program import TransferParams, transfer
from solders.message import Message
from solders.keypair import Keypair




# inputs
amount = 1.0  # Amount to swap (in SOL)
input_token_address = "So11111111111111111111111111111111111111112"  # Replace with your from token addess
output_token_address = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" # Replace with your to token address
private_key_string = "REPLACE WITH YOUR PRIVATE KEY" # Your Private Key in base58 (import it from phantom)



client = Client("https://api.devnet.solana.com")


# Create the sender Keypair from private key bytes
sender =  Keypair.from_base58_string(private_key_string)

# Generate a keypair for the sender (or load from a private key)

# Print the sender's public key
print(f"Sender public key: {sender.pubkey()}")

# Example: Swap SOL for USDC
  # Token to swap to


# Step 2: Get the swap route from Jupiter API
JUPITER_API_URL = f"https://quote-api.jup.ag/v6/quote?inputMint={input_token_address}" \
                  f"&outputMint={output_token_address}&amount={int(amount * 10**9)}&slippageBps=50"

# Fetch the best swap route from Jupiter API
response = requests.get(JUPITER_API_URL)
quote_data = response.json()

sender_balance = client.get_balance(sender.pubkey())


# Step 3: Extract transaction instructions from the quote response
route_plan = quote_data['routePlan']
if len(route_plan) == 0:
    print("No route found!")
    exit()

# The routePlan is a list of dictionaries, each containing the swap info
swap_info = route_plan[0]['swapInfo']
input_mint = swap_info['inputMint']
output_mint = swap_info['outputMint']
in_amount = int(swap_info['inAmount'])
out_amount = int(swap_info['outAmount'])
amm_key = Pubkey.from_string(swap_info['ammKey']) 
# swap_instructions = swap_info['transaction']['instructions']

# Step 4: Prepare the transaction to perform the swap

instruction = transfer((TransferParams(from_pubkey=sender.pubkey(), to_pubkey=Pubkey.from_string(output_mint), lamports=1_000_000)))




# Add the instructions to the transaction
# for instruction in swap_instructions:
#     # Ensure each instruction is properly formatted
#     instruction_data = instruction['data']  # Fetch instruction data
#     keys = instruction['keys']  # Fetch the keys for the instruction (signers, accounts)
    
#     # Add instruction to the transaction (Note: You'll need to convert this into Solana transaction format)
#     transaction.add(instruction_data)

# Step 5: Get recent blockhash from Solana
blockhash_response = client.get_latest_blockhash()
recent_blockhash = blockhash_response.value.blockhash
message = Message(instructions=[instruction], payer=sender.pubkey())
transaction = Transaction(
    from_keypairs=[sender],  # List of keypairs that will sign the transaction
    message=message,
    recent_blockhash=recent_blockhash
)


# Step 6: Sign the transaction with the sender's keypair
transaction.sign([sender],recent_blockhash)



# Step 7: Send the transaction to Solana
send_response = client.send_transaction(transaction)

# Step 8: Print the transaction signature
print(f"Swap transaction sent! Transaction signature: {send_response}")


-1

The solders code seems a bit raw currently. There seems to be instructions only for SystemProgram. I'm not sure what are the other design ideas being but Solana clients For transferring SOL you need to create an instruction of the SystemProgram, place it to a transaction, sign it (if needed, signature of the wallet could be added automatically, not sure though how it is here) and send it to network.

Based on the documentation I tried like this

import json
import requests
import json
from solana.rpc.api import Client
from solders.message import Message # type: ignore
from solders.transaction import Transaction # type: ignore
from solders.system_program import transfer, TransferParams
from solders.pubkey import Pubkey as PublicKey # type: ignore
from solders.keypair import Keypair # type: ignore
from solders.hash import Hash # type: ignore
from solders.commitment_config import CommitmentLevel # type: ignore
from solders.rpc.config import RpcSendTransactionConfig # type: ignore
from solders.rpc.requests import SendLegacyTransaction # type: ignore

SOL_TO_LAMPORTS = 1000000000

to = PublicKey.from_string("7xUpLb33Bp3yGKVsARWzAQiYanXL1ujx3136qoJCLWXN")
instruction = transfer(
    TransferParams(
        from_pubkey = loaded_keypair.pubkey(),
        to_pubkey = PublicKey.from_string("<some_pubkey_base58"),
        lamports = SOL_TO_LAMPORTS
    )
)

# solana api to get recent blockhash
solana_client = Client(args.rpc, timeout=30)
recent_blockhash = solana_client.get_recent_blockhash()
blockhash = Hash.from_string(recent_blockhash['result']['value']['blockhash'])

message = Message([instruction], loaded_keypair.pubkey())
tx = Transaction([loaded_keypair], message, blockhash)

commitment = CommitmentLevel.Confirmed
config = RpcSendTransactionConfig(preflight_commitment=commitment)
req = SendLegacyTransaction(tx, config)
as_json = req.to_json()  # as_json returns a string not a json

print('sending', SOL_TO_LAMPORTS, 'to', to)
res = requests.post(args.rpc, json=json.loads(as_json))
print(res.json())

For sending there seems not being a direct integration to solana.rpc.api.Client and the transaction can be get as a JSON to be sent via HTTP request.

1
  • Ok, thanks @kevinh for the clarification of the usage.
    – chalda
    Commented Mar 21, 2023 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.