Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add infura rpc as a fallback rpc provider #26

Merged
merged 8 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
2 changes: 2 additions & 0 deletions mm-bot/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
ENVIRONMENT=
ETH_RPC_URL=
SN_RPC_URL=
ETH_FALLBACK_RPC_URL=
SN_FALLBACK_RPC_URL=
ETH_CONTRACT_ADDR=
SN_CONTRACT_ADDR=
ETH_PRIVATE_KEY=
Expand Down
3 changes: 3 additions & 0 deletions mm-bot/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
ETH_RPC_URL = os.getenv('ETH_RPC_URL')
SN_RPC_URL = os.getenv('SN_RPC_URL')

ETH_FALLBACK_RPC_URL = os.getenv('ETH_FALLBACK_RPC_URL')
SN_FALLBACK_RPC_URL = os.getenv('SN_FALLBACK_RPC_URL')

ETH_CONTRACT_ADDR = os.getenv('ETH_CONTRACT_ADDR')
SN_CONTRACT_ADDR = os.getenv('SN_CONTRACT_ADDR')

Expand Down
59 changes: 37 additions & 22 deletions mm-bot/ethereum.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,47 @@
import os
from web3 import Web3, AsyncWeb3

w3 = Web3(Web3.HTTPProvider(constants.ETH_RPC_URL))
main_w3 = Web3(Web3.HTTPProvider(constants.ETH_RPC_URL))
fallback_w3 = Web3(Web3.HTTPProvider(constants.ETH_FALLBACK_RPC_URL))
w3_clients = [main_w3,fallback_w3]

logger = logging.getLogger(__name__)


def get_latest_block() -> int:
return w3.eth.block_number
for w3 in w3_clients:
try:
return w3.eth.block_number
except Exception as exception:
logger.error(f"[-] Failed to get block number from node: {exception}")
logger.error(f"[-] Failed to get block number from all nodes")


def transfer(deposit_id, dst_addr, amount):
acct = w3.eth.account.from_key(constants.ETH_PRIVATE_KEY)
# get only the abi not the entire file
abi = json.load(open(os.path.dirname(os.path.realpath(__file__)) + '/abi/YABTransfer.json'))['abi']

yab_transfer = w3.eth.contract(address=constants.ETH_CONTRACT_ADDR, abi=abi)
dst_addr_bytes = int(dst_addr, 0)
deposit_id = Web3.to_int(deposit_id)
amount = Web3.to_int(amount)
# we need amount so the transaction is valid with the transfer that will be transferred
unsent_tx = yab_transfer.functions.transfer(deposit_id, dst_addr_bytes, amount).build_transaction({
"chainId": 5,
"from": acct.address,
"nonce": w3.eth.get_transaction_count(acct.address),
"value": amount,
})
signed_tx = w3.eth.account.sign_transaction(unsent_tx, private_key=acct.key)

tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
w3.eth.wait_for_transaction_receipt(tx_hash)
logger.info(f"[+] Transfer tx hash: 0x{tx_hash.hex()}")
for w3 in w3_clients:
try:
acct = w3.eth.account.from_key(constants.ETH_PRIVATE_KEY)
# get only the abi not the entire file
abi = json.load(open(os.path.dirname(os.path.realpath(__file__)) + '/abi/YABTransfer.json'))['abi']

yab_transfer = w3.eth.contract(address=constants.ETH_CONTRACT_ADDR, abi=abi)
dst_addr_bytes = int(dst_addr, 0)
deposit_id = Web3.to_int(deposit_id)
amount = Web3.to_int(amount)
# we need amount so the transaction is valid with the transfer that will be transferred
unsent_tx = yab_transfer.functions.transfer(deposit_id, dst_addr_bytes, amount).build_transaction({
"chainId": 5,
"from": acct.address,
"nonce": w3.eth.get_transaction_count(acct.address),
"value": amount,
})
signed_tx = w3.eth.account.sign_transaction(unsent_tx, private_key=acct.key)

tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
w3.eth.wait_for_transaction_receipt(tx_hash)
return tx_hash.hex()
except Exception as exception:
logger.error(f"[-] Failed to transfer eth on node: {exception}")
logger.error(f"[-] Failed to transfer eth on all nodes")
raise Exception("Failed to transfer eth on all nodes")

3 changes: 2 additions & 1 deletion mm-bot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ async def process_order(order_id, dst_addr, amount, eth_lock):
async with eth_lock:
try:
# in case it's processed on ethereum, but not processed on starknet
await asyncio.to_thread(ethereum.transfer, order_id, dst_addr, amount)
tx_hash_hex = await asyncio.to_thread(ethereum.transfer, order_id, dst_addr, amount)
logger.info(f"[+] Transfer tx hash: 0x{tx_hash_hex}")
logger.info(f"[+] Transfer complete")
except Exception as e:
logger.error(f"[-] Transfer failed: {e}")
Expand Down
89 changes: 52 additions & 37 deletions mm-bot/starknet.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
import logging
import requests
import constants
import json
import os

