Skip to content

Commit

Permalink
Merge pull request #31 from Snedashkovsky/add-swaps
Browse files Browse the repository at this point in the history
Add swap execution
  • Loading branch information
Snedashkovsky authored Sep 16, 2023
2 parents 39274e6 + 411714c commit ac3cf29
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 10 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
BASH_PRECOMMAND = ''
BASH_PRECOMMAND = ''
MN = ''
MN2 = ''
10 changes: 5 additions & 5 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@

OSMOSIS_NODE_RPC_URL = 'https://rpc.osmosis-1.bronbro.io:443'
OSMOSIS_NODE_LCD_URL = 'https://lcd.osmosis-1.bronbro.io'
OSMOSIS_POOLS_API_URL = f'{OSMOSIS_NODE_LCD_URL}/osmosis/gamm/v1beta1/pools?pagination.limit=1000' # 'https://lcd-osmosis.keplr.app/osmosis/gamm/v1beta1/pools?pagination.limit=1000'
OSMOSIS_POOLS_API_URL = f'{OSMOSIS_NODE_LCD_URL}/osmosis/gamm/v1beta1/pools?pagination.limit=1000'
OSMOSIS_CHAIN_ID = 'osmosis-1'
OSMOSIS_LCD_CLIENT = LCDClient(chain_id=OSMOSIS_CHAIN_ID, url=OSMOSIS_NODE_LCD_URL, prefix='osmo')
OSMOSIS_BASH_PRECOMMAND = dotenv_values(".env")['BASH_PRECOMMAND']

CRESCENT_NODE_RPC_URL = 'https://mainnet.crescent.network:26657' # 'https://crescent-mainnet-rpc.autostake.net:443'
CRESCENT_NODE_LCD_URL = 'https://mainnet.crescent.network:1317' # 'https://crescent-mainnet-lcd.autostake.net'
CRESCENT_NODE_RPC_URL = 'https://mainnet.crescent.network:26657'
CRESCENT_NODE_LCD_URL = 'https://mainnet.crescent.network:1317'
CRESCENT_POOLS_API_URL = f'{CRESCENT_NODE_LCD_URL}/crescent/liquidity/v1beta1/pools'
CRESCENT_CHAIN_ID = 'crescent-1'
CRESCENT_LCD_CLIENT = LCDClient(chain_id=CRESCENT_CHAIN_ID, url=CRESCENT_NODE_LCD_URL, prefix='cre')
Expand All @@ -86,8 +86,8 @@
COSMOSHUB_CHAIN_ID = 'cosmoshub-4'
COSMOSHUB_LCD_CLIENT = LCDClient(chain_id=COSMOSHUB_CHAIN_ID, url=COSMOSHUB_NODE_LCD_URL, prefix='cosmos')

JUNO_NODE_RPC_URL = 'https://rpc.juno-1.bronbro.io:443'
JUNO_NODE_LCD_URL = 'https://lcd.juno-1.bronbro.io'
JUNO_NODE_RPC_URL = 'https://rpc-juno.ecostake.com:443'
JUNO_NODE_LCD_URL = 'https://rest-juno.ecostake.com'
JUNO_CHAIN_ID = 'juno-1'
JUNO_LCD_CLIENT = LCDClient(chain_id=JUNO_CHAIN_ID, url=JUNO_NODE_LCD_URL, prefix='juno')

Expand Down
151 changes: 147 additions & 4 deletions src/swap_utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import pandas as pd
import numpy as np
import json
from typing import Optional, Union
from math import ceil

from cyber_sdk.core.bech32 import AccAddress
from cyber_sdk.core.coins import Coins
from cyber_sdk.core.coins import Coin, Coins
from cyber_sdk.core.liquidity import MsgSwapWithinBatch
from cyberutils.bash import execute_bash, get_json_from_bash_query

