hive-nectar 0.0.11__py3-none-any.whl → 0.1.1__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.
Potentially problematic release.
This version of hive-nectar might be problematic. Click here for more details.
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.1.dist-info}/METADATA +12 -11
- hive_nectar-0.1.1.dist-info/RECORD +88 -0
- nectar/__init__.py +1 -4
- nectar/account.py +791 -685
- nectar/amount.py +82 -21
- nectar/asset.py +1 -2
- nectar/block.py +49 -23
- nectar/blockchain.py +111 -143
- nectar/blockchaininstance.py +396 -247
- nectar/blockchainobject.py +33 -5
- nectar/cli.py +1058 -1349
- nectar/comment.py +313 -181
- nectar/community.py +39 -43
- nectar/constants.py +1 -14
- nectar/discussions.py +793 -139
- nectar/hive.py +137 -77
- nectar/hivesigner.py +106 -68
- nectar/imageuploader.py +33 -23
- nectar/instance.py +31 -79
- nectar/market.py +128 -264
- nectar/memo.py +40 -13
- nectar/message.py +23 -10
- nectar/nodelist.py +115 -81
- nectar/price.py +80 -61
- nectar/profile.py +6 -3
- nectar/rc.py +45 -25
- nectar/snapshot.py +285 -163
- nectar/storage.py +16 -5
- nectar/transactionbuilder.py +132 -41
- nectar/utils.py +37 -17
- nectar/version.py +1 -1
- nectar/vote.py +171 -30
- nectar/wallet.py +26 -19
- nectar/witness.py +153 -54
- nectarapi/graphenerpc.py +147 -133
- nectarapi/noderpc.py +12 -6
- nectarapi/rpcutils.py +12 -6
- nectarapi/version.py +1 -1
- nectarbase/ledgertransactions.py +24 -1
- nectarbase/objects.py +17 -6
- nectarbase/operations.py +160 -90
- nectarbase/signedtransactions.py +38 -2
- nectarbase/version.py +1 -1
- nectargraphenebase/account.py +295 -17
- nectargraphenebase/chains.py +0 -135
- nectargraphenebase/ecdsasig.py +152 -176
- nectargraphenebase/types.py +18 -4
- nectargraphenebase/unsignedtransactions.py +1 -1
- nectargraphenebase/version.py +1 -1
- hive_nectar-0.0.11.dist-info/RECORD +0 -91
- nectar/blurt.py +0 -562
- nectar/conveyor.py +0 -308
- nectar/steem.py +0 -581
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.1.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.1.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.1.dist-info}/licenses/LICENSE.txt +0 -0
nectar/market.py
CHANGED
|
@@ -29,9 +29,9 @@ log = logging.getLogger(__name__)
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class Market(dict):
|
|
32
|
-
"""This class allows
|
|
32
|
+
"""This class allows access to the internal market for trading, etc. (Hive-only).
|
|
33
33
|
|
|
34
|
-
:param
|
|
34
|
+
:param Hive blockchain_instance: Hive instance
|
|
35
35
|
:param Asset base: Base asset
|
|
36
36
|
:param Asset quote: Quote asset
|
|
37
37
|
:returns: Blockchain Market
|
|
@@ -50,7 +50,7 @@ class Market(dict):
|
|
|
50
50
|
* ``base-quote`` separated with ``-``
|
|
51
51
|
|
|
52
52
|
.. note:: Throughout this library, the ``quote`` symbol will be
|
|
53
|
-
presented first (e.g. ``
|
|
53
|
+
presented first (e.g. ``HIVE:HBD`` with ``HIVE`` being the
|
|
54
54
|
quote), while the ``base`` only refers to a secondary asset
|
|
55
55
|
for a trade. This means, if you call
|
|
56
56
|
:func:`nectar.market.Market.sell` or
|
|
@@ -61,17 +61,18 @@ class Market(dict):
|
|
|
61
61
|
|
|
62
62
|
def __init__(self, base=None, quote=None, blockchain_instance=None, **kwargs):
|
|
63
63
|
"""
|
|
64
|
-
|
|
64
|
+
Create a Market mapping with "base" and "quote" Asset objects.
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
Supports three initialization modes:
|
|
67
|
+
- Single-string market identifier (e.g., "HBD:HIVE" or "HIVE:HBD"): parsed into quote and base symbols and converted to Asset objects.
|
|
68
|
+
- Explicit base and quote (either Asset instances or values accepted by Asset): each converted to an Asset.
|
|
69
|
+
- No arguments: uses the blockchain instance's default token symbols (token_symbol as base, backed_token_symbol as quote).
|
|
70
|
+
|
|
71
|
+
The resolved Asset objects are stored in the instance as entries "base" and "quote". The blockchain instance used is the provided one or the shared global instance.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
ValueError: if the combination of arguments does not match any supported initialization mode.
|
|
69
75
|
"""
|
|
70
|
-
if blockchain_instance is None:
|
|
71
|
-
if kwargs.get("steem_instance"):
|
|
72
|
-
blockchain_instance = kwargs["steem_instance"]
|
|
73
|
-
elif kwargs.get("hive_instance"):
|
|
74
|
-
blockchain_instance = kwargs["hive_instance"]
|
|
75
76
|
self.blockchain = blockchain_instance or shared_blockchain_instance()
|
|
76
77
|
|
|
77
78
|
if quote is None and isinstance(base, str):
|
|
@@ -97,9 +98,14 @@ class Market(dict):
|
|
|
97
98
|
raise ValueError("Unknown Market config")
|
|
98
99
|
|
|
99
100
|
def get_string(self, separator=":"):
|
|
100
|
-
"""
|
|
101
|
+
"""
|
|
102
|
+
Return the market identifier as "QUOTE{separator}BASE" (e.g. "HIVE:HBD").
|
|
103
|
+
|
|
104
|
+
Parameters:
|
|
105
|
+
separator (str): Token placed between quote and base symbols. Defaults to ":".
|
|
101
106
|
|
|
102
|
-
:
|
|
107
|
+
Returns:
|
|
108
|
+
str: Formatted market string in the form "<quote><separator><base>".
|
|
103
109
|
"""
|
|
104
110
|
return "%s%s%s" % (self["quote"]["symbol"], separator, self["base"]["symbol"])
|
|
105
111
|
|
|
@@ -116,35 +122,21 @@ class Market(dict):
|
|
|
116
122
|
)
|
|
117
123
|
|
|
118
124
|
def ticker(self, raw_data=False):
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
Output Parameters:
|
|
122
|
-
|
|
123
|
-
* ``latest``: Price of the order last filled
|
|
124
|
-
* ``lowest_ask``: Price of the lowest ask
|
|
125
|
-
* ``highest_bid``: Price of the highest bid
|
|
126
|
-
* ``sbd_volume``: Volume of SBD
|
|
127
|
-
* ``steem_volume``: Volume of STEEM
|
|
128
|
-
* ``hbd_volume``: Volume of HBD
|
|
129
|
-
* ``hive_volume``: Volume of HIVE
|
|
130
|
-
* ``percent_change``: 24h change percentage (in %)
|
|
125
|
+
"""
|
|
126
|
+
Return the market ticker for this Market (HIVE:HBD).
|
|
131
127
|
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
By default returns a dict with Price objects for 'highest_bid', 'latest', and 'lowest_ask',
|
|
129
|
+
a float 'percent_change' (24h), and Amount objects for 'hbd_volume' and 'hive_volume' when present.
|
|
130
|
+
If raw_data is True, returns the unprocessed RPC result.
|
|
134
131
|
|
|
135
|
-
|
|
132
|
+
Parameters:
|
|
133
|
+
raw_data (bool): If True, return the raw market_history RPC response instead of mapped objects.
|
|
136
134
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
'highest_bid': 0.30100226633322913,
|
|
141
|
-
'latest': 0.0,
|
|
142
|
-
'lowest_ask': 0.3249636958897082,
|
|
143
|
-
'percent_change': 0.0,
|
|
144
|
-
'sbd_volume': 108329611.0,
|
|
145
|
-
'steem_volume': 355094043.0
|
|
146
|
-
}
|
|
135
|
+
Returns:
|
|
136
|
+
dict or Any: Mapped ticker dictionary (prices as Price, volumes as Amount) or raw RPC data.
|
|
147
137
|
|
|
138
|
+
Notes:
|
|
139
|
+
Prices are expressed as HBD per HIVE.
|
|
148
140
|
"""
|
|
149
141
|
data = {}
|
|
150
142
|
# Core Exchange rate
|
|
@@ -173,46 +165,30 @@ class Market(dict):
|
|
|
173
165
|
blockchain_instance=self.blockchain,
|
|
174
166
|
)
|
|
175
167
|
data["percent_change"] = float(ticker["percent_change"])
|
|
176
|
-
if "
|
|
177
|
-
data["sbd_volume"] = Amount(ticker["sbd_volume"], blockchain_instance=self.blockchain)
|
|
178
|
-
elif "hbd_volume" in ticker:
|
|
168
|
+
if "hbd_volume" in ticker:
|
|
179
169
|
data["hbd_volume"] = Amount(ticker["hbd_volume"], blockchain_instance=self.blockchain)
|
|
180
|
-
if "
|
|
181
|
-
data["steem_volume"] = Amount(
|
|
182
|
-
ticker["steem_volume"], blockchain_instance=self.blockchain
|
|
183
|
-
)
|
|
184
|
-
elif "hive_volume" in ticker:
|
|
170
|
+
if "hive_volume" in ticker:
|
|
185
171
|
data["hive_volume"] = Amount(ticker["hive_volume"], blockchain_instance=self.blockchain)
|
|
186
172
|
|
|
187
173
|
return data
|
|
188
174
|
|
|
189
175
|
def volume24h(self, raw_data=False):
|
|
190
|
-
"""
|
|
191
|
-
|
|
192
|
-
Sample output:
|
|
193
|
-
|
|
194
|
-
.. code-block:: js
|
|
176
|
+
"""
|
|
177
|
+
Return 24-hour trading volume for this market.
|
|
195
178
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
179
|
+
If raw_data is True, returns the raw result from the blockchain `market_history` RPC.
|
|
180
|
+
Otherwise, if the RPC result contains 'hbd_volume' and 'hive_volume', returns a dict mapping
|
|
181
|
+
asset symbols to Amount objects, e.g. { "HBD": Amount(...), "HIVE": Amount(...) }.
|
|
182
|
+
If the expected volume keys are not present, returns None.
|
|
200
183
|
|
|
184
|
+
Parameters:
|
|
185
|
+
raw_data (bool): If True, return the unprocessed RPC response.
|
|
201
186
|
"""
|
|
202
187
|
self.blockchain.rpc.set_next_node_on_empty_reply(True)
|
|
203
188
|
volume = self.blockchain.rpc.get_volume(api="market_history")
|
|
204
189
|
if raw_data:
|
|
205
190
|
return volume
|
|
206
|
-
if "
|
|
207
|
-
return {
|
|
208
|
-
self["base"]["symbol"]: Amount(
|
|
209
|
-
volume["sbd_volume"], blockchain_instance=self.blockchain
|
|
210
|
-
),
|
|
211
|
-
self["quote"]["symbol"]: Amount(
|
|
212
|
-
volume["steem_volume"], blockchain_instance=self.blockchain
|
|
213
|
-
),
|
|
214
|
-
}
|
|
215
|
-
elif "hbd_volume" in volume and "hive_volume" in volume:
|
|
191
|
+
if "hbd_volume" in volume and "hive_volume" in volume:
|
|
216
192
|
return {
|
|
217
193
|
self["base"]["symbol"]: Amount(
|
|
218
194
|
volume["hbd_volume"], blockchain_instance=self.blockchain
|
|
@@ -223,7 +199,7 @@ class Market(dict):
|
|
|
223
199
|
}
|
|
224
200
|
|
|
225
201
|
def orderbook(self, limit=25, raw_data=False):
|
|
226
|
-
"""Returns the order book for
|
|
202
|
+
"""Returns the order book for the HBD/HIVE market.
|
|
227
203
|
|
|
228
204
|
:param int limit: Limit the amount of orders (default: 25)
|
|
229
205
|
|
|
@@ -233,12 +209,12 @@ class Market(dict):
|
|
|
233
209
|
|
|
234
210
|
{
|
|
235
211
|
'asks': [
|
|
236
|
-
380.510
|
|
237
|
-
53.785
|
|
212
|
+
380.510 HIVE 460.291 HBD @ 1.209669 HBD/HIVE,
|
|
213
|
+
53.785 HIVE 65.063 HBD @ 1.209687 HBD/HIVE
|
|
238
214
|
],
|
|
239
215
|
'bids': [
|
|
240
|
-
0.292
|
|
241
|
-
8.498
|
|
216
|
+
0.292 HIVE 0.353 HBD @ 1.208904 HBD/HIVE,
|
|
217
|
+
8.498 HIVE 10.262 HBD @ 1.207578 HBD/HIVE
|
|
242
218
|
],
|
|
243
219
|
'asks_date': [
|
|
244
220
|
datetime.datetime(2018, 4, 30, 21, 7, 24, tzinfo=<UTC>),
|
|
@@ -257,19 +233,19 @@ class Market(dict):
|
|
|
257
233
|
{
|
|
258
234
|
'asks': [
|
|
259
235
|
{
|
|
260
|
-
'order_price': {'base': '8.000
|
|
236
|
+
'order_price': {'base': '8.000 HIVE', 'quote': '9.618 HBD'},
|
|
261
237
|
'real_price': '1.20225000000000004',
|
|
262
|
-
'
|
|
263
|
-
'
|
|
238
|
+
'hive': 4565,
|
|
239
|
+
'hbd': 5488,
|
|
264
240
|
'created': '2018-04-30T21:12:45'
|
|
265
241
|
}
|
|
266
242
|
],
|
|
267
243
|
'bids': [
|
|
268
244
|
{
|
|
269
|
-
'order_price': {'base': '10.000
|
|
245
|
+
'order_price': {'base': '10.000 HBD', 'quote': '8.333 HIVE'},
|
|
270
246
|
'real_price': '1.20004800192007677',
|
|
271
|
-
'
|
|
272
|
-
'
|
|
247
|
+
'hive': 8333,
|
|
248
|
+
'hbd': 10000,
|
|
273
249
|
'created': '2018-04-30T20:29:33'
|
|
274
250
|
}
|
|
275
251
|
]
|
|
@@ -314,42 +290,17 @@ class Market(dict):
|
|
|
314
290
|
return data
|
|
315
291
|
|
|
316
292
|
def recent_trades(self, limit=25, raw_data=False):
|
|
317
|
-
"""
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
:param int limit: Limit the amount of orders (default: 25)
|
|
321
|
-
:param bool raw_data: when False, FilledOrder objects will be
|
|
322
|
-
returned
|
|
323
|
-
|
|
324
|
-
Sample output (raw_data=False):
|
|
325
|
-
|
|
326
|
-
.. code-block:: none
|
|
327
|
-
|
|
328
|
-
[
|
|
329
|
-
(2018-04-30 21:00:54+00:00) 0.267 STEEM 0.323 SBD @ 1.209738 SBD/STEEM,
|
|
330
|
-
(2018-04-30 20:59:30+00:00) 0.131 STEEM 0.159 SBD @ 1.213740 SBD/STEEM,
|
|
331
|
-
(2018-04-30 20:55:45+00:00) 0.093 STEEM 0.113 SBD @ 1.215054 SBD/STEEM,
|
|
332
|
-
(2018-04-30 20:55:30+00:00) 26.501 STEEM 32.058 SBD @ 1.209690 SBD/STEEM,
|
|
333
|
-
(2018-04-30 20:55:18+00:00) 2.108 STEEM 2.550 SBD @ 1.209677 SBD/STEEM,
|
|
334
|
-
]
|
|
335
|
-
|
|
336
|
-
Sample output (raw_data=True):
|
|
337
|
-
|
|
338
|
-
.. code-block:: js
|
|
293
|
+
"""
|
|
294
|
+
Return recent trades for this market.
|
|
339
295
|
|
|
340
|
-
|
|
341
|
-
{'date': '2018-04-30T21:02:45', 'current_pays': '0.235 SBD', 'open_pays': '0.194 STEEM'},
|
|
342
|
-
{'date': '2018-04-30T21:02:03', 'current_pays': '24.494 SBD', 'open_pays': '20.248 STEEM'},
|
|
343
|
-
{'date': '2018-04-30T20:48:30', 'current_pays': '175.464 STEEM', 'open_pays': '211.955 SBD'},
|
|
344
|
-
{'date': '2018-04-30T20:48:30', 'current_pays': '0.999 STEEM', 'open_pays': '1.207 SBD'},
|
|
345
|
-
{'date': '2018-04-30T20:47:54', 'current_pays': '0.273 SBD', 'open_pays': '0.225 STEEM'},
|
|
346
|
-
]
|
|
296
|
+
By default returns up to `limit` most recent trades wrapped as FilledOrder objects; if `raw_data` is True the raw trade dictionaries from the market_history API are returned instead.
|
|
347
297
|
|
|
348
|
-
|
|
349
|
-
:
|
|
350
|
-
|
|
351
|
-
obtain the actual amounts for sale
|
|
298
|
+
Parameters:
|
|
299
|
+
limit (int): Maximum number of trades to retrieve (default: 25).
|
|
300
|
+
raw_data (bool): If True, return raw API trade entries; if False, return a list of FilledOrder instances constructed with this market's blockchain instance.
|
|
352
301
|
|
|
302
|
+
Returns:
|
|
303
|
+
list: A list of FilledOrder objects when `raw_data` is False, or a list of raw trade dicts as returned by the market_history API when `raw_data` is True.
|
|
353
304
|
"""
|
|
354
305
|
self.blockchain.rpc.set_next_node_on_empty_reply(limit > 0)
|
|
355
306
|
if self.blockchain.rpc.get_use_appbase():
|
|
@@ -450,36 +401,22 @@ class Market(dict):
|
|
|
450
401
|
return ret
|
|
451
402
|
|
|
452
403
|
def market_history(self, bucket_seconds=300, start_age=3600, end_age=0, raw_data=False):
|
|
453
|
-
"""
|
|
404
|
+
"""
|
|
405
|
+
Return market history buckets for a time window.
|
|
454
406
|
|
|
455
|
-
|
|
456
|
-
`returnMarketHistoryBuckets()`)
|
|
457
|
-
:param int start_age: Age (in seconds) of the start of the
|
|
458
|
-
window (default: 1h/3600)
|
|
459
|
-
:param int end_age: Age (in seconds) of the end of the window
|
|
460
|
-
(default: now/0)
|
|
461
|
-
:param bool raw_data: (optional) returns raw data if set True
|
|
407
|
+
This fetches aggregated market history buckets (filled orders) for the market over a window defined by start_age and end_age and grouped by bucket_seconds. bucket_seconds may be provided either as a numeric bucket size (seconds) or as an index into available buckets returned by market_history_buckets(). When raw_data is False any bucket "open" timestamp strings are normalized to a consistent formatted datetime string.
|
|
462
408
|
|
|
463
|
-
|
|
409
|
+
Parameters:
|
|
410
|
+
bucket_seconds (int): Bucket size in seconds or an index into market_history_buckets().
|
|
411
|
+
start_age (int): Age in seconds from now to the start of the window (default 3600 seconds).
|
|
412
|
+
end_age (int): Age in seconds from now to the end of the window (default 0 = now).
|
|
413
|
+
raw_data (bool): If True, return the raw RPC response without normalizing timestamps.
|
|
464
414
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
{
|
|
468
|
-
'close_sbd': 2493387,
|
|
469
|
-
'close_steem': 7743431,
|
|
470
|
-
'high_sbd': 1943872,
|
|
471
|
-
'high_steem': 5999610,
|
|
472
|
-
'id': '7.1.5252',
|
|
473
|
-
'low_sbd': 534928,
|
|
474
|
-
'low_steem': 1661266,
|
|
475
|
-
'open': '2016-07-08T11:25:00',
|
|
476
|
-
'open_sbd': 534928,
|
|
477
|
-
'open_steem': 1661266,
|
|
478
|
-
'sbd_volume': 9714435,
|
|
479
|
-
'seconds': 300,
|
|
480
|
-
'steem_volume': 30088443
|
|
481
|
-
}
|
|
415
|
+
Returns:
|
|
416
|
+
list: A list of bucket dicts (or the raw RPC list when raw_data is True). Each bucket contains fields such as 'open', 'seconds', 'open_hbd', 'close_hbd', 'high_hbd', 'low_hbd', 'hbd_volume', 'open_hive', 'close_hive', 'high_hive', 'low_hive', 'hive_volume', and 'id' when available.
|
|
482
417
|
|
|
418
|
+
Raises:
|
|
419
|
+
ValueError: If bucket_seconds is not a valid bucket size or valid index into available buckets.
|
|
483
420
|
"""
|
|
484
421
|
buckets = self.market_history_buckets()
|
|
485
422
|
if bucket_seconds < 5 and bucket_seconds >= 0:
|
|
@@ -562,39 +499,29 @@ class Market(dict):
|
|
|
562
499
|
orderid=None,
|
|
563
500
|
returnOrderId=False,
|
|
564
501
|
):
|
|
565
|
-
"""
|
|
566
|
-
|
|
567
|
-
:param float price: price denoted in ``base``/``quote``
|
|
568
|
-
:param number amount: Amount of ``quote`` to buy
|
|
569
|
-
:param number expiration: (optional) expiration time of the order in seconds (defaults to 7 days)
|
|
570
|
-
:param bool killfill: flag that indicates if the order shall be killed if it is not filled (defaults to False)
|
|
571
|
-
:param string account: Account name that executes that order
|
|
572
|
-
:param string returnOrderId: If set to "head" or "irreversible" the call will wait for the tx to appear in
|
|
573
|
-
the head/irreversible block and add the key "orderid" to the tx output
|
|
574
|
-
|
|
575
|
-
Prices/Rates are denoted in 'base', i.e. the SBD_STEEM market
|
|
576
|
-
is priced in STEEM per SBD.
|
|
577
|
-
|
|
578
|
-
**Example:** in the SBD_STEEM market, a price of 300 means
|
|
579
|
-
a SBD is worth 300 STEEM
|
|
502
|
+
"""
|
|
503
|
+
Place a buy order (limit order) on this market.
|
|
580
504
|
|
|
581
|
-
|
|
505
|
+
Prices are expressed in the market's base/quote orientation (HIVE per HBD in HBD_HIVE). This method submits a limit-order-create operation that effectively places a sell order of the base asset to acquire the requested amount of the quote asset.
|
|
582
506
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
507
|
+
Parameters:
|
|
508
|
+
price (float or Price): Price expressed in base per quote (e.g., HIVE per HBD).
|
|
509
|
+
amount (number or str or Amount): Amount of the quote asset to buy.
|
|
510
|
+
expiration (int, optional): Order lifetime in seconds (default: configured order-expiration, typically 7 days).
|
|
511
|
+
killfill (bool, optional): If True, set fill_or_kill on the order (defaults to False).
|
|
512
|
+
account (str, optional): Account name that will own and broadcast the order. If omitted, default_account from config is used; a ValueError is raised if none is available.
|
|
513
|
+
orderid (int, optional): Explicit client-side order id. If omitted one is randomly generated.
|
|
514
|
+
returnOrderId (bool or str, optional): If truthy (or set to "head"/"irreversible"), the call will wait for the transaction and attach the assigned order id to the returned transaction under the "orderid" key.
|
|
586
515
|
|
|
587
|
-
|
|
516
|
+
Returns:
|
|
517
|
+
dict: The finalized broadcast transaction object returned by the blockchain client. If returnOrderId was used, the dict includes an "orderid" field.
|
|
588
518
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
buy asset than you placed the order
|
|
593
|
-
for. Example:
|
|
519
|
+
Raises:
|
|
520
|
+
ValueError: If no account can be resolved.
|
|
521
|
+
AssertionError: If an Amount is provided whose asset symbol does not match the market quote.
|
|
594
522
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
* If an order on the market exists that sells SBD for cheaper, you will end up with more than 10 SBD
|
|
523
|
+
Notes:
|
|
524
|
+
- Because buy orders are implemented as limit-sell orders of the base asset, the trade can result in receiving more of the quote asset than requested if matching orders exist at better prices.
|
|
598
525
|
"""
|
|
599
526
|
if not expiration:
|
|
600
527
|
expiration = self.blockchain.config["order-expiration"]
|
|
@@ -660,27 +587,26 @@ class Market(dict):
|
|
|
660
587
|
orderid=None,
|
|
661
588
|
returnOrderId=False,
|
|
662
589
|
):
|
|
663
|
-
"""
|
|
664
|
-
|
|
665
|
-
:param float price: price denoted in ``base``/``quote``
|
|
666
|
-
:param number amount: Amount of ``quote`` to sell
|
|
667
|
-
:param number expiration: (optional) expiration time of the order in seconds (defaults to 7 days)
|
|
668
|
-
:param bool killfill: flag that indicates if the order shall be killed if it is not filled (defaults to False)
|
|
669
|
-
:param string account: Account name that executes that order
|
|
670
|
-
:param string returnOrderId: If set to "head" or "irreversible" the call will wait for the tx to appear in
|
|
671
|
-
the head/irreversible block and add the key "orderid" to the tx output
|
|
590
|
+
"""
|
|
591
|
+
Place a limit sell order on this market, selling the market's quote asset for its base asset.
|
|
672
592
|
|
|
673
|
-
|
|
674
|
-
is priced in STEEM per SBD.
|
|
593
|
+
This creates a Limit_order_create operation where `amount_to_sell` is the provided `amount` in the market's quote asset and `min_to_receive` is `amount * price` in the market's base asset.
|
|
675
594
|
|
|
676
|
-
|
|
677
|
-
|
|
595
|
+
Parameters:
|
|
596
|
+
price (float or Price): Price expressed as base per quote (e.g., in HBD_HIVE market, a price of 3 means 1 HBD = 3 HIVE).
|
|
597
|
+
amount (number or str or Amount): Quantity of the quote asset to sell; may be an Amount instance, a string (e.g., "10.000 HBD"), or a numeric value.
|
|
598
|
+
expiration (int, optional): Order lifetime in seconds; defaults to the node/configured order-expiration (typically 7 days).
|
|
599
|
+
killfill (bool, optional): If True, treat the order as fill-or-kill (cancel if not fully filled). Defaults to False.
|
|
600
|
+
account (str, optional): Account name placing the order. If omitted, the configured default_account is used. Raises ValueError if no account is available.
|
|
601
|
+
orderid (int, optional): Client-provided order identifier; a random 32-bit id is used if not supplied.
|
|
602
|
+
returnOrderId (bool or str, optional): If truthy (or set to "head"/"irreversible"), the call will wait according to the blocking mode and the returned transaction will include an "orderid" field.
|
|
678
603
|
|
|
679
|
-
|
|
604
|
+
Returns:
|
|
605
|
+
dict: The finalized transaction object returned by the blockchain finalizeOp call. If `returnOrderId` is used, the dict will include an "orderid" key.
|
|
680
606
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
607
|
+
Raises:
|
|
608
|
+
ValueError: If no account is provided or available from configuration.
|
|
609
|
+
AssertionError: If an Amount is provided whose asset symbol does not match the market's quote asset.
|
|
684
610
|
"""
|
|
685
611
|
if not expiration:
|
|
686
612
|
expiration = self.blockchain.config["order-expiration"]
|
|
@@ -769,8 +695,20 @@ class Market(dict):
|
|
|
769
695
|
|
|
770
696
|
@staticmethod
|
|
771
697
|
def btc_usd_ticker(verbose=False):
|
|
772
|
-
"""
|
|
773
|
-
weighted
|
|
698
|
+
"""
|
|
699
|
+
Return the market-weighted BTC/USD price aggregated from multiple external sources.
|
|
700
|
+
|
|
701
|
+
Queries a set of public endpoints (currently CoinGecko; legacy support for Bitfinex, GDAX, Kraken, OKCoin, Bitstamp is present)
|
|
702
|
+
and computes a volume-weighted average price (VWAP) across successful responses.
|
|
703
|
+
|
|
704
|
+
Parameters:
|
|
705
|
+
verbose (bool): If True, prints the raw price/volume map collected from each source.
|
|
706
|
+
|
|
707
|
+
Returns:
|
|
708
|
+
float: The VWAP of BTC in USD computed from available sources.
|
|
709
|
+
|
|
710
|
+
Raises:
|
|
711
|
+
RuntimeError: If no valid price data could be obtained from any source after several attempts.
|
|
774
712
|
"""
|
|
775
713
|
prices = {}
|
|
776
714
|
responses = []
|
|
@@ -845,91 +783,17 @@ class Market(dict):
|
|
|
845
783
|
)
|
|
846
784
|
|
|
847
785
|
@staticmethod
|
|
848
|
-
def
|
|
849
|
-
"""Returns the STEEM/BTC price from bittrex, binance, huobi and upbit. The mean price is
|
|
850
|
-
weighted by the exchange volume.
|
|
786
|
+
def hive_btc_ticker():
|
|
851
787
|
"""
|
|
852
|
-
|
|
853
|
-
responses = []
|
|
854
|
-
urls = [
|
|
855
|
-
# "https://poloniex.com/public?command=returnTicker",
|
|
856
|
-
# "https://bittrex.com/api/v1.1/public/getmarketsummary?market=BTC-STEEM",
|
|
857
|
-
# "https://api.binance.com/api/v1/ticker/24hr",
|
|
858
|
-
# "https://api.huobi.pro/market/history/kline?period=1day&size=1&symbol=steembtc",
|
|
859
|
-
# "https://crix-api.upbit.com/v1/crix/trades/ticks?code=CRIX.UPBIT.BTC-STEEM&count=1",
|
|
860
|
-
"https://api.coingecko.com/api/v3/simple/price?ids=steem&vs_currencies=btc&include_24hr_vol=true",
|
|
861
|
-
]
|
|
862
|
-
headers = {
|
|
863
|
-
"Content-type": "application/x-www-form-urlencoded",
|
|
864
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",
|
|
865
|
-
}
|
|
866
|
-
cnt = 0
|
|
867
|
-
while len(prices) == 0 and cnt < 5:
|
|
868
|
-
cnt += 1
|
|
869
|
-
try:
|
|
870
|
-
responses = list(requests.get(u, headers=headers, timeout=30) for u in urls)
|
|
871
|
-
except Exception as e:
|
|
872
|
-
log.debug(str(e))
|
|
873
|
-
|
|
874
|
-
for r in [
|
|
875
|
-
x
|
|
876
|
-
for x in responses
|
|
877
|
-
if hasattr(x, "status_code") and x.status_code == 200 and x.json()
|
|
878
|
-
]:
|
|
879
|
-
try:
|
|
880
|
-
if "poloniex" in r.url:
|
|
881
|
-
data = r.json()["BTC_STEEM"]
|
|
882
|
-
prices["poloniex"] = {
|
|
883
|
-
"price": float(data["last"]),
|
|
884
|
-
"volume": float(data["baseVolume"]),
|
|
885
|
-
}
|
|
886
|
-
elif "bittrex" in r.url:
|
|
887
|
-
data = r.json()["result"][0]
|
|
888
|
-
price = (data["Bid"] + data["Ask"]) / 2
|
|
889
|
-
prices["bittrex"] = {"price": price, "volume": data["BaseVolume"]}
|
|
890
|
-
elif "binance" in r.url:
|
|
891
|
-
data = [x for x in r.json() if x["symbol"] == "STEEMBTC"][0]
|
|
892
|
-
prices["binance"] = {
|
|
893
|
-
"price": float(data["lastPrice"]),
|
|
894
|
-
"volume": float(data["quoteVolume"]),
|
|
895
|
-
}
|
|
896
|
-
elif "huobi" in r.url:
|
|
897
|
-
data = r.json()["data"][-1]
|
|
898
|
-
prices["huobi"] = {
|
|
899
|
-
"price": float(data["close"]),
|
|
900
|
-
"volume": float(data["vol"]),
|
|
901
|
-
}
|
|
902
|
-
elif "upbit" in r.url:
|
|
903
|
-
data = r.json()[-1]
|
|
904
|
-
prices["upbit"] = {
|
|
905
|
-
"price": float(data["tradePrice"]),
|
|
906
|
-
"volume": float(data["tradeVolume"]),
|
|
907
|
-
}
|
|
908
|
-
elif "coingecko" in r.url:
|
|
909
|
-
data = r.json()["steem"]
|
|
910
|
-
if "usd_24h_vol" in data:
|
|
911
|
-
volume = float(data["usd_24h_vol"])
|
|
912
|
-
else:
|
|
913
|
-
volume = 1
|
|
914
|
-
prices["coingecko"] = {"price": float(data["btc"]), "volume": volume}
|
|
915
|
-
except KeyError as e:
|
|
916
|
-
log.info(str(e))
|
|
788
|
+
Return the HIVE/BTC price as a volume-weighted average from multiple public exchanges.
|
|
917
789
|
|
|
918
|
-
|
|
919
|
-
raise RuntimeError("Obtaining STEEM/BTC prices has failed from all sources.")
|
|
790
|
+
Queries several public APIs (CoinGecko and others) to collect recent HIVE/BTC prices and 24h volumes, then computes a volume-weighted average price (VWAP). The function retries up to 5 times if no valid responses are obtained.
|
|
920
791
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
)
|
|
792
|
+
Returns:
|
|
793
|
+
float: VWAP price expressed in BTC per 1 HIVE.
|
|
924
794
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
return self.steem_btc_ticker() * self.btc_usd_ticker()
|
|
928
|
-
|
|
929
|
-
@staticmethod
|
|
930
|
-
def hive_btc_ticker():
|
|
931
|
-
"""Returns the HIVE/BTC price from bittrex and upbit. The mean price is
|
|
932
|
-
weighted by the exchange volume.
|
|
795
|
+
Raises:
|
|
796
|
+
RuntimeError: If no valid price data could be obtained from any source.
|
|
933
797
|
"""
|
|
934
798
|
prices = {}
|
|
935
799
|
responses = []
|
nectar/memo.py
CHANGED
|
@@ -19,7 +19,7 @@ class Memo(object):
|
|
|
19
19
|
|
|
20
20
|
:param Account from_account: Account that has sent the memo
|
|
21
21
|
:param Account to_account: Account that has received the memo
|
|
22
|
-
:param
|
|
22
|
+
:param Hive blockchain_instance: Hive instance
|
|
23
23
|
|
|
24
24
|
A memo is encrypted with a shared secret derived from a private key of
|
|
25
25
|
the sender and a public key of the receiver. Due to the underlying
|
|
@@ -51,7 +51,7 @@ class Memo(object):
|
|
|
51
51
|
|
|
52
52
|
Memo Keys
|
|
53
53
|
|
|
54
|
-
In
|
|
54
|
+
In Hive, memos are AES-256 encrypted with a shared secret between sender and
|
|
55
55
|
receiver. It is derived from the memo private key of the sender and the memo
|
|
56
56
|
public key of the receiver.
|
|
57
57
|
|
|
@@ -136,11 +136,23 @@ class Memo(object):
|
|
|
136
136
|
"""
|
|
137
137
|
|
|
138
138
|
def __init__(self, from_account=None, to_account=None, blockchain_instance=None, **kwargs):
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
"""
|
|
140
|
+
Initialize a Memo helper that resolves sender/recipient identifiers into Account/Key objects.
|
|
141
|
+
|
|
142
|
+
If `from_account`/`to_account` are provided as strings shorter than 51 characters they are treated as account names and resolved to Account(...) using the selected blockchain instance. Strings with length >= 51 are treated as raw keys and converted to PrivateKey (for `from_account`) or PublicKey (for `to_account`). If an input is omitted, the corresponding attribute is set to None.
|
|
143
|
+
|
|
144
|
+
Also sets self.blockchain to the provided blockchain_instance or, if None, the shared blockchain instance.
|
|
145
|
+
|
|
146
|
+
Parameters:
|
|
147
|
+
from_account (str|Account|PrivateKey|None): Sender identity — an account name (resolved to Account) or a private key string (resolved to PrivateKey). If already an Account/PrivateKey object, it will be assigned as-is by calling the appropriate constructor above.
|
|
148
|
+
to_account (str|Account|PublicKey|None): Recipient identity — an account name (resolved to Account) or a public key string (resolved to PublicKey).
|
|
149
|
+
blockchain_instance (optional): Blockchain client/instance to use for Account resolution; if omitted the shared blockchain instance is used.
|
|
150
|
+
|
|
151
|
+
Attributes set:
|
|
152
|
+
self.blockchain: blockchain instance used for key/account resolution.
|
|
153
|
+
self.from_account: Account or PrivateKey instance (or None).
|
|
154
|
+
self.to_account: Account or PublicKey instance (or None).
|
|
155
|
+
"""
|
|
144
156
|
self.blockchain = blockchain_instance or shared_blockchain_instance()
|
|
145
157
|
|
|
146
158
|
if to_account and len(to_account) < 51:
|
|
@@ -272,20 +284,35 @@ class Memo(object):
|
|
|
272
284
|
return from_key, to_key, nonce
|
|
273
285
|
|
|
274
286
|
def decrypt(self, memo):
|
|
275
|
-
"""
|
|
287
|
+
"""
|
|
288
|
+
Decrypt a memo message produced for a transfer.
|
|
276
289
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
:
|
|
290
|
+
Accepts either a raw memo string or a transfer-style dict with keys "from", "to", and "memo" or "message". If provided, the memo dict may also contain a "nonce". The function will locate an appropriate private memo key from the local wallet (or use a provided PrivateKey), derive the shared secret with the counterparty public key, and return the decrypted plaintext.
|
|
291
|
+
|
|
292
|
+
Parameters:
|
|
293
|
+
memo (str or dict): Encrypted memo as a string, or a dict in transfer form:
|
|
294
|
+
{"from": <account|key>, "to": <account|key>, "memo"/"message": <str>, "nonce"?: <int|str>}.
|
|
295
|
+
- "from"/"to" entries may be account names, account dicts, PublicKey/PrivateKey objects, or omitted.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
str: Decrypted memo plaintext, or None if `memo` is falsy.
|
|
299
|
+
|
|
300
|
+
Raises:
|
|
301
|
+
MissingKeyError: If no installed private memo key can be found for decrypting the message.
|
|
280
302
|
"""
|
|
281
303
|
if not memo:
|
|
282
304
|
return None
|
|
283
305
|
memo_wif = None
|
|
284
306
|
# We first try to decode assuming we received the memo
|
|
285
|
-
if
|
|
307
|
+
if (
|
|
308
|
+
isinstance(memo, dict)
|
|
309
|
+
and "to" in memo
|
|
310
|
+
and "from" in memo
|
|
311
|
+
and ("memo" in memo or "message" in memo)
|
|
312
|
+
):
|
|
286
313
|
memo_to = Account(memo["to"], blockchain_instance=self.blockchain)
|
|
287
314
|
memo_from = Account(memo["from"], blockchain_instance=self.blockchain)
|
|
288
|
-
message = memo
|
|
315
|
+
message = memo.get("memo") or memo.get("message")
|
|
289
316
|
else:
|
|
290
317
|
memo_to = self.to_account
|
|
291
318
|
memo_from = self.from_account
|