mrkts 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mrkts/__init__.py +6 -0
- mrkts/auth.py +12 -0
- mrkts/client.py +145 -0
- mrkts/market/client.py +11 -0
- mrkts/market/gifts.py +195 -0
- mrkts/market/offers.py +29 -0
- mrkts/market/orders.py +155 -0
- mrkts/pool.py +101 -0
- mrkts/steam/client.py +56 -0
- mrkts/steam/cs2/client.py +10 -0
- mrkts/steam/cs2/offers.py +5 -0
- mrkts/steam/cs2/orders.py +5 -0
- mrkts/steam/cs2/skins.py +285 -0
- mrkts/user.py +54 -0
- mrkts/utils.py +75 -0
- mrkts-0.2.0.dist-info/METADATA +269 -0
- mrkts-0.2.0.dist-info/RECORD +20 -0
- mrkts-0.2.0.dist-info/WHEEL +5 -0
- mrkts-0.2.0.dist-info/licenses/LICENSE +21 -0
- mrkts-0.2.0.dist-info/top_level.txt +1 -0
mrkts/__init__.py
ADDED
mrkts/auth.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
async def get_token(init_data: str, *, proxy: str | None = None) -> str:
|
|
2
|
+
from .client import MrktClient
|
|
3
|
+
|
|
4
|
+
async with MrktClient(token=None, proxy=proxy) as client:
|
|
5
|
+
return await client.auth(init_data)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def refresh_token(session: str, *, workdir: str = ".", proxy: str | None = None) -> str:
|
|
9
|
+
from .utils import get_init_data
|
|
10
|
+
|
|
11
|
+
init_data = await get_init_data(session, workdir=workdir, proxy=proxy)
|
|
12
|
+
return await get_token(init_data, proxy=proxy)
|
mrkts/client.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Main object of MRKT client"""
|
|
2
|
+
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
import random
|
|
5
|
+
from aiohttp import ClientSession
|
|
6
|
+
from .auth import get_token, refresh_token
|
|
7
|
+
|
|
8
|
+
_preloads = {
|
|
9
|
+
"market": (".market.client", "MarketClient"),
|
|
10
|
+
"steam": (".steam.client", "SteamClient"),
|
|
11
|
+
"user": (".user", "User"),
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class MrktClient:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
token: str | None = None,
|
|
18
|
+
*,
|
|
19
|
+
session: str | None = None,
|
|
20
|
+
preload: tuple[str, ...] | None = None,
|
|
21
|
+
workdir: str = ".",
|
|
22
|
+
proxy: str | None = None,
|
|
23
|
+
headers: dict | None = None,
|
|
24
|
+
):
|
|
25
|
+
self.token = token
|
|
26
|
+
self._session = session
|
|
27
|
+
self.workdir = workdir
|
|
28
|
+
self.proxy = proxy
|
|
29
|
+
self.headers = headers or {}
|
|
30
|
+
self._closed = False
|
|
31
|
+
self.http: ClientSession | None = None
|
|
32
|
+
self.web = ClientSession | None = None
|
|
33
|
+
|
|
34
|
+
for name in preload or []:
|
|
35
|
+
self._preload(name)
|
|
36
|
+
|
|
37
|
+
def _setup_http(self):
|
|
38
|
+
chrome, edge = random.randint(120, 145), random.randint(120, 145)
|
|
39
|
+
|
|
40
|
+
headers = {
|
|
41
|
+
"accept": "application/json, text/plain, */*",
|
|
42
|
+
"accept-encoding": "gzip, deflate",
|
|
43
|
+
"accept-language": "ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7",
|
|
44
|
+
"content-type": "application/json",
|
|
45
|
+
"origin": "https://cdn.tgmrkt.io",
|
|
46
|
+
"priority": "u=1, i",
|
|
47
|
+
"referer": "https://cdn.tgmrkt.io/",
|
|
48
|
+
"sec-ch-ua": f'"Not=A?Brand";v="8", "Chromium";v="{chrome}", "Microsoft Edge";v="{edge}"',
|
|
49
|
+
"sec-ch-ua-mobile": "?0",
|
|
50
|
+
"sec-ch-ua-platform": random.choice(['"Windows"', '"macOS"', '"Linux"']),
|
|
51
|
+
"sec-fetch-dest": "empty",
|
|
52
|
+
"sec-fetch-mode": "cors",
|
|
53
|
+
"sec-fetch-site": "same-site",
|
|
54
|
+
"sec-fetch-storage-access": "active",
|
|
55
|
+
"user-agent": f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{chrome}.0.0.0 Safari/537.36 Edg/{edge}.0.0.0",
|
|
56
|
+
}
|
|
57
|
+
if self.token:
|
|
58
|
+
headers["authorization"] = f"Bearer {self.token}"
|
|
59
|
+
headers["cookie"] = f"access_token={self.token}"
|
|
60
|
+
self.headers.update(headers)
|
|
61
|
+
|
|
62
|
+
self.http = ClientSession(
|
|
63
|
+
base_url="https://api.tgmrkt.io/api/v1/",
|
|
64
|
+
headers=self.headers,
|
|
65
|
+
proxy=self.proxy,
|
|
66
|
+
)
|
|
67
|
+
self._closed = False
|
|
68
|
+
|
|
69
|
+
async def auth(self, tgWebAppData: str) -> str:
|
|
70
|
+
if not self.http:
|
|
71
|
+
self._setup_http()
|
|
72
|
+
response = await self.http.post("auth", json={"data": tgWebAppData})
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
data = response.json()
|
|
75
|
+
token = data.get("token")
|
|
76
|
+
if not token:
|
|
77
|
+
raise ValueError(f"Auth failed: {data}")
|
|
78
|
+
return token
|
|
79
|
+
|
|
80
|
+
async def start(self) -> "MrktClient":
|
|
81
|
+
if not self.token and self._session:
|
|
82
|
+
self.token = await refresh_token(session=self._session, workdir=self.workdir, proxy=self.proxy)
|
|
83
|
+
if not self.http and self.token:
|
|
84
|
+
self._setup_http()
|
|
85
|
+
return self
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
async def session(
|
|
89
|
+
cls,
|
|
90
|
+
session: str,
|
|
91
|
+
*,
|
|
92
|
+
workdir: str = ".",
|
|
93
|
+
proxy: str | None = None,
|
|
94
|
+
**kwargs
|
|
95
|
+
):
|
|
96
|
+
token = await refresh_token(session, workdir=workdir, proxy=proxy)
|
|
97
|
+
return cls(token=token, workdir=workdir, proxy=proxy, **kwargs)
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
async def init_data(
|
|
101
|
+
cls,
|
|
102
|
+
init_data: str,
|
|
103
|
+
*,
|
|
104
|
+
workdir: str = ".",
|
|
105
|
+
proxy: str | None = None,
|
|
106
|
+
impersonate: str = "chrome124",
|
|
107
|
+
**kwargs,
|
|
108
|
+
) -> "MrktClient":
|
|
109
|
+
token = await get_token(init_data, proxy=proxy)
|
|
110
|
+
return cls(token=token, workdir=workdir, proxy=proxy, impersonate=impersonate, **kwargs)
|
|
111
|
+
|
|
112
|
+
def set_token(self, token: str) -> None:
|
|
113
|
+
self.token = token
|
|
114
|
+
self.headers["authorization"] = f"Bearer {token}"
|
|
115
|
+
self.headers["cookie"] = f"access_token={token}"
|
|
116
|
+
|
|
117
|
+
if self.http is None:
|
|
118
|
+
self._setup_http()
|
|
119
|
+
else:
|
|
120
|
+
self.http.headers.update({
|
|
121
|
+
"authorization": f"Bearer {token}",
|
|
122
|
+
"cookie": f"access_token={token}",
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
def _preload(self, name: str) -> None:
|
|
126
|
+
try:
|
|
127
|
+
module_name, class_name = _preloads[name]
|
|
128
|
+
except KeyError:
|
|
129
|
+
raise ValueError(f"Unknown preload: {name!r}") from None
|
|
130
|
+
|
|
131
|
+
module = import_module(module_name, package=__package__)
|
|
132
|
+
cls = getattr(module, class_name)
|
|
133
|
+
|
|
134
|
+
setattr(self, name, cls(self))
|
|
135
|
+
|
|
136
|
+
async def __aenter__(self):
|
|
137
|
+
return await self.start()
|
|
138
|
+
|
|
139
|
+
async def __aexit__(self, *args):
|
|
140
|
+
await self.close()
|
|
141
|
+
|
|
142
|
+
async def close(self):
|
|
143
|
+
if not self._closed and self.http:
|
|
144
|
+
await self.http.close()
|
|
145
|
+
self._closed = True
|
mrkts/market/client.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'''Market object of MRKT client'''
|
|
2
|
+
|
|
3
|
+
from .gifts import Gifts
|
|
4
|
+
from .orders import Orders
|
|
5
|
+
from .offers import Offers
|
|
6
|
+
|
|
7
|
+
class MarketClient:
|
|
8
|
+
def __init__(self, client):
|
|
9
|
+
self.gifts = Gifts(client)
|
|
10
|
+
self.orders = Orders(client)
|
|
11
|
+
self.offers = Offers(client)
|
mrkts/market/gifts.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
'''Gifts object of MRKT client'''
|
|
2
|
+
|
|
3
|
+
class Gifts:
|
|
4
|
+
def __init__(self, client):
|
|
5
|
+
self._client = client
|
|
6
|
+
|
|
7
|
+
async def saling(
|
|
8
|
+
self,
|
|
9
|
+
*,
|
|
10
|
+
count: int = 20,
|
|
11
|
+
cursor: str = "",
|
|
12
|
+
collectionNames: list[str] | None = None,
|
|
13
|
+
modelNames: list[str] | None = None,
|
|
14
|
+
backdropNames: list[str] | None = None,
|
|
15
|
+
symbolNames: list[str] | None = None,
|
|
16
|
+
number: int | None = None,
|
|
17
|
+
isNew: bool | None = None,
|
|
18
|
+
isPremarket: bool | None = None,
|
|
19
|
+
luckyBuy: bool | None = None,
|
|
20
|
+
giftType: str | None = None,
|
|
21
|
+
craftable: bool | None = None,
|
|
22
|
+
isCrafted: bool | None = None,
|
|
23
|
+
tgCanBeCraftedFrom: bool | None = None,
|
|
24
|
+
removeSelfSales: bool | None = None,
|
|
25
|
+
isTransferable: bool | None = None,
|
|
26
|
+
availableForStaking: bool | None = None,
|
|
27
|
+
forGame: bool | None = None,
|
|
28
|
+
minPrice: int | None = None,
|
|
29
|
+
maxPrice: int | None = None,
|
|
30
|
+
ordering: str = "Price",
|
|
31
|
+
lowToHigh: bool = True,
|
|
32
|
+
query: str | None = None,
|
|
33
|
+
**kwargs
|
|
34
|
+
) -> dict:
|
|
35
|
+
payload = {
|
|
36
|
+
"count": count,
|
|
37
|
+
"cursor": cursor,
|
|
38
|
+
"collectionNames": collectionNames or [],
|
|
39
|
+
"modelNames": modelNames or [],
|
|
40
|
+
"backdropNames": backdropNames or [],
|
|
41
|
+
"symbolNames": symbolNames or [],
|
|
42
|
+
"number": number,
|
|
43
|
+
"isNew": isNew,
|
|
44
|
+
"isPremarket": isPremarket,
|
|
45
|
+
"luckyBuy": luckyBuy,
|
|
46
|
+
"giftType": giftType,
|
|
47
|
+
"craftable": craftable,
|
|
48
|
+
"isCrafted": isCrafted,
|
|
49
|
+
"tgCanBeCraftedFrom": tgCanBeCraftedFrom,
|
|
50
|
+
"removeSelfSales": removeSelfSales,
|
|
51
|
+
"isTransferable": isTransferable,
|
|
52
|
+
"availableForStaking": availableForStaking,
|
|
53
|
+
"forGame": forGame,
|
|
54
|
+
"minPrice": minPrice,
|
|
55
|
+
"maxPrice": maxPrice,
|
|
56
|
+
"ordering": ordering,
|
|
57
|
+
"lowToHigh": lowToHigh,
|
|
58
|
+
"query": query,
|
|
59
|
+
**kwargs
|
|
60
|
+
}
|
|
61
|
+
payload = {k: v for k, v in payload.items() if v is not None}
|
|
62
|
+
|
|
63
|
+
response = await self._client.http.post("gifts/saling", json=payload)
|
|
64
|
+
response.raise_for_status()
|
|
65
|
+
return await response.json()
|
|
66
|
+
|
|
67
|
+
async def buy(self, *, ids: list):
|
|
68
|
+
response = await self._client.http.post("gifts/buy", json={"ids": ids})
|
|
69
|
+
response.raise_for_status()
|
|
70
|
+
return await response.json()
|
|
71
|
+
|
|
72
|
+
async def sale(self, *, ids: list, price: int):
|
|
73
|
+
response = await self._client.http.post("gifts/sale", json={"ids": ids, "price": price})
|
|
74
|
+
response.raise_for_status()
|
|
75
|
+
return await response.json()
|
|
76
|
+
|
|
77
|
+
async def collections(self) -> list[dict]:
|
|
78
|
+
response = await self._client.http.get("gifts/collections")
|
|
79
|
+
response.raise_for_status()
|
|
80
|
+
return await response.json()
|
|
81
|
+
|
|
82
|
+
async def models(self, collections: list[str]) -> list[dict]:
|
|
83
|
+
response = await self._client.http.post("gifts/models", json={"collections": collections})
|
|
84
|
+
response.raise_for_status()
|
|
85
|
+
return await response.json()
|
|
86
|
+
|
|
87
|
+
async def backdrops(self, collections: list[str]) -> list[dict]:
|
|
88
|
+
response = await self._client.http.post("gifts/backdrops", json={"collections": collections})
|
|
89
|
+
response.raise_for_status()
|
|
90
|
+
return await response.json()
|
|
91
|
+
|
|
92
|
+
async def inventory(
|
|
93
|
+
self,
|
|
94
|
+
*,
|
|
95
|
+
isListed: bool = False,
|
|
96
|
+
count: int = 20,
|
|
97
|
+
cursor: str = "",
|
|
98
|
+
collectionNames: list[str] | None = None,
|
|
99
|
+
modelNames: list[str] | None = None,
|
|
100
|
+
backdropNames: list[str] | None = None,
|
|
101
|
+
symbolNames: list[str] | None = None,
|
|
102
|
+
number: int | None = None,
|
|
103
|
+
isNew: bool | None = None,
|
|
104
|
+
isPremarket: bool | None = None,
|
|
105
|
+
luckyBuy: bool | None = None,
|
|
106
|
+
giftType: str | None = None,
|
|
107
|
+
craftable: bool | None = None,
|
|
108
|
+
isCrafted: bool | None = None,
|
|
109
|
+
tgCanBeCraftedFrom: bool | None = None,
|
|
110
|
+
removeSelfSales: bool | None = None,
|
|
111
|
+
isTransferable: bool | None = None,
|
|
112
|
+
availableForStaking: bool | None = None,
|
|
113
|
+
forGame: bool | None = None,
|
|
114
|
+
minPrice: int | None = None,
|
|
115
|
+
maxPrice: int | None = None,
|
|
116
|
+
ordering: str = "None",
|
|
117
|
+
lowToHigh: bool = False,
|
|
118
|
+
query: str | None = None,
|
|
119
|
+
**kwargs
|
|
120
|
+
) -> dict:
|
|
121
|
+
payload = {
|
|
122
|
+
"isListed": isListed,
|
|
123
|
+
"count": count,
|
|
124
|
+
"cursor": cursor,
|
|
125
|
+
"collectionNames": collectionNames or [],
|
|
126
|
+
"modelNames": modelNames or [],
|
|
127
|
+
"backdropNames": backdropNames or [],
|
|
128
|
+
"symbolNames": symbolNames or [],
|
|
129
|
+
"number": number,
|
|
130
|
+
"isNew": isNew,
|
|
131
|
+
"isPremarket": isPremarket,
|
|
132
|
+
"luckyBuy": luckyBuy,
|
|
133
|
+
"giftType": giftType,
|
|
134
|
+
"craftable": craftable,
|
|
135
|
+
"isCrafted": isCrafted,
|
|
136
|
+
"tgCanBeCraftedFrom": tgCanBeCraftedFrom,
|
|
137
|
+
"removeSelfSales": removeSelfSales,
|
|
138
|
+
"isTransferable": isTransferable,
|
|
139
|
+
"availableForStaking": availableForStaking,
|
|
140
|
+
"forGame": forGame,
|
|
141
|
+
"minPrice": minPrice,
|
|
142
|
+
"maxPrice": maxPrice,
|
|
143
|
+
"ordering": ordering,
|
|
144
|
+
"lowToHigh": lowToHigh,
|
|
145
|
+
"query": query,
|
|
146
|
+
**kwargs
|
|
147
|
+
}
|
|
148
|
+
payload = {k: v for k, v in payload.items() if v is not None}
|
|
149
|
+
|
|
150
|
+
response = await self._client.http.post("gifts", json=payload)
|
|
151
|
+
response.raise_for_status()
|
|
152
|
+
return await response.json()
|
|
153
|
+
|
|
154
|
+
async def history(self, *, limit: int = 20, type: str = "Gift", **kwargs) -> dict:
|
|
155
|
+
response = await self._client.http.get("history", json={"limit": limit, "type": type, **kwargs})
|
|
156
|
+
response.raise_for_status()
|
|
157
|
+
return await response.json()
|
|
158
|
+
|
|
159
|
+
async def feed(
|
|
160
|
+
self,
|
|
161
|
+
*,
|
|
162
|
+
count: int = 20,
|
|
163
|
+
cursor: str = "",
|
|
164
|
+
collectionNames: list[str] | None = None,
|
|
165
|
+
modelNames: list[str] | None = None,
|
|
166
|
+
backdropNames: list[str] | None = None,
|
|
167
|
+
number: int | None = None,
|
|
168
|
+
type: list[str] | None = None, # "listing", "sale", "return", "unlisting", "changeprice", "withdraw"
|
|
169
|
+
minPrice: int | None = None,
|
|
170
|
+
maxPrice: int | None = None,
|
|
171
|
+
ordering: str = "Latest",
|
|
172
|
+
lowToHigh: bool = False,
|
|
173
|
+
query: str | None = None,
|
|
174
|
+
**kwargs
|
|
175
|
+
) -> dict:
|
|
176
|
+
payload = {
|
|
177
|
+
"count": count,
|
|
178
|
+
"cursor": cursor,
|
|
179
|
+
"collectionNames": collectionNames or [],
|
|
180
|
+
"modelNames": modelNames or [],
|
|
181
|
+
"backdropNames": backdropNames or [],
|
|
182
|
+
"number": number,
|
|
183
|
+
"type": type or [],
|
|
184
|
+
"minPrice": minPrice,
|
|
185
|
+
"maxPrice": maxPrice,
|
|
186
|
+
"ordering": ordering,
|
|
187
|
+
"lowToHigh": lowToHigh,
|
|
188
|
+
"query": query,
|
|
189
|
+
**kwargs
|
|
190
|
+
}
|
|
191
|
+
payload = {k: v for k, v in payload.items() if v is not None}
|
|
192
|
+
|
|
193
|
+
response = await self._client.http.post("feed", json=payload)
|
|
194
|
+
response.raise_for_status()
|
|
195
|
+
return await response.json()
|
mrkts/market/offers.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Offers object of MRKT client"""
|
|
2
|
+
|
|
3
|
+
class Offers:
|
|
4
|
+
def __init__(self, client):
|
|
5
|
+
self._client = client
|
|
6
|
+
|
|
7
|
+
async def create(self, price: int, giftSaleId: str):
|
|
8
|
+
payload = {
|
|
9
|
+
"price": price,
|
|
10
|
+
"giftSaleId": giftSaleId
|
|
11
|
+
}
|
|
12
|
+
response = await self._client.http.post("offers/create", json=payload)
|
|
13
|
+
response.raise_for_status()
|
|
14
|
+
return await response.json()
|
|
15
|
+
|
|
16
|
+
async def cancel(self, offerId: str):
|
|
17
|
+
response = await self._client.http.post(f"offers/cancel?offerId={offerId}")
|
|
18
|
+
response.raise_for_status()
|
|
19
|
+
return await response.json()
|
|
20
|
+
|
|
21
|
+
async def activities(self, *, count: int = 20, isActive: bool = True, filters: list = ["Offers", "ChannelOffers", "GiftsCollectionOffers"]):
|
|
22
|
+
response = await self._client.http.get("activities/with-totals", params={"count": count, "isActive": str(isActive).lower(), "filters": filters})
|
|
23
|
+
response.raise_for_status()
|
|
24
|
+
return await response.json()
|
|
25
|
+
|
|
26
|
+
async def myOffersByGift(self, id: str, count: int = 20):
|
|
27
|
+
response = await self._client.http.get(f"offers/by-gift/{id}?count={count}")
|
|
28
|
+
response.raise_for_status()
|
|
29
|
+
return await response.json()
|
mrkts/market/orders.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Orders object of MRKT client"""
|
|
2
|
+
from aiohttp import ClientResponseError
|
|
3
|
+
|
|
4
|
+
class Orders:
|
|
5
|
+
def __init__(self, client):
|
|
6
|
+
self._client = client
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def create(
|
|
10
|
+
self,
|
|
11
|
+
*,
|
|
12
|
+
collectionName: str = None,
|
|
13
|
+
modelName: str = None,
|
|
14
|
+
backdropName: str = None,
|
|
15
|
+
symbolName: str = None,
|
|
16
|
+
priceMinNanoTONs: int = 500000000,
|
|
17
|
+
priceMaxNanoTONs: int = 1000000000,
|
|
18
|
+
quantity: int = 1,
|
|
19
|
+
isTransferable: bool = False,
|
|
20
|
+
**kwargs
|
|
21
|
+
):
|
|
22
|
+
payload = {
|
|
23
|
+
"collectionName": collectionName,
|
|
24
|
+
"modelName": modelName,
|
|
25
|
+
"backdropName": backdropName,
|
|
26
|
+
"symbolName": symbolName,
|
|
27
|
+
"priceMinNanoTONs": priceMinNanoTONs,
|
|
28
|
+
"priceMaxNanoTONs": priceMaxNanoTONs,
|
|
29
|
+
"quantity": quantity,
|
|
30
|
+
"isTransferable": isTransferable,
|
|
31
|
+
**kwargs
|
|
32
|
+
}
|
|
33
|
+
response = await self._client.http.post("orders/create", json=payload)
|
|
34
|
+
response.raise_for_status()
|
|
35
|
+
return await response.json()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def cancel(self, orderId: str):
|
|
39
|
+
try:
|
|
40
|
+
response = await self._client.http.post(f"orders/cancel/{orderId}")
|
|
41
|
+
response.raise_for_status()
|
|
42
|
+
return True
|
|
43
|
+
except ClientResponseError:
|
|
44
|
+
return False
|
|
45
|
+
except Exception as e:
|
|
46
|
+
raise e
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def list(
|
|
50
|
+
self,
|
|
51
|
+
*,
|
|
52
|
+
collectionNames: list[str],
|
|
53
|
+
modelNames: list[str] = [],
|
|
54
|
+
backdropNames: list[str] = [],
|
|
55
|
+
symbolNames: list[str] = [],
|
|
56
|
+
availableForStaking: bool = None,
|
|
57
|
+
minPrice: float = None,
|
|
58
|
+
maxPrice: float = None,
|
|
59
|
+
ordering: str = "Price",
|
|
60
|
+
lowToHigh: bool = False,
|
|
61
|
+
query: str = None,
|
|
62
|
+
cursor: str = "",
|
|
63
|
+
count: int = 20,
|
|
64
|
+
**kwargs
|
|
65
|
+
) -> list[dict]:
|
|
66
|
+
payload = {
|
|
67
|
+
"collectionNames": collectionNames,
|
|
68
|
+
"modelNames": modelNames,
|
|
69
|
+
"backdropNames": backdropNames,
|
|
70
|
+
"symbolNames": symbolNames,
|
|
71
|
+
"availableForStaking": availableForStaking,
|
|
72
|
+
"minPrice": minPrice,
|
|
73
|
+
"maxPrice": maxPrice,
|
|
74
|
+
"ordering": ordering,
|
|
75
|
+
"lowToHigh": lowToHigh,
|
|
76
|
+
"query": query,
|
|
77
|
+
"cursor": cursor,
|
|
78
|
+
"count": count,
|
|
79
|
+
**kwargs
|
|
80
|
+
}
|
|
81
|
+
response = await self._client.http.post("orders", json=payload)
|
|
82
|
+
response.raise_for_status()
|
|
83
|
+
return await response.json()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
async def fill(self, *, orderId: str, giftIds: str):
|
|
87
|
+
response = await self._client.http.post("orders/fill", json={"orderId": orderId, "giftIds": giftIds})
|
|
88
|
+
response.raise_for_status()
|
|
89
|
+
return await response.json()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
async def getMyOrders(
|
|
93
|
+
self,
|
|
94
|
+
*,
|
|
95
|
+
collectionNames: list = [],
|
|
96
|
+
modelNames: list = [],
|
|
97
|
+
backdropNames: list = [],
|
|
98
|
+
symbolNames: list = [],
|
|
99
|
+
availableForStaking: bool = None,
|
|
100
|
+
minPrice: float = None,
|
|
101
|
+
maxPrice: float = None,
|
|
102
|
+
ordering: str = "PublicationTime",
|
|
103
|
+
lowToHigh: bool = False,
|
|
104
|
+
query: str = None,
|
|
105
|
+
cursor: str = "",
|
|
106
|
+
count: int = 20,
|
|
107
|
+
**kwargs
|
|
108
|
+
):
|
|
109
|
+
payload = {
|
|
110
|
+
"collectionNames": collectionNames,
|
|
111
|
+
"modelNames": modelNames,
|
|
112
|
+
"backdropNames": backdropNames,
|
|
113
|
+
"symbolNames": symbolNames,
|
|
114
|
+
"availableForStaking": availableForStaking,
|
|
115
|
+
"minPrice": minPrice,
|
|
116
|
+
"maxPrice": maxPrice,
|
|
117
|
+
"ordering": ordering,
|
|
118
|
+
"lowToHigh": lowToHigh,
|
|
119
|
+
"query": query,
|
|
120
|
+
"cursor": cursor,
|
|
121
|
+
"count": count,
|
|
122
|
+
**kwargs
|
|
123
|
+
}
|
|
124
|
+
response = await self._client.http.post("orders/get-my-orders", json=payload)
|
|
125
|
+
response.raise_for_status()
|
|
126
|
+
return await response.json()
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
async def allCollectionTop(self):
|
|
130
|
+
response = await self._client.http.get("orders/all-collection-top")
|
|
131
|
+
response.raise_for_status()
|
|
132
|
+
return await response.json()
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
async def giftsHistory(self, *, st_from: str = "", limit: int = 20, **kwargs):
|
|
136
|
+
payload = {
|
|
137
|
+
"from": st_from,
|
|
138
|
+
"limit": limit,
|
|
139
|
+
**kwargs
|
|
140
|
+
}
|
|
141
|
+
response = await self._client.http.post("orders/gifts-history", json=payload)
|
|
142
|
+
response.raise_for_status()
|
|
143
|
+
return await response.json()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
async def top(self, *, collectionName: str, modelName: str = None, backdropName: str = None, symbolName: str = None):
|
|
147
|
+
payload = {
|
|
148
|
+
"collectionName": collectionName,
|
|
149
|
+
"modelName": modelName,
|
|
150
|
+
"backdropName": backdropName,
|
|
151
|
+
"symbolName": symbolName
|
|
152
|
+
}
|
|
153
|
+
response = await self._client.http.post("orders/top", json=payload)
|
|
154
|
+
response.raise_for_status()
|
|
155
|
+
return await response.json()
|
mrkts/pool.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import *
|
|
3
|
+
|
|
4
|
+
from .client import MrktClient
|
|
5
|
+
from .utils import get_tokens
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MrktPool:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
*,
|
|
12
|
+
tokens: list[str] | None = None,
|
|
13
|
+
sessions: list[str] | None = None,
|
|
14
|
+
workdir: str = ".",
|
|
15
|
+
tasks: list[tuple[str, dict]] | None = None,
|
|
16
|
+
proxy: str | None = None,
|
|
17
|
+
unlimited: bool = False
|
|
18
|
+
):
|
|
19
|
+
self.clients: list["MrktClient"] = []
|
|
20
|
+
self._tasks = tasks
|
|
21
|
+
self.proxy = proxy
|
|
22
|
+
self.workdir = workdir
|
|
23
|
+
self._kwargs = {
|
|
24
|
+
"proxy": self.proxy,
|
|
25
|
+
"workdir": self.workdir
|
|
26
|
+
}
|
|
27
|
+
self._unlimited = unlimited
|
|
28
|
+
|
|
29
|
+
if tokens and sessions:
|
|
30
|
+
raise ValueError("Client can not run with tokens and sessions both")
|
|
31
|
+
|
|
32
|
+
if tokens:
|
|
33
|
+
self.clients = [MrktClient(token=token, **self._kwargs) for token in tokens]
|
|
34
|
+
elif sessions:
|
|
35
|
+
self._load_sessions(sessions)
|
|
36
|
+
else:
|
|
37
|
+
raise ValueError("Client can not run without tokens or sessions")
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
async def from_sessions(
|
|
41
|
+
cls,
|
|
42
|
+
sessions: list[str],
|
|
43
|
+
*,
|
|
44
|
+
workdir: str = ".",
|
|
45
|
+
proxy: str | None = None,
|
|
46
|
+
concurrency: int = 5,
|
|
47
|
+
**kwargs: Any,
|
|
48
|
+
) -> "MrktPool":
|
|
49
|
+
tokens = await get_tokens(
|
|
50
|
+
sessions,
|
|
51
|
+
workdir=workdir,
|
|
52
|
+
proxy=proxy,
|
|
53
|
+
concurrency=concurrency,
|
|
54
|
+
)
|
|
55
|
+
return cls(
|
|
56
|
+
tokens=tokens,
|
|
57
|
+
workdir=workdir,
|
|
58
|
+
proxy=proxy,
|
|
59
|
+
**kwargs,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def _load_sessions(self, sessions: list[str]):
|
|
63
|
+
async def load():
|
|
64
|
+
tokens = await get_tokens(sessions, workdir=self.workdir, proxy=self.proxy)
|
|
65
|
+
self.clients = [MrktClient(token=t, **self._kwargs) for t in tokens]
|
|
66
|
+
|
|
67
|
+
self._token_future = load()
|
|
68
|
+
|
|
69
|
+
async def start(self):
|
|
70
|
+
if not self.clients and hasattr(self, "_token_future"):
|
|
71
|
+
await self._token_future
|
|
72
|
+
self.clients = [MrktClient(token=t, **self._kwargs) for t in self.clients]
|
|
73
|
+
|
|
74
|
+
async def map(
|
|
75
|
+
self,
|
|
76
|
+
coro_func: Callable[[MrktClient], Awaitable[Any]],
|
|
77
|
+
*,
|
|
78
|
+
concurrency: int = 5,
|
|
79
|
+
) -> list[Any | Exception]:
|
|
80
|
+
if concurrency < 1 and not self._unlimited:
|
|
81
|
+
raise ValueError("concurrency must be greater than zero")
|
|
82
|
+
|
|
83
|
+
sem = asyncio.Semaphore(concurrency)
|
|
84
|
+
|
|
85
|
+
async def worker(client):
|
|
86
|
+
async with sem:
|
|
87
|
+
return await coro_func(client)
|
|
88
|
+
|
|
89
|
+
return await asyncio.gather(*(worker(c) for c in self.clients), return_exceptions=True)
|
|
90
|
+
|
|
91
|
+
async def close(self):
|
|
92
|
+
if self.clients:
|
|
93
|
+
await asyncio.gather(*[c.close() for c in self.clients], return_exceptions=True)
|
|
94
|
+
self.clients.clear()
|
|
95
|
+
|
|
96
|
+
async def __aenter__(self) -> "MrktPool":
|
|
97
|
+
await self.start()
|
|
98
|
+
return self
|
|
99
|
+
|
|
100
|
+
async def __aexit__(self, *args: Any) -> None:
|
|
101
|
+
await self.close()
|