def create_wrapped_native_account( conn: Client, program_id: PublicKey, owner: PublicKey, payer: Account, amount: int, skip_confirmation: bool = False, ) -> PublicKey: """Create and initialize a new account on the special native token mint. :param conn: RPC connection to a solana cluster. :param program_id: SPL Token program account. :param owner: The owner of the new token account. :param payer: The source of the lamports to initialize, and payer of the initialization fees. :param amount: The amount of lamports to wrap. :param skip_confirmation: (optional) Option to skip transaction confirmation. :return: The new token account. If skip confirmation is set to `False`, this method will block for at most 30 seconds or until the transaction is confirmed. """ # Allocate memory for the account balance_needed = Token.get_min_balance_rent_for_exempt_for_account( conn) new_account_public_key, txn, payer, new_account, opts = _TokenCore._create_wrapped_native_account_args( program_id, owner, payer, amount, skip_confirmation, balance_needed) conn.send_transaction(txn, payer, new_account, opts=opts) return new_account_public_key
def create_mint( cls, conn: Client, payer: Account, mint_authority: PublicKey, decimals: int, program_id: PublicKey, freeze_authority: Optional[PublicKey] = None, skip_confirmation: bool = False, ) -> Token: """Create and initialize a token. :param conn: RPC connection to a solana cluster. :param payer: Fee payer for transaction. :param mint_authority: Account or multisig that will control minting. :param decimals: Location of the decimal place. :param program_id: SPL Token program account. :param freeze_authority: (optional) Account or multisig that can freeze token accounts. :param skip_confirmation: (optional) Option to skip transaction confirmation. :return: Token object for the newly minted token. If skip confirmation is set to `False`, this method will block for at most 30 seconds or until the transaction is confirmed. """ # Allocate memory for the account balance_needed = Token.get_min_balance_rent_for_exempt_for_mint(conn) # Construct transaction token, txn, payer, mint_account, opts = _TokenCore._create_mint_args( conn, payer, mint_authority, decimals, program_id, freeze_authority, skip_confirmation, balance_needed, cls) # Send the two instructions conn.send_transaction(txn, payer, mint_account, opts=opts) return cast(Token, token)
def topup(self, api_endpoint, to, amount=None, skip_confirmation=True): """ Send a small amount of native currency to the specified wallet to handle gas fees. Return a status flag of success or fail and the native transaction data. """ msg = "" try: # Connect to the api_endpoint client = Client(api_endpoint) msg += "Initialized client" # List accounts sender_account = Account(self.private_key) dest_account = PublicKey(to) msg += " | Gathered accounts" # List signers signers = [sender_account] # Start transaction tx = Transaction() # Determine the amount to send try: if amount is None: min_rent_reseponse = client.get_minimum_balance_for_rent_exemption( ACCOUNT_LAYOUT.sizeof()) lamports = min_rent_reseponse["result"] else: lamports = int(amount) msg += f" | Fetched lamports: {lamports * 1e-9} SOL" except Exception as e: msg += " | ERROR: couldn't process lamports" raise (e) # Generate transaction transfer_ix = transfer( TransferParams(from_pubkey=sender_account.public_key(), to_pubkey=dest_account, lamports=lamports)) tx = tx.add(transfer_ix) msg += f" | Transferring funds" # Send request try: response = client.send_transaction( tx, *signers, opts=types.TxOpts(skip_confirmation=skip_confirmation)) return json.dumps({ 'status': HTTPStatus.OK, 'msg': f"Successfully sent {lamports * 1e-9} SOL to {to}", 'tx': response.get('result') if skip_confirmation else response['result']['transaction']['signatures'], }) except Exception as e: msg += f" | ERROR: Encountered exception while attempting to send transaction: {e}" raise (e) except Exception as e: return json.dumps({ 'status': HTTPStatus.BAD_REQUEST, 'msg': msg, })
def test_confirm_bad_signature(test_http_client: Client) -> None: """Test that RPCException is raised when trying to confirm an invalid signature.""" with pytest.raises(RPCException) as exc_info: test_http_client.confirm_transaction("foo") err_object = exc_info.value.args[0] assert err_object == { "code": -32602, "message": "Invalid param: WrongSize" }
def mint_to(self, api_endpoint, pool_account, dest, amount, skip_confirmation=True): msg = "" client = Client(api_endpoint) msg += "Initialized client" # Create account objects source_account = Account(self.private_key) signers = [source_account] pool = self.load_binary_option(api_endpoint, pool_account) # List non-derived accounts pool_account = PublicKey(pool_account) dest_account = PublicKey(dest) escrow_mint_account = PublicKey(pool["escrow_mint"]) mint_authority_account = source_account.public_key() payer_account = source_account.public_key() token_account = PublicKey(TOKEN_PROGRAM_ID) tx = Transaction() token_pda_address = get_associated_token_address( dest_account, escrow_mint_account) associated_token_account_ix = create_associated_token_account( payer=payer_account, owner=dest_account, mint=escrow_mint_account, ) tx = tx.add(associated_token_account_ix) mint_to_ix = mint_to( MintToParams( program_id=token_account, mint=escrow_mint_account, dest=token_pda_address, mint_authority=mint_authority_account, amount=int(amount), signers=[mint_authority_account], )) tx = tx.add(mint_to_ix) # Send request try: response = client.send_transaction( tx, *signers, opts=types.TxOpts(skip_confirmation=skip_confirmation)) return json.dumps({ 'status': HTTPStatus.OK, 'msg': msg + f" | MintTo {dest} successful", 'tx': response.get('result') if skip_confirmation else response['result']['transaction']['signatures'], }) except Exception as e: msg += f" | ERROR: Encountered exception while attempting to send transaction: {e}" raise (e)
def create_mint( conn: Client, payer: Account, mint_authority: PublicKey, decimals: int, program_id: PublicKey, freeze_authority: Optional[PublicKey] = None, skip_confirmation: bool = False, ) -> Token: """Create and initialize a token. :param conn: RPC connection to a solana cluster. :param payer: Fee payer for transaction. :param mint_authority: Account or multisig that will control minting. :param decimals: Location of the decimal place. :param program_id: SPL Token program account. :param freeze_authority: (optional) Account or multisig that can freeze token accounts. :param skip_confirmation: (optional) Option to skip transaction confirmation. :return: Token object for the newly minted token. If skip confirmation is set to `False`, this method will block for at most 30 seconds or until the transaction is confirmed. """ mint_account = Account() token = Token(conn, mint_account.public_key(), program_id, payer) # Allocate memory for the account balance_needed = Token.get_min_balance_rent_for_exempt_for_mint(conn) # Construct transaction txn = Transaction() txn.add( sp.create_account( sp.CreateAccountParams( from_pubkey=payer.public_key(), new_account_pubkey=mint_account.public_key(), lamports=balance_needed, space=MINT_LAYOUT.sizeof(), program_id=program_id, ) ) ) txn.add( spl_token.initialize_mint( spl_token.InitializeMintParams( program_id=program_id, mint=mint_account.public_key(), decimals=decimals, mint_authority=mint_authority, freeze_authority=freeze_authority, ) ) ) # Send the two instructions conn.send_transaction( txn, payer, mint_account, opts=TxOpts(skip_confirmation=skip_confirmation, skip_preflight=True) ) return token
def setUpClass(self): print( "\n\nhttps://app.zenhub.com/workspaces/solana-evm-6007c75a9dc141001100ccb8/issues/neonlabsorg/proxy-model.py/245" ) self.account = proxy.eth.account.create() print('account.address:', self.account.address) request_airdrop(self.account.address) self.client = Client(solana_url) wallet = WalletAccount(wallet_path()) self.acc = wallet.get_acc()
class transacton_cost(unittest.TestCase): @classmethod def setUpClass(self): print( "\n\nhttps://app.zenhub.com/workspaces/solana-evm-6007c75a9dc141001100ccb8/issues/neonlabsorg/proxy-model.py/245" ) self.account = proxy.eth.account.create() print('account.address:', self.account.address) request_airdrop(self.account.address) self.client = Client(solana_url) wallet = WalletAccount(wallet_path()) self.acc = wallet.get_acc() @unittest.skip("only for debug") def test_deploy_cost(self): print("\n\ntest_deploy_cost") compiled = compile_source(CONTRACT) id, interface = compiled.popitem() contract = proxy.eth.contract(abi=interface['abi'], bytecode=interface['bin']) trx = proxy.eth.account.sign_transaction( dict(nonce=proxy.eth.get_transaction_count(self.account.address), chainId=proxy.eth.chain_id, gas=987654321, gasPrice=1000000000, to='', value=0, data=contract.bytecode), self.account.key) print("trx_hash", trx.hash.hex()[2:]) balance_pre = int( self.client.get_balance(self.acc.public_key(), commitment=Confirmed)['result']['value']) print("incoming balance {:,}".format(balance_pre).replace(',', ' ')) signature = proxy.eth.send_raw_transaction(trx.rawTransaction) receipt = proxy.eth.wait_for_transaction_receipt(signature) # self.contract = proxy.eth.contract( # address=receipt.contractAddress, # abi=contract.abi # ) balance_post = int( self.client.get_balance(self.acc.public_key(), commitment=Confirmed)['result']['value']) print("outgoing balance {:,}".format(balance_post).replace(',', ' ')) print("cost {:,}".format(balance_pre - balance_post).replace(',', ' '))
def test_http_client_cached_blockhash(docker_services) -> Client: """Test http_client.is_connected.""" http_client = Client(commitment=Processed, blockhash_cache=True) docker_services.wait_until_responsive(timeout=15, pause=1, check=http_client.is_connected) return http_client
def test_http_client(docker_services) -> Client: """Test http_client.is_connected.""" http_client = Client() docker_services.wait_until_responsive(timeout=15, pause=1, check=http_client.is_connected) return http_client
def create_celery(test_config=None): # pylint: disable=W0603 global web3endpoint, web3, abi_values, eth_abi_values, eth_web3 global solana_client web3endpoint = helpers.get_web3_endpoint(shared_config) web3 = Web3(HTTPProvider(web3endpoint)) abi_values = helpers.load_abi_values() eth_abi_values = helpers.load_eth_abi_values() # Initialize eth_web3 with MultiProvider # We use multiprovider to allow for multiple web3 providers and additional resiliency. # However, we do not use multiprovider in data web3 because of the effect of disparate block status reads. eth_web3 = Web3(MultiProvider(shared_config["web3"]["eth_provider_url"])) # Initialize Solana web3 provider solana_client = Client(SOLANA_ENDPOINT) global registry global user_factory global track_factory global social_feature_factory global playlist_factory global user_library_factory global ipld_blacklist_factory global user_replica_set_manager global contract_addresses # pylint: enable=W0603 (registry, user_factory, track_factory, social_feature_factory, playlist_factory, user_library_factory, ipld_blacklist_factory, user_replica_set_manager, contract_addresses) = init_contracts() return create(test_config, mode="celery")
def handle_get_signatures_for_address(client: Client, index: int): endpoint = self.endpoints[index] num_retries = retries while num_retries > 0: try: logger.info( f"solana_client_manager.py | handle_get_signatures_for_address | Fetching {before} {endpoint}" ) transactions: ConfirmedSignatureForAddressResponse = ( client.get_signatures_for_address( account, before, until, limit, Commitment("finalized"))) logger.info( f"solana_client_manager.py | handle_get_signatures_for_address | Finished fetching {before} {endpoint}" ) return transactions except Exception as e: logger.error( f"solana_client_manager.py | handle_get_signatures_for_address | \ Error fetching account {account} from endpoint {endpoint}, {e}", exc_info=True, ) num_retries -= 1 time.sleep(DELAY_SECONDS) logger.error( f"solana_client_manager.py | handle_get_signatures_for_address | Retrying account fetch: {account} with endpoint {endpoint}" ) raise Exception( f"solana_client_manager.py | handle_get_signatures_for_address | Failed to fetch account {account} with endpoint {endpoint}" )
def handle_get_sol_tx_info(client: Client, index: int): endpoint = self.endpoints[index] num_retries = retries while num_retries > 0: try: logger.info( f"solana_client_manager.py | get_sol_tx_info | Fetching tx {tx_sig} {endpoint}" ) tx_info: ConfirmedTransaction = client.get_transaction( tx_sig, encoding) logger.info( f"solana_client_manager.py | get_sol_tx_info | Finished fetching tx {tx_sig} {endpoint}" ) if tx_info["result"] is not None: return tx_info except Exception as e: logger.error( f"solana_client_manager.py | get_sol_tx_info | \ Error fetching tx {tx_sig} from endpoint {endpoint}, {e}", exc_info=True, ) num_retries -= 1 time.sleep(DELAY_SECONDS) logger.error( f"solana_client_manager.py | get_sol_tx_info | Retrying tx fetch: {tx_sig} with endpoint {endpoint}" ) raise Exception( f"solana_client_manager.py | get_sol_tx_info | Failed to fetch {tx_sig} with endpoint {endpoint}" )
def create_token_mint(self): self.solana_client = SolanaClient(SOLANA_URL) with open("proxy/operator-keypairs/id.json") as f: d = json.load(f) self.mint_authority = SolanaAccount(d[0:32]) self.solana_client.request_airdrop(self.mint_authority.public_key(), 1000_000_000_000, Confirmed) while True: balance = self.solana_client.get_balance( self.mint_authority.public_key(), Confirmed)["result"]["value"] if balance > 0: break sleep(1) print('create_token_mint mint, SolanaAccount: ', self.mint_authority.public_key()) self.token = SplToken.create_mint( self.solana_client, self.mint_authority, self.mint_authority.public_key(), 9, TOKEN_PROGRAM_ID, )
def load_bytes_data(addr: PublicKey, conn: Client): res = conn.get_account_info(addr) if ("result" not in res) or ("value" not in res["result"]) or ( "data" not in res["result"]["value"]): raise Exception("Cannot load byte data.") data = res["result"]["value"]["data"][0] return base64.decodebytes(data.encode("ascii"))
def get_min_balance_rent_for_exempt_for_mint(conn: Client) -> int: """Get the minimum balance for the mint to be rent exempt. :param conn: RPC connection to a solana cluster. :return: Number of lamports required. """ resp = conn.get_minimum_balance_for_rent_exemption(MINT_LAYOUT.sizeof()) return resp["result"]
def get_min_balance_rent_for_exempt_for_multisig(conn: Client) -> int: """Get the minimum balance for the multisig to be rent exempt. Args: conn: RPC connection to a solana cluster. Return: Number of lamports required. """ resp = conn.get_minimum_balance_for_rent_exemption( MULTISIG_LAYOUT.sizeof()) return resp["result"]
def load_binary_option(self, api_endpoint, pool_account): client = Client(api_endpoint) try: pool_data = base64.b64decode( client.get_account_info(pool_account)['result']['value'] ['data'][0]) except Exception as e: return json.dumps({ 'status': HTTPStatus.BAD_REQUEST, 'msg': str(e), }) pubkey = 'B' * 32 raw_bytes = struct.unpack( f"<BQ?{pubkey}{pubkey}{pubkey}{pubkey}{pubkey}{pubkey}", pool_data) i = 0 pool = {} pool["decimals"] = raw_bytes[i] i += 1 pool["circulation"] = raw_bytes[i] i += 1 pool["settled"] = raw_bytes[i] i += 1 pool["escrow_mint"] = base58.b58encode(bytes( raw_bytes[i:i + 32])).decode('ascii') i += 32 pool["escrow"] = base58.b58encode(bytes(raw_bytes[i:i + 32])).decode('ascii') i += 32 pool["long_mint"] = base58.b58encode(bytes( raw_bytes[i:i + 32])).decode('ascii') i += 32 pool["short_mint"] = base58.b58encode(bytes( raw_bytes[i:i + 32])).decode('ascii') i += 32 pool["owner"] = base58.b58encode(bytes(raw_bytes[i:i + 32])).decode('ascii') i += 32 pool["winning_side"] = base58.b58encode(bytes( raw_bytes[i:i + 32])).decode('ascii') i += 32 return pool
def settle(self, api_endpoint, pool_account, winning_mint, skip_confirmation=True): msg = "" client = Client(api_endpoint) msg += "Initialized client" # Create account objects source_account = Account(self.private_key) # Signers signers = [source_account] # List non-derived accounts pool_account = PublicKey(pool_account) winning_mint_account = PublicKey(winning_mint) tx = Transaction() settle_ix = settle_instruction( pool_account, winning_mint_account, source_account.public_key(), ) tx = tx.add(settle_ix) # Send request try: response = client.send_transaction( tx, *signers, opts=types.TxOpts(skip_confirmation=skip_confirmation)) return json.dumps({ 'status': HTTPStatus.OK, 'msg': msg + f" | Settle successful, winner: {str(winning_mint_account)}", 'tx': response.get('result') if skip_confirmation else response['result']['transaction']['signatures'], }) except Exception as e: msg += f" | ERROR: Encountered exception while attempting to send transaction: {e}" raise (e)
def get_min_balance_rent_for_exempt_for_account(conn: Client) -> int: """Get the minimum balance for the account to be rent exempt. Args: conn: RPC connection to a solana cluster. Returns: Number of lamports required. """ resp = conn.get_minimum_balance_for_rent_exemption( ACCOUNT_LAYOUT.sizeof()) return resp["result"]
def __init__(self, cluster: str, cluster_url: str, program_id: PublicKey, dex_program_id: PublicKey, group_name: str, group_id: PublicKey): self.logger: logging.Logger = logging.getLogger( self.__class__.__name__) self.cluster: str = cluster self.cluster_url: str = cluster_url self.client: Client = Client(cluster_url) self.program_id: PublicKey = program_id self.dex_program_id: PublicKey = dex_program_id self.group_name: str = group_name self.group_id: PublicKey = group_id self.commitment: Commitment = Single self.encoding: str = "base64"
def test_request_air_drop(stubbed_sender: Keypair, stubbed_receiver: Keypair, test_http_client: Client): """Test air drop to stubbed_sender and stubbed_receiver.""" # Airdrop to stubbed_sender resp = test_http_client.request_airdrop(stubbed_sender.public_key, AIRDROP_AMOUNT) assert_valid_response(resp) test_http_client.confirm_transaction(resp["result"]) balance = test_http_client.get_balance(stubbed_sender.public_key) assert balance["result"]["value"] == AIRDROP_AMOUNT # Airdrop to stubbed_receiver resp = test_http_client.request_airdrop(stubbed_receiver, AIRDROP_AMOUNT) assert_valid_response(resp) test_http_client.confirm_transaction(resp["result"]) balance = test_http_client.get_balance(stubbed_receiver) assert balance["result"]["value"] == AIRDROP_AMOUNT
def test_http_clients(docker_services) -> Clients: """Test http_client.is_connected.""" http_client = Client() async_client = AsyncClient() loop = asyncio.get_event_loop() def check() -> bool: sync_result = http_client.is_connected() async_result = loop.run_until_complete(async_client.is_connected()) return sync_result and async_result docker_services.wait_until_responsive(timeout=15, pause=1, check=check) clients = Clients(sync=http_client, async_=async_client, loop=loop) yield clients clients.loop.run_until_complete(async_client.close())
def stubbed_market() -> Market: conn = Client("http://stubbed_endpoint:123/") market_state = State( Container( dict( account_flags=AccountFlags( initialized=True, market=True, bids=False, ), quote_dust_threshold=100, base_lot_size=100, quote_lot_size=10, )), program_id=DEFAULT_DEX_PROGRAM_ID, base_mint_decimals=6, quote_mint_decimals=6, ) return Market(conn, market_state)
def confirm_transaction(client: Client, tx_sig: str) -> RPCResponse: """Confirm a transaction.""" TIMEOUT = 30 # 30 seconds pylint: disable=invalid-name elapsed_time = 0 while elapsed_time < TIMEOUT: sleep_time = 3 if not elapsed_time: sleep_time = 7 time.sleep(sleep_time) else: time.sleep(sleep_time) resp = client.get_confirmed_transaction(tx_sig) if resp["result"]: break elapsed_time += sleep_time if not resp["result"]: raise RuntimeError("could not confirm transaction: ", tx_sig) return resp
def _get_slot(client: Client, index): endpoint = self.endpoints[index] num_retries = retries while num_retries > 0: try: response = client.get_slot(Commitment("finalized")) return response["result"] except Exception as e: logger.error( f"solana_client_manager.py | get_slot, {e}", exc_info=True, ) num_retries -= 1 time.sleep(DELAY_SECONDS) logger.error( f"solana_client_manager.py | get_slot | Retrying with endpoint {endpoint}" ) raise Exception( f"solana_client_manager.py | get_slot | Failed with endpoint {endpoint}" )
def find_for_market_and_owner( conn: Client, market: PublicKey, owner: PublicKey, program_id: PublicKey, commitment: Commitment = Recent) -> List[OpenOrdersAccount]: filters = [ MemcmpOpts( offset=5 + 8, # 5 bytes of padding, 8 bytes of account flag bytes=str(market), ), MemcmpOpts( offset=5 + 8 + 32, # 5 bytes of padding, 8 bytes of account flag, 32 bytes of market public key bytes=str(owner), ), ] resp = conn.get_program_accounts( program_id, commitment=commitment, encoding="base64", memcmp_opts=filters, data_size=OPEN_ORDERS_LAYOUT.sizeof(), ) accounts = [] for account in resp["result"]: account_details = account["account"] accounts.append( ProgramAccount( public_key=PublicKey(account["pubkey"]), data=base64.decodebytes( account_details["data"][0].encode("ascii")), is_executablable=bool(account_details["executable"]), owner=PublicKey(account_details["owner"]), lamports=int(account_details["lamports"]), )) return [ OpenOrdersAccount.from_bytes(account.public_key, account.data) for account in accounts ]
from solana.rpc.api import Client from solana.transaction import Transaction from solana.system_program import decode_transfer as sol_decode_transfer from spl.token.instructions import decode_transfer as spl_decode_transfer from solana.system_program import TransferParams as SOLTransferParams from spl.token.instructions import TransferParams as SPLTransferParams from solana.transaction import Transaction, TransactionInstruction from solana._layouts.system_instructions import SYSTEM_INSTRUCTIONS_LAYOUT, InstructionType as SOLInstructionType from spl.token._layouts import INSTRUCTIONS_LAYOUT, InstructionType as SPLInstructionType import base64 # solana_client = Client("https://api.mainnet-beta.solana.com") solana_client = Client("https://devnet.solana.com") address = "" transactions = solana_client.get_confirmed_signature_for_address2(address)["result"] for tx in transactions: tx_result = solana_client.get_confirmed_transaction(tx_sig=tx["signature"], encoding="base64") raw_tx_str = tx_result['result']['transaction'][0] raw_tx_base64_bytes = raw_tx_str.encode('ascii') raw_tx_bytes = base64.b64decode(raw_tx_base64_bytes) des_tx: Transaction = Transaction.deserialize(raw_tx_bytes) tx_instruction: TransactionInstruction = des_tx.instructions.pop() # program id will be a bunch of ones if it's a transaction involving SOL if tx_instruction.program_id.__str__() == "11111111111111111111111111111111": if SYSTEM_INSTRUCTIONS_LAYOUT.parse(tx_instruction.data).instruction_type == SOLInstructionType.Transfer: transfer_params: SOLTransferParams = sol_decode_transfer(tx_instruction) print(tx["slot"]) # blockheight print(f'from:{transfer_params.from_pubkey}') # from print(f'to:{transfer_params.to_pubkey}') # to
from time import sleep import base58 import binascii import codecs from solana.rpc.api import Client AUDIUS_PROGRAM = "Fm4g3bGuezevgqSHopjEDGRGCtVU6CDpFXZE3832EzGs" SECP_PROGRAM = "KeccakSecp256k11111111111111111111111111111" SLEEP_TIME = 3 # SOLANA_ENDPOINT = "https://devnet.solana.com" SOLANA_ENDPOINT = "http://localhost:8899" http_client = Client(SOLANA_ENDPOINT) slot_from = None while True: if not slot_from: slot_from = http_client.get_slot()["result"] transaction = http_client.get_confirmed_signature_for_address2( AUDIUS_PROGRAM, limit=1) if transaction["result"][0]["slot"] > slot_from: slot_from = transaction["result"][0]["slot"] tx_info = http_client.get_confirmed_transaction( transaction["result"][0]["signature"]) if SECP_PROGRAM in tx_info["result"]["transaction"]["message"][
def __init__(self, solana_endpoints) -> None: self.endpoints = solana_endpoints.split(",") self.clients = [Client(endpoint) for endpoint in self.endpoints]