Skip to content

Commit 653fff7

Browse files
committed
feat(market): support all xeggex market pairs
1 parent 1f19520 commit 653fff7

File tree

6 files changed

+204
-106
lines changed

6 files changed

+204
-106
lines changed
File renamed without changes.

assets/tradeogre.png

8.17 KB
Loading

assets/xeggex.png

2.88 KB
Loading

cogs/market.py

Lines changed: 132 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING
3+
from typing import TYPE_CHECKING, Any, Dict, List
44

55
from datetime import UTC, time, datetime, timedelta
66

@@ -12,7 +12,11 @@
1212
from discord.ext.menus.views import ViewMenuPages
1313

1414
from utils.cd import cooldown
15-
from utils.paginators import TradeOgrePaginatorSource, HistoricalPricePaginatorSource
15+
from utils.paginators import (
16+
XeggeXPaginatorSource,
17+
TradeOgrePaginatorSource,
18+
HistoricalPricePaginatorSource,
19+
)
1620

1721
if TYPE_CHECKING:
1822
from bot import RoboNerva
@@ -181,44 +185,57 @@ async def _tradeogre(self, ctx: discord.Interaction):
181185
# noinspection PyUnresolvedReferences
182186
await ctx.response.defer(thinking=True)
183187

184-
entries = list()
185-
186-
async with aiohttp.ClientSession() as session:
187-
async with session.get(
188-
"https://tradeogre.com/api/v1/ticker/xnv-btc"
189-
) as res:
190-
data = await res.json(content_type=None)
191-
192-
entry = {
193-
"pair": "XNV-BTC",
194-
"last_price": f"{round(float(data['price']) * 100_000_000)} sat",
195-
"bid": f"{round(float(data['bid']) * 100_000_000)} sat",
196-
"ask": f"{round(float(data['ask']) * 100_000_000)} sat",
197-
"volume": f"{float(data['volume'])} BTC",
198-
"high": f"{round(float(data['high']) * 100_000_000)} sat",
199-
"low": f"{round(float(data['low']) * 100_000_000)} sat",
200-
}
201-
202-
entries.append(entry)
203-
204-
async with session.get(
205-
"https://tradeogre.com/api/v1/ticker/xnv-usdt"
206-
) as res:
207-
data = await res.json(content_type=None)
208-
209-
entry = {
210-
"pair": "XNV-USDT",
211-
"last_price": f"${round(float(data['price']), 4)}",
212-
"bid": f"${round(float(data['bid']), 4)}",
213-
"ask": f"${round(float(data['ask']), 4)}",
214-
"volume": f"${round(float(data['volume']), 2)}",
215-
"high": f"${round(float(data['high']), 4)}",
216-
"low": f"${round(float(data['low']), 4)}",
217-
}
218-
219-
entries.append(entry)
220-
221-
pages = TradeOgrePaginatorSource(entries=entries, ctx=ctx)
188+
market_data: List[Dict] = list()
189+
190+
for pair in self.bot.config.TRADEOGRE_MARKET_PAIRS:
191+
async with aiohttp.ClientSession() as session:
192+
async with session.get(
193+
f"https://tradeogre.com/api/v1/ticker/{pair.lower()}"
194+
) as res:
195+
data: Dict[str, Any] = await res.json(content_type=None)
196+
197+
if "error" in data:
198+
continue
199+
200+
else:
201+
last_price: str
202+
bid: str
203+
ask: str
204+
volume: str
205+
high: str
206+
low: str
207+
208+
if pair.endswith("BTC"):
209+
last_price = (
210+
f"{round(float(data['price']) * 100_000_000)} sat"
211+
)
212+
bid = f"{round(float(data['bid']) * 100_000_000)} sat"
213+
ask = f"{round(float(data['ask']) * 100_000_000)} sat"
214+
volume = f"{float(data['volume'])} BTC"
215+
high = f"{round(float(data['high']) * 100_000_000)} sat"
216+
low = f"{round(float(data['low']) * 100_000_000)} sat"
217+
218+
else:
219+
last_price = f"${round(float(data['price']), 4)}"
220+
bid = f"${round(float(data['bid']), 4)}"
221+
ask = f"${round(float(data['ask']), 4)}"
222+
volume = f"${round(float(data['volume']), 2)}"
223+
high = f"${round(float(data['high']), 4)}"
224+
low = f"${round(float(data['low']), 4)}"
225+
226+
market_data.append(
227+
{
228+
"pair": pair,
229+
"last_price": last_price,
230+
"bid": bid,
231+
"ask": ask,
232+
"volume": volume,
233+
"high": high,
234+
"low": low,
235+
}
236+
)
237+
238+
pages = TradeOgrePaginatorSource(entries=market_data, ctx=ctx)
222239
paginator = ViewMenuPages(
223240
source=pages,
224241
timeout=300,
@@ -246,45 +263,83 @@ async def _xeggex(self, ctx: discord.Interaction):
246263
"q=tbn:ANd9GcQge9tw8HHcbwBXNALMQvysPoL6s-bFhJjA3g&s"
247264
)
248265