from src.denom_utils import rename_denom, reverse_rename_denom
from config import BOSTROM_CHAIN_ID, BOSTROM_NODE_RPC_URL, POOL_FEE, BOSTROM_LCD_CLIENT, OSMOSIS_LCD_CLIENT, \
PUSSY_LCD_CLIENT, COSMOSHUB_LCD_CLIENT, CRESCENT_LCD_CLIENT, JUNO_LCD_CLIENT, CLI_WALLET
OSMOSIS_NODE_RPC_URL, OSMOSIS_CHAIN_ID, PUSSY_LCD_CLIENT, COSMOSHUB_LCD_CLIENT, CRESCENT_LCD_CLIENT, \
JUNO_LCD_CLIENT, CLI_WALLET, OSMOSIS_BASH_PRECOMMAND


def get_pool_value_by_coin(
Expand Down Expand Up @@ -91,7 +96,8 @@ def get_total_balance(
_balance = 0
_balance_all_coins = Coins()
for _address in addresses:
_balance_item, _balance_all_coins_item = get_balance(address=_address, price_df=price_df,
_balance_item, _balance_all_coins_item = get_balance(address=_address,
price_df=price_df,
base_coin_denom=base_coin_denom,
display_exceptions=display_exceptions)
_balance += _balance_item
Expand Down Expand Up @@ -119,6 +125,7 @@ def generate_swap_bash_query(
price_df: pd.DataFrame,
max_slippage: float = 0.15,
wallet: str = CLI_WALLET,
cli_name: str = 'cyber',
chain_id: str = BOSTROM_CHAIN_ID,
node_rpc_url: str = BOSTROM_NODE_RPC_URL) -> str:
"""
Expand All @@ -130,14 +137,16 @@ def generate_swap_bash_query(
:param price_df: dataframe with price data
:param max_slippage: max slippage
:param wallet: wallet name/address in CLI
:param cli_name: name of a CLI application for bash execution
:param chain_id: chain id
:param node_rpc_url: URL of RPC node
:return: swap bash query for bostrom network
"""
_pool_id = coins_pool_df.loc[:, 'id'].to_list()[0]
_pool_type = coins_pool_df.loc[:, 'type_id'].to_list()[0]
_price = price_df.loc[coin_from_denom, coin_to_denom] * (1 + max_slippage)
return f'cyber tx liquidity swap {_pool_id} {_pool_type} {int(coin_from_amount)}{reverse_rename_denom(coin_from_denom)}' \
return f'{cli_name} tx liquidity swap {_pool_id} {_pool_type} ' \
f'{int(coin_from_amount)}{reverse_rename_denom(coin_from_denom)}' \
f' {reverse_rename_denom(coin_to_denom)} {_price:.12f} 0.003 ' \
f'--from {wallet} --chain-id {chain_id} --gas 200000 --gas-prices 0.01boot --yes ' \
f'--node {node_rpc_url} --broadcast-mode block'
Expand Down Expand Up @@ -173,3 +182,137 @@ def generate_swap_bash_queries(
coins_pool_df=_coins_pool_df, price_df=price_df))
_coin_from_amount = _coin_to_amount
return _coin_from_amount, _coin2_way_queries


def generate_swap_cyber_msg(
coin_from_amount: float,
coin_from_denom: str,
coin_to_denom: str,
coins_pool_df: pd.DataFrame,
price_df: pd.DataFrame,
wallet_address: Union[str, AccAddress],
max_slippage: float = 0.05,
swap_fee: float = POOL_FEE) -> MsgSwapWithinBatch:
"""
Generate a swap message for the liquidity module of the cyber protocol (bostrom and space-pussy chains)
:param coin_from_amount: initial coin amount
:param coin_from_denom: initial coin denom
:param coin_to_denom: received coin denom
:param coins_pool_df: dataframe with pool data
:param price_df: dataframe with price data
:param wallet_address: wallet address in a cyber chain
:param max_slippage: maximum slippage
:param swap_fee: pool fee
:return: swap message
"""
_pool_id = coins_pool_df.loc[:, 'id'].to_list()[0]
_pool_type = coins_pool_df.loc[:, 'type_id'].to_list()[0]
_coin_from_denom = reverse_rename_denom(coin_from_denom)
_coin_to_denom = reverse_rename_denom(coin_to_denom)
_order_price = \
str(
int(
1e18 * (
price_df.loc[coin_from_denom, coin_to_denom] * (1 + max_slippage) \
if _coin_from_denom < _coin_to_denom \
else price_df.loc[coin_to_denom, coin_from_denom] * (1 - max_slippage)
)
)
)

return MsgSwapWithinBatch(
swap_requester_address=AccAddress(wallet_address),
pool_id=int(_pool_id),
swap_type_id=_pool_type,
offer_coin=Coin(amount=int(coin_from_amount), denom=_coin_from_denom),
demand_coin_denom=_coin_to_denom,
offer_coin_fee=Coin(amount=ceil(coin_from_amount * swap_fee / 2), denom=_coin_from_denom),
order_price=_order_price
)


def swap_osmosis(
coin_from_amount: int,
coin_from_denom: str,
coin_to_denom: str,
pools_df: pd.DataFrame,
price_df: pd.DataFrame,
osmosis_wallet_address: str,
fee_amount: int,
tx_unsigned_file_name: str,
tx_signed_file_name: str,
max_slippage: float = 0.05,
gas_limit: int = 250_000,
fee_denom: str = 'uosmo') -> str:
"""
Swap in the gamm module of Osmosis
:param coin_from_amount: initial coin amount
:param coin_from_denom: initial coin denom
:param coin_to_denom: received coin denom
:param pools_df: dataframe with pool data
:param price_df: dataframe with price data
:param osmosis_wallet_address: wallet address in osmosis
:param fee_amount: fee amount
:param tx_unsigned_file_name: file name with unsigned transaction
:param tx_signed_file_name: file name with signed transaction
:param max_slippage: maximum slippage
:param gas_limit: gas limit
:param fee_denom: fee denom
:return: transaction hash
"""
_coins_pool_df = pools_df.loc[
pools_df.apply(
lambda x: coin_from_denom in x.reserve_coin_denoms and coin_to_denom in x.reserve_coin_denoms,
axis=1)
]
_pool_id = _coins_pool_df.loc[:, 'id'].to_list()[0]

_routes = [
{"pool_id": str(_pool_id),
"token_out_denom": reverse_rename_denom(coin_to_denom)}
]
_msgs = [
{"@type": "/osmosis.gamm.v1beta1.MsgSwapExactAmountIn",
"sender": osmosis_wallet_address,
"routes": _routes,
"token_in":
{"denom": reverse_rename_denom(coin_from_denom), "amount": str(int(coin_from_amount))},
"token_out_min_amount": str(
int(coin_from_amount * price_df.loc[coin_to_denom, coin_from_denom] * (1 - max_slippage)))}
]
_tx_unsigned = {
"body":
{"messages": _msgs,
"memo": "",
"timeout_height": "0",
"extension_options": [],
"non_critical_extension_options": []
},
"auth_info":
{"signer_infos": [],
"fee": {
"amount": [{"denom": fee_denom, "amount": str(fee_amount)}],
"gas_limit": str(gas_limit),
"payer": "",
"granter": ""}
},
"signatures": []
}

with open(tx_unsigned_file_name, 'w') as _outfile:
_outfile.write(json.dumps(_tx_unsigned, indent=4))

execute_bash(
bash_command=f'{OSMOSIS_BASH_PRECOMMAND}osmosisd tx sign {tx_unsigned_file_name} '
f'--output-document {tx_signed_file_name} --from {osmosis_wallet_address} '
f'--chain-id {OSMOSIS_CHAIN_ID} --node {OSMOSIS_NODE_RPC_URL}',
shell=True
)
_res_json = get_json_from_bash_query(
bash_command=f'osmosisd tx broadcast {tx_signed_file_name} --output json --broadcast-mode=block '
f'--chain-id {OSMOSIS_CHAIN_ID} --node {OSMOSIS_NODE_RPC_URL}'
)
# print the tx to the console, if there is an error
if 'raw_log' not in _res_json.keys() or _res_json['raw_log'][0] != '[':
print(_res_json)
return _res_json["txhash"]

0 comments on commit ac3cf29

Please sign in to comment.