from starknet_py.contract import Contract
from starknet_py.net.full_node_client import FullNodeClient
from starknet_py.hash.selector import get_selector_from_name
from starknet_py.net.account.account import Account
from starknet_py.net.client_models import Call
from starknet_py.net.full_node_client import FullNodeClient
from starknet_py.net.models.chains import StarknetChainId
from starknet_py.net.signer.stark_curve_signer import KeyPair
from starknet_py.hash.selector import get_selector_from_name
from starknet_py.net.client_models import Call
from starknet_py.cairo.felt import decode_shortstring

import constants

SET_ORDER_EVENT_KEY = 0x2c75a60b5bdad73ebbf539cc807fccd09875c3cbf3f44041f852cdb96d8acd3

full_node_client = FullNodeClient(node_url=constants.SN_RPC_URL)
main_full_node_client = FullNodeClient(node_url=constants.SN_RPC_URL)
fallback_full_node_client = FullNodeClient(node_url=constants.SN_FALLBACK_RPC_URL)
full_node_clients = [main_full_node_client, fallback_full_node_client]

key_pair = KeyPair.from_private_key(key=constants.SN_PRIVATE_KEY)
account = Account(
client=full_node_client,
main_account = Account(
client=main_full_node_client,
address=constants.SN_WALLET_ADDR,
key_pair=key_pair,
chain=StarknetChainId.TESTNET,
)
fallback_account = Account(
client=fallback_full_node_client,
address=constants.SN_WALLET_ADDR,
key_pair=key_pair,
chain=StarknetChainId.TESTNET,
)
accounts = [main_account, fallback_account]

logger = logging.getLogger(__name__)

Expand All @@ -35,21 +40,24 @@ def __init__(self, order_id, recipient_address, amount):
self.amount = amount

def __str__(self):
return f"order_id:{self.order_id}, recipent: {self.recipient_address}, amount: {self.amount}"
return f"order_id:{self.order_id}, recipient: {self.recipient_address}, amount: {self.amount}"


async def get_starknet_events():
try:
events_response = await full_node_client.get_events(
address=constants.SN_CONTRACT_ADDR,
chunk_size=10,
keys=[[SET_ORDER_EVENT_KEY]],
from_block_number='pending'
)
except Exception as e:
logger.error(f"[-] Failed to get events: {e}")
return None
return events_response
for client in full_node_clients:
try:
events_response = await client.get_events(
address=constants.SN_CONTRACT_ADDR,
chunk_size=10,
keys=[[SET_ORDER_EVENT_KEY]],
from_block_number='pending'
)
return events_response
except Exception as exception:
logger.error(f"[-] Failed to get events from node: {exception}")

logger.error(f"[-] Failed to get events from all nodes")
return None


async def get_is_used_order(order_id) -> bool:
Expand All @@ -58,11 +66,14 @@ async def get_is_used_order(order_id) -> bool:
selector=get_selector_from_name("get_order_used"),
calldata=[order_id, 0],
)
try:
status = await account.client.call_contract(call)
return status[0]
except Exception as e:
return True
for account in accounts:
try:
status = await account.client.call_contract(call)
return status[0]
except Exception as exception:
logger.error(f"[-] Failed to get order status from node: {exception}")
logger.error(f"[-] Failed to get order status from all nodes")
return True


async def get_latest_unfulfilled_orders():
Expand Down Expand Up @@ -93,11 +104,15 @@ async def withdraw(order_id, block, slot) -> bool:
selector=get_selector_from_name("withdraw"),
calldata=[order_id, 0, block, 0, slot_low, slot_high]
)
try:
transaction = await account.sign_invoke_transaction(call, max_fee=10000000000000)
result = await account.client.send_transaction(transaction)
await account.client.wait_for_tx(result.transaction_hash)

logger.info(f"[+] Withdrawn from starknet: {hex(result.transaction_hash)}")
except Exception as e:
logger.error(f"[-] Failed to withdraw from starknet: {e}")
for account in accounts:
try:
transaction = await account.sign_invoke_transaction(call, max_fee=10000000000000)
JuArce marked this conversation as resolved.
Show resolved Hide resolved
result = await account.client.send_transaction(transaction)
await account.client.wait_for_tx(result.transaction_hash)

logger.info(f"[+] Withdrawn from starknet: {hex(result.transaction_hash)}")
return True
except Exception as e:
logger.error(f"[-] Failed to withdraw from starknet: {e}")
logger.error(f"[-] Failed to withdraw from all nodes")
return False