249-
async with aiohttp.ClientSession() as session:
250-
async with session.get(
251-
"https://api.xeggex.com/api/v2/market/getbysymbol/XNV_USDT"
252-
) as res:
253-
data = await res.json()
254-
255-
embed.add_field(
256-
name="Last Price", value=f"${round(float(data['lastPrice']), 4)}"
257-
)
258-
embed.add_field(
259-
name="Bid", value=f"${round(float(data['bestBid']), 4)}"
260-
)
261-
embed.add_field(
262-
name="Ask", value=f"${round(float(data['bestAsk']), 4)}"
263-
)
264-
embed.add_field(
265-
name="Volume", value=f"{round(float(data['volume']), 2)}"
266-
)
267-
embed.add_field(
268-
name="High", value=f"${round(float(data['highPrice']), 4)}"
269-
)
270-
embed.add_field(
271-
name="Low", value=f"${round(float(data['lowPrice']), 4)}"
272-
)
273-
embed.add_field(
274-
name="Last Trade",
275-
value=f"<t:{data['lastTradeAt'] // 1000}:F> "
276-
f"(<t:{data['lastTradeAt'] // 1000}:R>)",
277-
)
278-
279-
view = discord.ui.View()
280-
view.add_item(
281-
discord.ui.Button(
282-
label="Xeggex (XNV-USDT)",
283-
url="https://xeggex.com/market/XNV_USDT",
284-
)
266+
market_data: List[Dict] = list()
267+
268+
for pair in self.bot.config.XEGGEX_MARKET_PAIRS:
269+
async with aiohttp.ClientSession() as session:
270+
async with session.get(
271+
f"https://api.xeggex.com/api/v2/market/getbysymbol/{pair.replace('-', '_')}"
272+
) as res:
273+
data: Dict[str, Any] = await res.json()
274+
275+
if "error" in data:
276+
continue
277+
278+
else:
279+
last_price: str
280+
bid: str
281+
ask: str
282+
volume: str
283+
high: str
284+
low: str
285+
last_trade: str
286+
287+
if pair.endswith("BTC"):
288+
last_price = f"{round(float(data['lastPrice']) * 100_000_000)} sat"
289+
bid = (
290+
f"{round(float(data['bestBid']) * 100_000_000)} sat"
291+
)
292+
ask = (
293+
f"{round(float(data['bestAsk']) * 100_000_000)} sat"
294+
)
295+
volume = f"{float(data['volumeSecondary'])} BTC"
296+
high = f"{round(float(data['highPrice']) * 100_000_000)} sat"
297+
low = (
298+
f"{round(float(data['lowPrice']) * 100_000_000)} sat"
299+
)
300+
last_trade = data["lastTradeAt"] // 1000
301+
302+
elif pair.endswith("USDT") or pair.endswith("USDC"):
303+
last_price = f"${round(float(data['lastPrice']), 4)}"
304+
bid = f"${round(float(data['bestBid']), 4)}"
305+
ask = f"${round(float(data['bestAsk']), 4)}"
306+
volume = f"${round(float(data['volumeSecondary']), 2)}"
307+
high = f"${round(float(data['highPrice']), 4)}"
308+
low = f"${round(float(data['lowPrice']), 4)}"
309+
last_trade = data["lastTradeAt"] // 1000
310+
311+
else:
312+
last_price = f"{round(float(data['lastPrice']), 4)} XPE"
313+
bid = f"{round(float(data['bestBid']), 4)} XPE"
314+
ask = f"{round(float(data['bestAsk']), 4)} XPE"
315+
volume = f"{float(data['volumeSecondary'])} XPE"
316+
high = f"{round(float(data['highPrice']), 4)} XPE"
317+
low = f"{round(float(data['lowPrice']), 4)} XPE"
318+
last_trade = data["lastTradeAt"] // 1000
319+
320+
market_data.append(
321+
{
322+
"pair": pair,
323+
"last_price": last_price,
324+
"bid": bid,
325+
"ask": ask,
326+
"volume": volume,
327+
"high": high,
328+
"low": low,
329+
"last_trade": last_trade,
330+
}
331+
)
332+
333+
pages = XeggeXPaginatorSource(entries=market_data, ctx=ctx)
334+
paginator = ViewMenuPages(
335+
source=pages,
336+
timeout=300,
337+
delete_message_after=False,
338+
clear_reactions_after=True,
285339
)
286340

287-
await ctx.edit_original_response(embed=embed, view=view)
341+
await ctx.edit_original_response(content="\U0001f44c")
342+
await paginator.start(ctx)
288343

289344
@app_commands.command(name="history")
290345
@app_commands.guilds(COMMUNITY_GUILD_ID)

config.example.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,54 @@
1-
DISCORD_TOKEN = "bot_token"
2-
TELEGRAM_TOKEN = "telegram_token"
1+
DISCORD_TOKEN = "..."
2+
TELEGRAM_TOKEN = "..."
33

4-
TELEGRAM_CHAT_ID = -1001234567890
4+
TELEGRAM_CHAT_ID = ...
55

6-
EMBED_COLOR = 0x00000
6+
EMBED_COLOR = ...
77

8-
LOG_WEBHOOK_ID = 1234567890
9-
LOG_WEBHOOK_TOKEN = "log_webhook_token"
8+
LOG_WEBHOOK_ID = ...
9+
LOG_WEBHOOK_TOKEN = "..."
1010

11-
AUTOMOD_WEBHOOK_ID = 1234567890
12-
AUTOMOD_WEBHOOK_TOKEN = "automod_webhook_token"
11+
AUTOMOD_WEBHOOK_ID = ...
12+
AUTOMOD_WEBHOOK_TOKEN = "..."
1313

14-
COMMUNITY_GUILD_ID = 1234567890
14+
COMMUNITY_GUILD_ID = ...
1515

16-
TIPBOT_USER_ID = 1234567890
16+
TIPBOT_USER_ID = ...
1717

18-
VERIFIED_USER_ROLE_ID = 1234567890
19-
UNVERIFIED_USER_ROLE_ID = 1234567890
18+
VERIFIED_USER_ROLE_ID = ...
19+
UNVERIFIED_USER_ROLE_ID = ...
2020

2121
ADMIN_ROLE_IDS = [...]
2222
DEVELOPER_USER_IDS = [...]
2323

24-
MONGODB_URI = "mongodb_uri"
25-
MONGODB_DATABASE = "mongodb_database"
24+
MONGODB_URI = "..."
25+
MONGODB_DATABASE = "..."
2626

27-
COINGECKO_API_KEY = "coingecko_api_key"
27+
COINGECKO_API_KEY = "..."
2828

29-
GITHUB_TOKEN = "github_token"
29+
GITHUB_TOKEN = "..."
3030

31-
TWITTER_USERNAME = "twitter_username"
32-
TWITTER_EMAIL = "twitter_email"
33-
TWITTER_PASSWORD = "twitter_password"
31+
TWITTER_USERNAME = "..."
32+
TWITTER_EMAIL = "..."
33+
TWITTER_PASSWORD = "..."
3434

35-
FALLBACK_TWEET_ID = 1234567890
35+
FALLBACK_TWEET_ID = ...
3636

37-
AUTOPOST_VOTE_REMINDER_CHANNEL_ID = 1234567890
38-
AUTOPOST_PRICE_UPDATE_CHANNEL_ID = 1234567890
39-
RULES_CHANNEL_ID = 1234567890
40-
WELCOME_CHANNEL_ID = 1234567890
41-
TIPBOT_CHANNEL_ID = 1234567890
37+
AUTOPOST_VOTE_REMINDER_CHANNEL_ID = ...
38+
AUTOPOST_PRICE_UPDATE_CHANNEL_ID = ...
39+
RULES_CHANNEL_ID = ...
40+
WELCOME_CHANNEL_ID = ...
41+
TIPBOT_CHANNEL_ID = ...
4242

43-
AUTOPOST_MINUTES_AFTER_UTC = 0
44-
MARKET_HISTORY_HOURS_AFTER_UTC = 0
43+
AUTOPOST_MINUTES_AFTER_UTC = ...
44+
MARKET_HISTORY_HOURS_AFTER_UTC = ...
4545

46-
AUTOMOD_CHANNEL_HISTORY_MESSAGE_LIMIT = 0
46+
AUTOMOD_CHANNEL_HISTORY_MESSAGE_LIMIT = ...
4747

4848
NAME_BLACKLIST_REGEX = [...]
49-
5049
MESSAGE_BLACKLIST_REGEX = [...]
5150

51+
TRADEOGRE_MARKET_PAIRS = [...]
52+
XEGGEX_MARKET_PAIRS = [...]
53+
5254
INITIAL_EXTENSIONS = [...]

utils/paginators.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,47 @@ def is_paginating(self) -> bool:
9898
return True
9999

100100

101+
class XeggeXPaginatorSource(ListPageSource):
102+
def __init__(
103+
self,
104+
entries: list,
105+
ctx: discord.Interaction,
106+
per_page: Optional[int] = 1,
107+
):
108+
super().__init__(list(enumerate(entries, 1)), per_page=per_page)
109+
110+
self.ctx = ctx
111+
self.total_pages = len(entries)
112+
113+
async def format_page(self, menu: Menu, item: Any) -> discord.Embed:
114+
page_no, item = item
115+
116+
embed = discord.Embed(colour=EMBED_COLOR)
117+
embed.title = f"**{item['pair']}** on XeggeX"
118+
embed.url = f"https://xeggex.com/market/{item['pair']}"
119+
120+
embed.set_author(name="RoboNerva", icon_url=self.ctx.guild.me.avatar.url)
121+
embed.set_thumbnail(
122+
url="https://encrypted-tbn0.gstatic.com/images?"
123+
"q=tbn:ANd9GcQge9tw8HHcbwBXNALMQvysPoL6s-bFhJjA3g&s"
124+
)
125+
126+
embed.add_field(name="Last Price", value=item["last_price"])
127+
embed.add_field(name="Bid", value=item["bid"])
128+
embed.add_field(name="Ask", value=item["ask"])
129+
embed.add_field(name="Volume", value=item["volume"])
130+
embed.add_field(name="High", value=item["high"])
131+
embed.add_field(name="Low", value=item["low"])
132+
embed.add_field(name="Last Trade", value=f"<t:{item['last_trade']}:R>")
133+
134+
embed.set_footer(text=f"Entry {page_no}/{self.total_pages}")
135+
136+
return embed
137+
138+
def is_paginating(self) -> bool:
139+
return True
140+
141+
101142
class IPBanPaginatorSource(ListPageSource):
102143
def __init__(
103144
self,

0 commit comments

Comments
 (0)