def create_account( self, owner: PublicKey, skip_confirmation: bool = False, ) -> PublicKey: """Create and initialize a new account. This account may then be used as a `transfer()` or `approve()` destination. :param owner: User account that will own the new account. :param skip_confirmation: (optional) Option to skip transaction confirmation. :return: Public key of the new empty account. If skip confirmation is set to `False`, this method will block for at most 30 seconds or until the transaction is confirmed. """ new_account = Account() # Allocate memory for the account balance_needed = Token.get_min_balance_rent_for_exempt_for_account( self._conn) # Construct transaction txn = Transaction() txn.add( sp.create_account( sp.CreateAccountParams( from_pubkey=self.payer.public_key(), new_account_pubkey=new_account.public_key(), lamports=balance_needed, space=ACCOUNT_LAYOUT.sizeof(), program_id=self.program_id, ))) txn.add( spl_token.initialize_account( spl_token.InitializeAccountParams( account=new_account.public_key(), mint=self.pubkey, owner=owner, program_id=self.program_id))) # Send the two instructions self._conn.send_transaction(txn, self.payer, new_account, opts=TxOpts( skip_preflight=True, skip_confirmation=skip_confirmation)) return new_account.public_key()
def test_sign_partial(stubbed_blockhash): """Test paritally sigining a transaction.""" acc1, acc2 = Account(), Account() transfer = sp.transfer( sp.TransferParams(from_pubkey=acc1.public_key(), to_pubkey=acc2.public_key(), lamports=123)) partial_txn = txlib.Transaction( recent_blockhash=stubbed_blockhash).add(transfer) partial_txn.sign_partial(acc1, acc2.public_key()) assert len(partial_txn.signature()) == txlib.SIG_LENGTH assert len(partial_txn.signatures) == 2 assert not partial_txn.signatures[1].signature partial_txn.add_signer(acc2) expected_txn = txlib.Transaction( recent_blockhash=stubbed_blockhash).add(transfer) expected_txn.sign(acc1, acc2) assert partial_txn == expected_txn
def test_transfer_signatures(stubbed_blockhash): """Test signing transfer transactions.""" acc1, acc2 = Account(), Account() transfer1 = sp.transfer( sp.TransferParams(from_pubkey=acc1.public_key(), to_pubkey=acc2.public_key(), lamports=123)) transfer2 = sp.transfer( sp.TransferParams(from_pubkey=acc2.public_key(), to_pubkey=acc1.public_key(), lamports=123)) txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add( transfer1, transfer2) txn.sign(acc1, acc2) expected = txlib.Transaction(recent_blockhash=stubbed_blockhash, signatures=txn.signatures).add( transfer1, transfer2) assert txn == expected
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 make_cancel_order_by_client_id_instruction( self, owner: Account, open_orders_account: PublicKey, client_id: int) -> TransactionInstruction: return instructions.cancel_order_by_client_id( instructions.CancelOrderByClientIDParams( market=self.state.public_key(), owner=owner.public_key(), open_orders=open_orders_account, request_queue=self.state.request_queue(), client_id=client_id, program_id=self.state.program_id(), ))
def test_generate_account_from_secret_key(): """Generate an account with provided secret key.""" secret_key = bytes( [ 153, 218, 149, 89, 225, 94, 145, 62, 233, 171, 46, 83, 227, 223, 173, 87, 93, 163, 59, 73, 190, 17, 37, 187, 146, 46, 51, 73, 79, 73, 136, 40, ] ) acc = Account(secret_key) assert str(acc.public_key()) == "2q7pyhPwAwZ3QMfZrnAbDhnh9mDUqycszcpf86VgQxhF"
def test_allocate_with_seed(): """Test creating a transaction for allocate with seed.""" params = sp.AllocateWithSeedParams( account_pubkey=Account().public_key(), base_pubkey=PublicKey(1), seed={ "length": 4, "chars": "gqln" }, space=65537, program_id=PublicKey(2), ) assert sp.decode_allocate_with_seed(sp.allocate(params)) == params
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 _create_wrapped_native_account_args( program_id: PublicKey, owner: PublicKey, payer: Account, amount: int, skip_confirmation: bool, balance_needed: int, ) -> Tuple[PublicKey, Transaction, Account, Account, TxOpts]: new_account = Account() # Allocate memory for the account # Construct transaction txn = Transaction() txn.add( sp.create_account( sp.CreateAccountParams( from_pubkey=payer.public_key(), new_account_pubkey=new_account.public_key(), lamports=balance_needed, space=ACCOUNT_LAYOUT.sizeof(), program_id=program_id, ))) txn.add( sp.transfer( sp.TransferParams(from_pubkey=payer.public_key(), to_pubkey=new_account.public_key(), lamports=amount))) txn.add( spl_token.initialize_account( spl_token.InitializeAccountParams( account=new_account.public_key(), mint=WRAPPED_SOL_MINT, owner=owner, program_id=program_id))) return new_account.public_key(), txn, payer, new_account, TxOpts( skip_confirmation=skip_confirmation)
def settle_funds( # pylint: disable=too-many-arguments self, owner: Account, open_orders: OpenOrdersAccount, base_wallet: PublicKey, quote_wallet: PublicKey, # TODO: add referrer_quote_wallet. opts: TxOpts = TxOpts(), ) -> RPCResponse: # TODO: Handle wrapped sol accounts if open_orders.owner != owner.public_key(): raise Exception("Invalid open orders account") vault_signer = PublicKey.create_program_address( [ bytes(self.state.public_key()), self.state.vault_signer_nonce().to_bytes(8, byteorder="little") ], self.state.program_id(), ) transaction = Transaction() transaction.add( self.make_settle_funds_instruction(open_orders, base_wallet, quote_wallet, vault_signer)) return self._conn.send_transaction(transaction, owner, opts=opts)
def _create_mint_args( conn: Union[Client, AsyncClient], payer: Account, mint_authority: PublicKey, decimals: int, program_id: PublicKey, freeze_authority: Optional[PublicKey], skip_confirmation: bool, balance_needed: int, cls: Union[Type[Token], Type[AsyncToken]], ) -> Tuple[Union[Token, AsyncToken], Transaction, Account, Account, TxOpts]: mint_account = Account() token = cls(conn, mint_account.public_key(), program_id, payer) # type: ignore # 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, ))) return token, txn, payer, mint_account, TxOpts( skip_confirmation=skip_confirmation, skip_preflight=True)
def __bootstrap_account(pubkey: str, secretkey: str) -> Account: secret = [int(b) for b in secretkey[1:-1].split(" ")] account = Account(secret) assert str(account.public_key() ) == pubkey, "account must map to provided public key" return account
class GridStrategy(object): def __init__(self, upper: float, lower: float, amount: float, grid: int, pair: str, base: str, quote: str, owner: str, private: str): """ :params upper: price up :params lower: price down :params amount: amount of the order :params grid: amount of grid :params pair: dexlab trading pair address :params base: youur base coin address for trading :params quote: your quote coin address for trading :params owner: your solana wallet address :params private: your private key for pay the transaction gas """ self.upper = upper self.lower = lower self.amount = amount self.grid = grid self.pair = pair self.base = base self.quote = quote self.owner = owner self.key = base58.b58decode(private) self.payer = Account(self.key[:32]) self.client = Client('', '') self.cc = conn('https://api.mainnet-beta.solana.com/') self.market = Market.load( self.cc, PublicKey(self.pair), program_id=PublicKey( '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin')) try: self.open_acc = self.market.find_open_orders_accounts_for_owner( self.payer.public_key())[0].address except: self.open_acc = '' self.base_decimal = self.market.state.base_spl_token_decimals() self.quote_decimal = self.market.state.quote_spl_token_decimals() print(f'Initialize...\n\n' f'----parameters----\n\n' f'upper: {self.upper}\n' f'lower: {self.lower}\n' f'amount: {self.amount}\n' f'grid: {self.grid}\n' f'base decimal: {self.base_decimal}\n' f'quote decimal: {self.quote_decimal}\n' f'pair: {self.pair}\n' f'base: {self.base}\n' f'quote: {self.quote}\n' f'owner: {self.owner}\n' f'open orders account: {self.open_acc}\n' f'key: {self.key[:32]}\n\n' f'----start----\n') def _get_orders(self): """ :return: a dict contains price and client id Ex: {price: client} """ orders = self.market.load_orders_for_owner(PublicKey(self.owner)) order_table = {} for o in orders: order_table[o.client_id] = o.info.price return order_table def _get_last_price(self): """ :return: last price (float) """ return float( self.client.get_public_single_market_price(self.pair)['price']) def _buy_func(self, price, client_id): self.market.place_order(payer=PublicKey(self.base), owner=self.payer, side=Side.BUY, order_type=OrderType.LIMIT, limit_price=price, max_quantity=abs(self.amount), client_id=client_id, opts=TxOpts(skip_preflight=True)) print( f'Client ID: {client_id}; Price {price}; Amount: {self.amount}; Open: BUY' ) def _sell_func(self, price, client_id): self.market.place_order(payer=PublicKey(self.quote), owner=self.payer, side=Side.SELL, order_type=OrderType.LIMIT, limit_price=price, max_quantity=abs(self.amount), client_id=client_id, opts=TxOpts(skip_preflight=True)) print( f'Client ID: {client_id}; Price {price}; Amount: {self.amount}; Open: SELL' ) def cancel_order(self, client_id): """ :return: a dict contains tx_hash and id """ self.open_acc = self.market.find_open_orders_accounts_for_owner( self.payer.public_key())[0].address return self.market.cancel_order_by_client_id( self.payer, PublicKey(self.open_acc), client_id, TxOpts(skip_preflight=True)) def cancel_pending(self): order_table = self._get_orders() for o in order_table.keys(): self.cancel_order(o) def on_exit(self): if True: print(f'----Exit----\n\n' f'Closing all open orders...\n') self.cancel_pending() print('----Success----') def update_order(self, order_table, distance, last_prcie): for i in range(self.grid): if (i + 1) not in order_table: if (self.lower + i * distance) < last_prcie: #self._buy_func(round((self.lower + i * distance), self.base_decimal), i + 1) print( f'Client ID: {i + 1}; Price {round((self.lower + i * distance), self.base_decimal)}; Amount: {self.amount}; Open: BUY' ) elif (self.lower + i * distance) > last_prcie: #self._sell_func(round((self.lower + i * distance), self.quote_decimal), i + 1) print( f'Client ID: {i + 1}; Price {round((self.lower + i * distance), self.quote_decimal)}; Amount: {self.amount}; Open: SELL' ) def griding(self): """ Main Logic """ distance = (self.upper - self.lower) / self.grid order_table = self._get_orders() last_prcie = self._get_last_price() print(f'Current Price: {last_prcie}\n') print('----place orders----') self.update_order(order_table, distance, last_prcie)
def collect(self, api_endpoint, pool_account, collector, skip_confirmation=True): msg = "" client = Client(api_endpoint) msg += "Initialized client" signers = [Account(self.private_key)] pool = self.load_binary_option(api_endpoint, pool_account) pool_account = PublicKey(pool_account) collector_account = PublicKey(collector) escrow_account = PublicKey(pool["escrow"]) escrow_mint_account = PublicKey(pool["escrow_mint"]) long_token_mint_account = PublicKey(pool["long_mint"]) short_token_mint_account = PublicKey(pool["short_mint"]) token_account = PublicKey(TOKEN_PROGRAM_ID) escrow_authority_account = PublicKey.find_program_address( [ bytes(long_token_mint_account), bytes(short_token_mint_account), bytes(token_account), bytes(PublicKey(BINARY_OPTION_PROGRAM_ID)) ], PublicKey(BINARY_OPTION_PROGRAM_ID), )[0] # Transaction tx = Transaction() atas = [] for mint_account in (long_token_mint_account, short_token_mint_account, escrow_mint_account): token_pda_address = get_associated_token_address( collector_account, mint_account) associated_token_account_info = client.get_account_info( token_pda_address) account_info = associated_token_account_info['result']['value'] if account_info is not None: account_state = ACCOUNT_LAYOUT.parse( base64.b64decode(account_info['data'][0])).state else: account_state = 0 if account_state == 0: msg += f" | Error Fetching PDA: {token_pda_address}" raise Exception() else: msg += f" | Fetched PDA: {token_pda_address}" atas.append(token_pda_address) collect_ix = collect_instruction( pool_account, collector_account, atas[0], atas[1], atas[2], long_token_mint_account, short_token_mint_account, escrow_account, escrow_authority_account, token_account, ) tx = tx.add(collect_ix) try: response = client.send_transaction( tx, *signers, opts=types.TxOpts(skip_confirmation=skip_confirmation)) return json.dumps({ 'status': HTTPStatus.OK, 'msg': msg + f" | Collect 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}" print(msg) raise (e)
class TestAirdropperIntegration(TestCase): @classmethod def setUpClass(cls) -> None: cls.create_token_mint(cls) cls.deploy_erc20_wrapper_contract(cls) cls.acc_num = 0 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 deploy_erc20_wrapper_contract(self): self.wrapper = ERC20Wrapper(proxy, NAME, SYMBOL, self.token, admin, self.mint_authority, EVM_LOADER_ID) self.wrapper.deploy_wrapper() def create_account_instruction(self, eth_address: str, payer: PublicKey): dest_address_solana, nonce = get_evm_loader_account_address( eth_address) neon_token_account = get_associated_token_address( dest_address_solana, ETH_TOKEN_MINT_ID) return TransactionInstruction( program_id=EVM_LOADER_ID, data=create_account_layout(0, 0, bytes.fromhex(eth_address[2:]), nonce), keys=[ AccountMeta(pubkey=payer, is_signer=True, is_writable=True), AccountMeta(pubkey=dest_address_solana, is_signer=False, is_writable=True), AccountMeta(pubkey=neon_token_account, is_signer=False, is_writable=True), AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False), AccountMeta(pubkey=ETH_TOKEN_MINT_ID, is_signer=False, is_writable=False), AccountMeta(pubkey=TOKEN_PROGRAM_ID, is_signer=False, is_writable=False), AccountMeta(pubkey=ASSOCIATED_TOKEN_PROGRAM_ID, is_signer=False, is_writable=False), AccountMeta(pubkey=SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False), ]) def create_sol_account(self): account = SolanaAccount() print( f"New solana account created: {account.public_key().to_base58()}. Airdropping..." ) self.solana_client.request_airdrop(account.public_key(), 1000_000_000_000, Confirmed) return account def create_token_account(self, owner: PublicKey, mint_amount: int): new_token_account = self.wrapper.create_associated_token_account( owner, self.mint_authority) self.wrapper.mint_to(new_token_account, mint_amount) return new_token_account def create_eth_account(self): self.acc_num += 1 account = proxy.eth.account.create( f'neonlabsorg/proxy-model.py/issues/344/eth_account{self.acc_num}') print(f"NEON account created: {account.address}") return account def test_success_airdrop_simple_case(self): from_owner = self.create_sol_account() mint_amount = 1000_000_000_000 from_spl_token_acc = self.create_token_account(from_owner.public_key(), mint_amount) to_neon_acc = self.create_eth_account().address self.assertEqual(self.wrapper.get_balance(from_spl_token_acc), mint_amount) self.assertEqual(self.wrapper.get_balance(to_neon_acc), 0) TRANSFER_AMOUNT = 123456 trx = Transaction() trx.add( self.create_account_instruction(to_neon_acc, from_owner.public_key())) trx.add( self.wrapper.create_neon_erc20_account_instruction( from_owner.public_key(), to_neon_acc)) trx.add( self.wrapper.create_input_liquidity_instruction( from_owner.public_key(), from_spl_token_acc, to_neon_acc, TRANSFER_AMOUNT)) opts = TxOpts(skip_preflight=True, skip_confirmation=False) print(self.solana_client.send_transaction(trx, from_owner, opts=opts)) self.assertEqual(self.wrapper.get_balance(from_spl_token_acc), mint_amount - TRANSFER_AMOUNT) self.assertEqual(self.wrapper.get_balance(to_neon_acc), TRANSFER_AMOUNT) wait_time = 0 eth_balance = 0 while wait_time < MAX_AIRDROP_WAIT_TIME: eth_balance = proxy.eth.get_balance(to_neon_acc) balance_ready = eth_balance > 0 and eth_balance < 10 * pow(10, 18) if balance_ready: break sleep(1) wait_time += 1 print(f"Wait time for simple transaction (1 airdrop): {wait_time}") eth_balance = proxy.eth.get_balance(to_neon_acc) print("NEON balance is: ", eth_balance) self.assertTrue( eth_balance > 0 and eth_balance < 10 * pow(10, 18)) # 10 NEON is a max airdrop amount def test_success_airdrop_complex_case(self): from_owner = self.create_sol_account() mint_amount = 1000_000_000_000 from_spl_token_acc = self.create_token_account(from_owner.public_key(), mint_amount) to_neon_acc1 = self.create_eth_account().address to_neon_acc2 = self.create_eth_account().address self.assertEqual(self.wrapper.get_balance(from_spl_token_acc), mint_amount) self.assertEqual(self.wrapper.get_balance(to_neon_acc1), 0) self.assertEqual(self.wrapper.get_balance(to_neon_acc2), 0) TRANSFER_AMOUNT1 = 123456 TRANSFER_AMOUNT2 = 654321 trx = Transaction() trx.add( self.create_account_instruction(to_neon_acc1, from_owner.public_key())) trx.add( self.create_account_instruction(to_neon_acc2, from_owner.public_key())) trx.add( self.wrapper.create_neon_erc20_account_instruction( from_owner.public_key(), to_neon_acc1)) trx.add( self.wrapper.create_neon_erc20_account_instruction( from_owner.public_key(), to_neon_acc2)) trx.add( self.wrapper.create_input_liquidity_instruction( from_owner.public_key(), from_spl_token_acc, to_neon_acc1, TRANSFER_AMOUNT1)) trx.add( self.wrapper.create_input_liquidity_instruction( from_owner.public_key(), from_spl_token_acc, to_neon_acc2, TRANSFER_AMOUNT2)) opts = TxOpts(skip_preflight=True, skip_confirmation=False) print(self.solana_client.send_transaction(trx, from_owner, opts=opts)) self.assertEqual(self.wrapper.get_balance(from_spl_token_acc), mint_amount - TRANSFER_AMOUNT1 - TRANSFER_AMOUNT2) self.assertEqual(self.wrapper.get_balance(to_neon_acc1), TRANSFER_AMOUNT1) self.assertEqual(self.wrapper.get_balance(to_neon_acc2), TRANSFER_AMOUNT2) wait_time = 0 eth_balance1 = 0 eth_balance2 = 0 while wait_time < MAX_AIRDROP_WAIT_TIME: eth_balance1 = proxy.eth.get_balance(to_neon_acc1) eth_balance2 = proxy.eth.get_balance(to_neon_acc2) balance1_ready = eth_balance1 > 0 and eth_balance1 < 10 * pow( 10, 18) balance2_ready = eth_balance2 > 0 and eth_balance2 < 10 * pow( 10, 18) if balance1_ready and balance2_ready: break sleep(1) wait_time += 1 print(f"Wait time for complex transaction (2 airdrops): {wait_time}") eth_balance1 = proxy.eth.get_balance(to_neon_acc1) eth_balance2 = proxy.eth.get_balance(to_neon_acc2) print("NEON balance 1 is: ", eth_balance1) print("NEON balance 2 is: ", eth_balance2) self.assertTrue( eth_balance1 > 0 and eth_balance1 < 10 * pow(10, 18)) # 10 NEON is a max airdrop amount self.assertTrue( eth_balance2 > 0 and eth_balance2 < 10 * pow(10, 18)) # 10 NEON is a max airdrop amount def test_no_airdrop(self): from_owner = self.create_sol_account() mint_amount = 1000_000_000_000 from_spl_token_acc = self.create_token_account(from_owner.public_key(), mint_amount) to_neon_acc = self.create_eth_account().address sleep(15) self.assertEqual(self.wrapper.get_balance(from_spl_token_acc), mint_amount) self.assertEqual(self.wrapper.get_balance(to_neon_acc), 0) trx = Transaction() trx.add( self.create_account_instruction(to_neon_acc, from_owner.public_key())) trx.add( self.wrapper.create_neon_erc20_account_instruction( from_owner.public_key(), to_neon_acc)) # No input liquidity opts = TxOpts(skip_preflight=True, skip_confirmation=False) print(self.solana_client.send_transaction(trx, from_owner, opts=opts)) sleep(15) eth_balance = proxy.eth.get_balance(to_neon_acc) print("NEON balance is: ", eth_balance) self.assertEqual(eth_balance, 0)
def trade(self, api_endpoint, pool_account, buyer_encrypted_private_key, seller_encrypted_private_key, size, buyer_price, seller_price, skip_confirmation=True): msg = "" client = Client(api_endpoint) msg += "Initialized client" # Create account objects buyer_private_key = list( self.cipher.decrypt(buyer_encrypted_private_key)) seller_private_key = list( self.cipher.decrypt(seller_encrypted_private_key)) assert (len(buyer_private_key) == 32) assert (len(seller_private_key) == 32) source_account = Account(self.private_key) buyer = Account(buyer_private_key) seller = Account(seller_private_key) # Signers signers = [buyer, seller, source_account] pool = self.load_binary_option(api_endpoint, pool_account) # List non-derived accounts pool_account = PublicKey(pool_account) escrow_account = PublicKey(pool["escrow"]) escrow_mint_account = PublicKey(pool["escrow_mint"]) long_token_mint_account = PublicKey(pool["long_mint"]) short_token_mint_account = PublicKey(pool["short_mint"]) buyer_account = buyer.public_key() seller_account = seller.public_key() token_account = PublicKey(TOKEN_PROGRAM_ID) escrow_owner_account = PublicKey.find_program_address( [ bytes(long_token_mint_account), bytes(short_token_mint_account), bytes(token_account), bytes(PublicKey(BINARY_OPTION_PROGRAM_ID)) ], PublicKey(BINARY_OPTION_PROGRAM_ID), )[0] # Transaction tx = Transaction() atas = [] for acct in [buyer_account, seller_account]: acct_atas = [] for mint_account in (long_token_mint_account, short_token_mint_account, escrow_mint_account): token_pda_address = get_associated_token_address( acct, mint_account) associated_token_account_info = client.get_account_info( token_pda_address) account_info = associated_token_account_info['result']['value'] if account_info is not None: account_state = ACCOUNT_LAYOUT.parse( base64.b64decode(account_info['data'][0])).state else: account_state = 0 if account_state == 0: msg += f" | Creating PDA: {token_pda_address}" associated_token_account_ix = create_associated_token_account( payer=source_account.public_key(), owner=acct, mint=mint_account, ) tx = tx.add(associated_token_account_ix) else: msg += f" | Fetched PDA: {token_pda_address}" acct_atas.append(token_pda_address) atas.append(acct_atas) trade_ix = trade_instruction( pool_account, escrow_account, long_token_mint_account, short_token_mint_account, buyer_account, seller_account, atas[0][2], atas[1][2], atas[0][0], atas[0][1], atas[1][0], atas[1][1], escrow_owner_account, token_account, int(size), int(buyer_price), int(seller_price), ) tx = tx.add(trade_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" | Trade 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 __init__(self, secret_key): self.logger: logging.Logger = logging.getLogger( self.__class__.__name__) self.secret_key = secret_key[0:32] self.account = Account(self.secret_key)
def place_order( # pylint: disable=too-many-arguments,too-many-locals self, payer: PublicKey, owner: Account, order_type: OrderType, side: Side, limit_price: int, max_quantity: int, client_id: int = 0, opts: TxOpts = TxOpts(), ) -> RPCResponse: # TODO: Add open_orders_address_key param and fee_discount_pubkey transaction = Transaction() signers: List[Account] = [owner] open_order_accounts = self.find_open_orders_accounts_for_owner( owner.public_key()) if not open_order_accounts: new_open_orders_account = Account() mbfre_resp = self._conn.get_minimum_balance_for_rent_exemption( OPEN_ORDERS_LAYOUT.sizeof()) balanced_needed = mbfre_resp["result"] transaction.add( make_create_account_instruction( owner.public_key(), new_open_orders_account.public_key(), balanced_needed, self.state.program_id(), )) signers.append(new_open_orders_account) # TODO: Cache new_open_orders_account # TODO: Handle open_orders_address_key # TODO: Handle fee_discount_pubkey if payer == owner.public_key(): raise ValueError("Invalid payer account") # TODO: add integration test for SOL wrapping. should_wrap_sol = (side == side.Buy and self.state.quote_mint() == WRAPPED_SOL_MINT) or (side == side.Sell and self.state.base_mint == WRAPPED_SOL_MINT) wrapped_sol_account = Account() if should_wrap_sol: transaction.add( create_account( CreateAccountParams( from_pubkey=owner.public_key(), new_account_pubkey=wrapped_sol_account.public_key(), lamports=Market._get_lamport_need_for_sol_wrapping( limit_price, max_quantity, side, open_order_accounts), space=ACCOUNT_LEN, program_id=TOKEN_PROGRAM_ID, ))) transaction.add( initialize_account( InitializeAccountParams( account=wrapped_sol_account.public_key(), mint=WRAPPED_SOL_MINT, owner=owner.public_key(), program_id=SYSVAR_RENT_PUBKEY, ))) transaction.add( self.make_place_order_instruction( wrapped_sol_account.public_key() if should_wrap_sol else payer, owner, order_type, side, limit_price, max_quantity, client_id, open_order_accounts[0].address if open_order_accounts else new_open_orders_account.public_key(), )) if should_wrap_sol: transaction.add( close_account( CloseAccountParams( account=wrapped_sol_account.public_key(), owner=owner.public_key(), dest=owner.public_key(), ))) # TODO: extract `make_place_order_transaction`. return self._conn.send_transaction(transaction, *signers, opts=opts)
def initialize(self, api_endpoint, escrow_mint, decimals=2, skip_confirmation=True): msg = "" # Initialize Clinet client = Client(api_endpoint) msg += "Initialized client" # Create account objects source_account = Account(self.private_key) pool = Account() long_escrow = Account() short_escrow = Account() long_mint = Account() short_mint = Account() # List non-derived accounts pool_account = pool.public_key() escrow_mint_account = PublicKey(escrow_mint) escrow_account = long_escrow.public_key() long_token_mint_account = long_mint.public_key() short_token_mint_account = short_mint.public_key() mint_authority_account = source_account.public_key() update_authority_account = source_account.public_key() token_account = PublicKey(TOKEN_PROGRAM_ID) system_account = PublicKey(SYSTEM_PROGRAM_ID) rent_account = PublicKey(SYSVAR_RENT_ID) msg += " | Gathered accounts" # List signers signers = [ source_account, long_mint, short_mint, long_escrow, short_escrow, pool ] # Start transaction tx = Transaction() # Create Token Metadata init_binary_option_ix = initialize_binary_option_instruction( pool_account, escrow_mint_account, escrow_account, long_token_mint_account, short_token_mint_account, mint_authority_account, update_authority_account, token_account, system_account, rent_account, decimals, ) tx = tx.add(init_binary_option_ix) msg += f" | Creating binary option" # Send request try: response = client.send_transaction( tx, *signers, opts=types.TxOpts(skip_confirmation=skip_confirmation)) return json.dumps({ 'status': HTTPStatus.OK, 'binary_option': str(pool_account), 'msg': msg + f" | Successfully created binary option {str(pool_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 test_transfer(): """Test creating a transaction for transfer.""" params = sp.TransferParams(from_pubkey=Account().public_key(), to_pubkey=Account().public_key(), lamports=123) assert sp.decode_transfer(sp.transfer(params)) == params
def alt_stubbed_sender() -> Account: """Another arbitrary known account to be used as sender.""" return Account(bytes([7] * PublicKey.LENGTH))
def test_generate_account(): """Generate an account.""" acc = Account() assert len(acc.secret_key()) == crypto_box_SECRETKEYBYTES
class Test_erc20_wrapper_contract(unittest.TestCase): @classmethod def setUpClass(cls): print("\n\nhttps://github.com/neonlabsorg/proxy-model.py/issues/197") print('admin.key:', admin.key.hex()) print('admin.address:', admin.address) print('user.key:', user.key.hex()) print('user.address:', user.address) cls.create_token_mint(cls) cls.deploy_erc20_wrapper_contract(cls) cls.create_token_accounts(cls) 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.solana_account = SolanaAccount(d[0:32]) self.solana_client.request_airdrop(self.solana_account.public_key(), 1000_000_000_000, Confirmed) while True: balance = self.solana_client.get_balance( self.solana_account.public_key(), Confirmed)["result"]["value"] if balance > 0: break sleep(1) print('create_token_mint mint, SolanaAccount: ', self.solana_account.public_key()) self.token = SplToken.create_mint( self.solana_client, self.solana_account, self.solana_account.public_key(), 9, TOKEN_PROGRAM_ID, ) def deploy_erc20_wrapper_contract(self): self.wrapper = ERC20Wrapper(proxy, NAME, SYMBOL, self.token, admin, self.solana_account, PublicKey(EVM_LOADER_ID)) self.wrapper.deploy_wrapper() def create_token_accounts(self): admin_token_key = self.wrapper.get_neon_erc20_account_address( admin.address) admin_token_info = { "key": admin_token_key, "owner": self.wrapper.get_neon_account_address(admin.address), "contract": self.wrapper.solana_contract_address, "mint": self.token.pubkey } instr = NeonInstruction( self.solana_account.public_key()).createERC20TokenAccountTrx( admin_token_info) self.solana_client.send_transaction(instr, self.solana_account, opts=TxOpts( skip_preflight=True, skip_confirmation=False)) self.wrapper.mint_to(admin_token_key, 10_000_000_000_000) def test_erc20_name(self): erc20 = proxy.eth.contract(address=self.wrapper.neon_contract_address, abi=self.wrapper.wrapper['abi']) name = erc20.functions.name().call() self.assertEqual(name, NAME) def test_erc20_symbol(self): erc20 = proxy.eth.contract(address=self.wrapper.neon_contract_address, abi=self.wrapper.wrapper['abi']) sym = erc20.functions.symbol().call() self.assertEqual(sym, SYMBOL) def test_erc20_decimals(self): erc20 = self.wrapper.erc20_interface() decs = erc20.functions.decimals().call() self.assertEqual(decs, 9) def test_erc20_totalSupply(self): erc20 = self.wrapper.erc20_interface() ts = erc20.functions.totalSupply().call() self.assertGreater(ts, 0) def test_erc20_balanceOf(self): erc20 = self.wrapper.erc20_interface() b = erc20.functions.balanceOf(admin.address).call() self.assertGreater(b, 0) b = erc20.functions.balanceOf(user.address).call() self.assertEqual(b, 0) def test_erc20_transfer(self): transfer_value = 1000 erc20 = self.wrapper.erc20_interface() admin_balance_before = erc20.functions.balanceOf(admin.address).call() user_balance_before = erc20.functions.balanceOf(user.address).call() nonce = proxy.eth.get_transaction_count(proxy.eth.default_account) tx = {'nonce': nonce} tx = erc20.functions.transfer(user.address, transfer_value).buildTransaction(tx) tx = proxy.eth.account.sign_transaction(tx, admin.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertIsNotNone(tx_receipt) self.assertEqual(tx_receipt.status, 1) admin_balance_after = erc20.functions.balanceOf(admin.address).call() user_balance_after = erc20.functions.balanceOf(user.address).call() self.assertEqual(admin_balance_after, admin_balance_before - transfer_value) self.assertEqual(user_balance_after, user_balance_before + transfer_value) def test_erc20_transfer_not_enough_funds(self): transfer_value = 100_000_000_000_000 erc20 = self.wrapper.erc20_interface() admin_balance_before = erc20.functions.balanceOf(admin.address).call() user_balance_before = erc20.functions.balanceOf(user.address).call() with self.assertRaisesRegex(Exception, "ERC20 transfer failed"): erc20.functions.transfer(user.address, transfer_value).buildTransaction() admin_balance_after = erc20.functions.balanceOf(admin.address).call() user_balance_after = erc20.functions.balanceOf(user.address).call() self.assertEqual(admin_balance_after, admin_balance_before) self.assertEqual(user_balance_after, user_balance_before) def test_erc20_transfer_out_of_bounds(self): transfer_value = 0xFFFF_FFFF_FFFF_FFFF + 1 erc20 = self.wrapper.erc20_interface() with self.assertRaisesRegex(Exception, "ERC20 transfer failed"): erc20.functions.transfer(user.address, transfer_value).buildTransaction() def test_erc20_approve(self): approve_value = 1000 erc20 = self.wrapper.erc20_interface() allowance_before = erc20.functions.allowance(admin.address, user.address).call() nonce = proxy.eth.get_transaction_count(admin.address) tx = erc20.functions.approve( user.address, approve_value).buildTransaction({'nonce': nonce}) tx = proxy.eth.account.sign_transaction(tx, admin.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertEqual(tx_receipt.status, 1) self.assertIsNotNone(tx_receipt) allowance_after = erc20.functions.allowance(admin.address, user.address).call() self.assertEqual(allowance_after, allowance_before + approve_value) def test_erc20_transferFrom(self): approve_value = 1000 transfer_value = 100 erc20 = self.wrapper.erc20_interface() nonce = proxy.eth.get_transaction_count(admin.address) tx = erc20.functions.approve( user.address, approve_value).buildTransaction({'nonce': nonce}) tx = proxy.eth.account.sign_transaction(tx, admin.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertIsNotNone(tx_receipt) self.assertEqual(tx_receipt.status, 1) allowance_before = erc20.functions.allowance(admin.address, user.address).call() admin_balance_before = erc20.functions.balanceOf(admin.address).call() user_balance_before = erc20.functions.balanceOf(user.address).call() nonce = proxy.eth.get_transaction_count(user.address) tx = erc20.functions.transferFrom(admin.address, user.address, transfer_value).buildTransaction({ 'nonce': nonce, 'from': user.address }) tx = proxy.eth.account.sign_transaction(tx, user.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertIsNotNone(tx_receipt) self.assertEqual(tx_receipt.status, 1) allowance_after = erc20.functions.allowance(admin.address, user.address).call() admin_balance_after = erc20.functions.balanceOf(admin.address).call() user_balance_after = erc20.functions.balanceOf(user.address).call() self.assertEqual(allowance_after, allowance_before - transfer_value) self.assertEqual(admin_balance_after, admin_balance_before - transfer_value) self.assertEqual(user_balance_after, user_balance_before + transfer_value) def test_erc20_transferFrom_beyond_approve(self): transfer_value = 10_000_000 erc20 = self.wrapper.erc20_interface() with self.assertRaisesRegex(Exception, "ERC20 transferFrom failed"): erc20.functions.transferFrom(admin.address, user.address, transfer_value).buildTransaction( {'from': user.address}) def test_erc20_transferFrom_out_of_bounds(self): transfer_value = 0xFFFF_FFFF_FFFF_FFFF + 1 erc20 = self.wrapper.erc20_interface() with self.assertRaisesRegex(Exception, "ERC20 transferFrom failed"): erc20.functions.transferFrom(admin.address, user.address, transfer_value).buildTransaction( {'from': user.address}) def test_erc20_approveSolana(self): delegate = SolanaAccount() approve_value = 1000 erc20 = self.wrapper.erc20_interface() nonce = proxy.eth.get_transaction_count(admin.address) tx = erc20.functions.approveSolana(bytes(delegate.public_key()), approve_value).buildTransaction( {'nonce': nonce}) tx = proxy.eth.account.sign_transaction(tx, admin.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertEqual(tx_receipt.status, 1) self.assertIsNotNone(tx_receipt) accounts = self.solana_client.get_token_accounts_by_delegate( delegate.public_key(), TokenAccountOpts(mint=self.token.pubkey), commitment=Recent) accounts = list( map(lambda a: PublicKey(a['pubkey']), accounts['result']['value'])) self.assertIn( self.wrapper.get_neon_erc20_account_address(admin.address), accounts)
def stubbed_sender() -> Account: """Arbitrary known account to be used as sender.""" return Account(bytes([8] * PublicKey.LENGTH))
def test_order_placement_cancellation_cycle( bootstrapped_market: Market, stubbed_payer: Account, stubbed_quote_wallet: Account, stubbed_base_wallet: Account, ): initial_request_len = len(bootstrapped_market.load_request_queue()) bootstrapped_market.place_order( payer=stubbed_quote_wallet.public_key(), owner=stubbed_payer, side=Side.Buy, order_type=OrderType.Limit, limit_price=1000, max_quantity=3000, opts=TxOpts(skip_confirmation=False), ) request_queue = bootstrapped_market.load_request_queue() # 0 request after matching. assert len(request_queue) == initial_request_len + 1 # There should be no bid order. bids = bootstrapped_market.load_bids() assert sum(1 for _ in bids) == 0 # There should be no ask order. asks = bootstrapped_market.load_asks() assert sum(1 for _ in asks) == 0 bootstrapped_market.place_order( payer=stubbed_base_wallet.public_key(), owner=stubbed_payer, side=Side.Sell, order_type=OrderType.Limit, limit_price=1500, max_quantity=3000, opts=TxOpts(skip_confirmation=False), ) # The two order shouldn't get executed since there is a price difference of 1 bootstrapped_market.match_orders( stubbed_payer, 2, opts=TxOpts(skip_confirmation=False), ) # There should be 1 bid order that we sent earlier. bids = bootstrapped_market.load_bids() assert sum(1 for _ in bids) == 1 # There should be 1 ask order that we sent earlier. asks = bootstrapped_market.load_asks() assert sum(1 for _ in asks) == 1 for bid in bids: bootstrapped_market.cancel_order(stubbed_payer, bid, opts=TxOpts(skip_confirmation=False)) bootstrapped_market.match_orders(stubbed_payer, 1, opts=TxOpts(skip_confirmation=False)) # All bid order should have been cancelled. bids = bootstrapped_market.load_bids() assert sum(1 for _ in bids) == 0 for ask in asks: bootstrapped_market.cancel_order(stubbed_payer, ask, opts=TxOpts(skip_confirmation=False)) bootstrapped_market.match_orders(stubbed_payer, 1, opts=TxOpts(skip_confirmation=False)) # All ask order should have been cancelled. asks = bootstrapped_market.load_asks() assert sum(1 for _ in asks) == 0
def create() -> "Wallet": new_account = Account() new_secret_key = new_account.secret_key() return Wallet(new_secret_key)
quote_ccy = pair.split("/")[0] quote_ccy_mint = {} for mkt in get_token_mints(): quote_ccy_mint.update({mkt.name: mkt.address}) print("Token Mint is: {}".format(quote_ccy_mint[quote_ccy])) # %% # Get private key and use that the create a new account #pubkey = "GKksmU6hSJ2X7zz1mcE3Qhr7DDEpvxqbygzb17SxygUD" f = open('./my-solana-wallet/my-keypair.json') private_key = json.load(f) mid = len(private_key) // 2 private_key = private_key[:mid] # to 32 bytes payer = Account(private_key) # Your account to pay fees print("Public Key is: {}".format(payer.public_key())) # %% cc = conn("https://api.mainnet-beta.solana.com/") quote_token = Token( cc, pubkey=PublicKey(quote_ccy_mint[quote_ccy]), # mint address of token program_id=TOKEN_PROGRAM_ID, payer=payer, ) quote_wallet = quote_token.create_account( payer.public_key(),
class Test_read_only_accounts(unittest.TestCase): @classmethod def setUpClass(cls): cls.create_token_mint(cls) cls.deploy_erc20_wrapper_contract(cls) cls.deploy_test_contract(cls) def account_exists(self, key: PublicKey) -> Boolean: info = self.solana_client.get_account_info(key) info["result"]["value"] is not None 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.solana_account = SolanaAccount(d[0:32]) self.solana_client.request_airdrop(self.solana_account.public_key(), 1000_000_000_000, Confirmed) while True: balance = self.solana_client.get_balance( self.solana_account.public_key(), Confirmed)["result"]["value"] if balance > 0: break sleep(1) print('create_token_mint mint, SolanaAccount: ', self.solana_account.public_key()) self.token = SplToken.create_mint( self.solana_client, self.solana_account, self.solana_account.public_key(), 9, TOKEN_PROGRAM_ID, ) def deploy_erc20_wrapper_contract(self): self.wrapper = ERC20Wrapper(proxy, "NEON", "NEON", self.token, admin, self.solana_account, PublicKey(EVM_LOADER_ID)) self.wrapper.deploy_wrapper() def deploy_test_contract(self): 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(admin.address), chainId=proxy.eth.chain_id, gas=987654321, gasPrice=1000000000, to='', value=0, data=contract.bytecode), admin.key) 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) def test_balanceOf(self): account = proxy.eth.account.create() solana_account = self.wrapper.get_neon_account_address(account.address) self.assertFalse(self.account_exists(solana_account)) nonce = proxy.eth.get_transaction_count(admin.address) tx = self.contract.functions.balanceOf( account.address).buildTransaction({"nonce": nonce}) tx = proxy.eth.account.sign_transaction(tx, admin.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertIsNotNone(tx_receipt) self.assertEqual(tx_receipt.status, 1) self.assertFalse(self.account_exists(solana_account)) def test_erc20_balanceOf(self): erc20 = self.wrapper.erc20_interface() account = proxy.eth.account.create() solana_account = self.wrapper.get_neon_account_address(account.address) self.assertFalse(self.account_exists(solana_account)) token_account = self.wrapper.get_neon_erc20_account_address( account.address) self.assertFalse(self.account_exists(token_account)) nonce = proxy.eth.get_transaction_count(admin.address) tx = erc20.functions.balanceOf(account.address).buildTransaction( {"nonce": nonce}) tx = proxy.eth.account.sign_transaction(tx, admin.key) tx_hash = proxy.eth.send_raw_transaction(tx.rawTransaction) tx_receipt = proxy.eth.wait_for_transaction_receipt(tx_hash) self.assertIsNotNone(tx_receipt) self.assertEqual(tx_receipt.status, 1) self.assertFalse(self.account_exists(solana_account)) self.assertFalse(self.account_exists(token_account))