Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
All connections to Solana by SolanaInteractor
  • Loading branch information
afalaleev committed Feb 19, 2022
commit 62c4368c4c6657b408958fe78756182743dbe137
6 changes: 1 addition & 5 deletions proxy/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
import os
from .indexer.airdropper import run_airdropper
from .indexer.indexer import run_indexer
from solana.rpc.api import Client

if __name__ == '__main__':
airdropper_mode = os.environ.get('AIRDROPPER_MODE', 'False').lower() in [1, 'true', 'True']
indexer_mode = os.environ.get('INDEXER_MODE', 'False').lower() in [1, 'true', 'True']
if airdropper_mode:
print("Will run in airdropper mode")
solana_url = os.environ['SOLANA_URL']
evm_loader_id = os.environ['EVM_LOADER']
pyth_mapping_account = PublicKey(os.environ['PYTH_MAPPING_ACCOUNT'])
faucet_url = os.environ['FAUCET_URL']
wrapper_whitelist = os.environ['INDEXER_ERC20_WRAPPER_WHITELIST']
Expand All @@ -34,7 +32,6 @@
max_conf = float(os.environ.get('MAX_CONFIDENCE_INTERVAL', 0.02))

run_airdropper(solana_url,
evm_loader_id,
pyth_mapping_account,
faucet_url,
wrapper_whitelist,
Expand All @@ -45,8 +42,7 @@
print("Will run in indexer mode")

solana_url = os.environ['SOLANA_URL']
evm_loader_id = os.environ['EVM_LOADER']

run_indexer(solana_url, evm_loader_id)
run_indexer(solana_url)
else:
entry_point()
54 changes: 23 additions & 31 deletions proxy/common_neon/account_whitelist.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import traceback
from datetime import datetime
import time
from proxy.environment import ELF_PARAMS, GET_WHITE_LIST_BALANCE_MAX_RETRIES, GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S
from proxy.environment import ELF_PARAMS
from proxy.common_neon.permission_token import PermissionToken
from solana.publickey import PublicKey
from solana.rpc.api import Client as SolanaClient
from solana.account import Account as SolanaAccount
from typing import Union
from proxy.common_neon.address import EthereumAddress
from logged_groups import logged_group
from ..common_neon.solana_interactor import SolanaInteractor

NEON_MINIMAL_CLIENT_ALLOWANCE_BALANCE = int(ELF_PARAMS.get("NEON_MINIMAL_CLIENT_ALLOWANCE_BALANCE", 0))
NEON_MINIMAL_CONTRACT_ALLOWANCE_BALANCE = int(ELF_PARAMS.get("NEON_MINIMAL_CONTRACT_ALLOWANCE_BALANCE", 0))
Expand All @@ -18,10 +17,7 @@

@logged_group("neon.AccountWhitelist")
class AccountWhitelist:
def __init__(self, solana: SolanaClient, payer: SolanaAccount, permission_update_int: int):
self.info(f'GET_WHITE_LIST_BALANCE_MAX_RETRIES={GET_WHITE_LIST_BALANCE_MAX_RETRIES}')
self.info(f'GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S={GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S} seconds')
self.info(f'permission_update_int={permission_update_int}')
def __init__(self, solana: SolanaInteractor, payer: SolanaAccount, permission_update_int: int):
self.solana = solana
self.account_cache = {}
self.permission_update_int = permission_update_int
Expand All @@ -43,9 +39,15 @@ def __init__(self, solana: SolanaClient, payer: SolanaAccount, permission_update
PublicKey(DENIAL_TOKEN_ADDR),
payer)

def read_balance_diff(self, ether_addr: Union[str, EthereumAddress]):
allowance_balance = self.allowance_token.get_balance(ether_addr)
denial_balance = self.denial_token.get_balance(ether_addr)
def read_balance_diff(self, ether_addr: Union[str, EthereumAddress]) -> int:
token_list = [
self.allowance_token.get_token_account_address(ether_addr),
self.denial_token.get_token_account_address(ether_addr)
]

balance_list = self.solana.get_token_account_balance_list(token_list)
allowance_balance = balance_list[0]
denial_balance = balance_list[1]
return allowance_balance - denial_balance

def grant_permissions(self, ether_addr: Union[str, EthereumAddress], min_balance: int):
Expand Down Expand Up @@ -106,27 +108,17 @@ def has_permission(self, ether_addr: Union[str, EthereumAddress], min_balance: i
if diff < self.permission_update_int:
return cached['diff'] >= min_balance

num_retries = GET_WHITE_LIST_BALANCE_MAX_RETRIES

while True:
try:
diff = self.read_balance_diff(ether_addr)
self.account_cache[ether_addr] = {
'last_update': current_time,
'diff': diff
}
return diff >= min_balance
except Exception as err:
err_tb = "".join(traceback.format_tb(err.__traceback__))
self.error(f'Failed to read permissions for {ether_addr}: ' +
f'Type(err): {type(err)}, Error: {err}, Traceback: {err_tb}')
num_retries -= 1
if num_retries == 0:
# This error should be forwarded to client
raise RuntimeError('Failed to read account permissions. Try to repeat later')

self.info(f'Will retry getting whitelist balance after {GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S} seconds')
time.sleep(GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S)
try:
diff = self.read_balance_diff(ether_addr)
self.account_cache[ether_addr] = {
'last_update': current_time,
'diff': diff
}
return diff >= min_balance
except Exception as err:
err_tb = "".join(traceback.format_tb(err.__traceback__))
self.error(f'Failed to read permissions for {ether_addr}: ' +
f'Type(err): {type(err)}, Error: {err}, Traceback: {err_tb}')

def has_client_permission(self, ether_addr: Union[str, EthereumAddress]):
return self.has_permission(ether_addr, NEON_MINIMAL_CLIENT_ALLOWANCE_BALANCE)
Expand Down
2 changes: 1 addition & 1 deletion proxy/common_neon/costs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import base58

from ..environment import EVM_LOADER_ID
from ..indexer.utils import BaseDB
from ..indexer.base_db import BaseDB


class SQLCost(BaseDB):
Expand Down
31 changes: 9 additions & 22 deletions proxy/common_neon/permission_token.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,53 @@
from lib2to3.pgen2 import token
from spl.token.client import Token as SplToken
from solana.publickey import PublicKey
from solana.rpc.api import Client as SolanaClient
from solana.account import Account as SolanaAccount
from spl.token.constants import TOKEN_PROGRAM_ID
from spl.token.instructions import get_associated_token_address
from proxy.common_neon.address import EthereumAddress, ether2program
from typing import Union
from solana.rpc.commitment import Confirmed
from solana.transaction import Transaction
from solana.rpc.types import TxOpts
import spl.token.instructions as spl_token
from proxy.common_neon.utils import get_from_dict
from proxy.common_neon.solana_interactor import SolanaInteractor
from decimal import Decimal
import os

class PermissionToken:
def __init__(self,
solana: SolanaClient,
solana: SolanaInteractor,
token_mint: PublicKey,
payer: SolanaAccount):
self.solana = solana
self.token_mint = token_mint
self.payer = payer
self.token = SplToken(self.solana,
self.token_mint,
TOKEN_PROGRAM_ID,
payer)

def get_token_account_address(self, ether_addr: Union[str, EthereumAddress]):
sol_addr = PublicKey(ether2program(ether_addr)[0])
return get_associated_token_address(sol_addr, self.token.pubkey)
return get_associated_token_address(sol_addr, self.token_mint)

def get_balance(self, ether_addr: Union[str, EthereumAddress]):
token_account = self.get_token_account_address(ether_addr)
result = self.token.get_balance(token_account).get('result', None)
if result is None:
return 0
return int(result['value']['amount'])
return self.solana.get_token_account_balance(token_account)

def create_account_if_needed(self,
ether_addr: Union[str, EthereumAddress]):
token_account = self.get_token_account_address(ether_addr)
response = self.solana.get_account_info(token_account, Confirmed)
if get_from_dict(response, 'result', 'value') is not None:
info = self.solana.get_account_info(token_account)
if info is not None:
return token_account

txn = Transaction()
create_txn = spl_token.create_associated_token_account(
payer=self.payer.public_key(),
owner=PublicKey(ether2program(ether_addr)[0]),
mint=self.token.pubkey
mint=self.token_mint
)
txn.add(create_txn)
self.token._conn.send_transaction(txn, self.payer, opts=TxOpts(skip_preflight=True, skip_confirmation=False))
self.solana.send_multiple_transactions(self.payer, [txn], skip_preflight=True)
return token_account

def mint_to(self,
amount: int,
ether_addr: Union[str, EthereumAddress],
mint_authority_file: str):
token_account = self.create_account_if_needed(ether_addr)
mint_command = f'spl-token mint "{str(self.token.pubkey)}" {Decimal(amount) * pow(Decimal(10), -9)}'
mint_command = f'spl-token mint "{str(self.token_mint)}" {Decimal(amount) * pow(Decimal(10), -9)}'
mint_command += f' --owner {mint_authority_file} -- "{str(token_account)}"'
os.system(mint_command)
Loading