def cancelOrder(self, assetPair, order): if not yuwaves.OFFLINE: if order.status() == 'Filled': msg = "Order already filled" logging.error(msg) yuwaves.throw_error(msg) elif not order.status(): msg = "Order not found" logging.error(msg) yuwaves.throw_error(msg) sData = base58.b58decode(bytes(self.publicKey)) + \ base58.b58decode(bytes(order.orderId)) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "sender": self.publicKey, "orderId": order.orderId, "signature": signature }) req = yuwaves.wrapper( '/matcher/orderbook/%s/%s/cancel' % ('WAVES' if assetPair.asset1.assetId == '' else assetPair.asset1.assetId, 'WAVES' if assetPair.asset2.assetId == '' else assetPair.asset2.assetId), data, host=yuwaves.MATCHER) if yuwaves.OFFLINE: return req else: id = -1 if req['status'] == 'OrderCanceled': id = req['orderId'] logging.info('Order Cancelled - ID: %s' % id) return id
def createAlias(self, alias, txFee=yuwaves.DEFAULT_ALIAS_FEE, timestamp=0): aliasWithNetwork = b'\x02' + crypto.str2bytes(bytes( yuwaves.CHAIN_ID)) + struct.pack( ">H", len(alias)) + crypto.str2bytes(alias) if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) else: if timestamp == 0: timestamp = int(time.time() * 1000) sData = b'\x0a' + \ base58.b58decode(bytes(self.publicKey)) + \ struct.pack(">H", len(aliasWithNetwork)) + \ crypto.str2bytes(bytes(aliasWithNetwork)) + \ struct.pack(">Q", txFee) + \ struct.pack(">Q", timestamp) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "alias": alias, "senderPublicKey": self.publicKey, "fee": txFee, "timestamp": timestamp, "signature": signature }) return yuwaves.wrapper('/alias/broadcast/create', data)
def leaseCancel(self, leaseId, txFee=yuwaves.DEFAULT_LEASE_FEE, timestamp=0): if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and self.balance() < txFee: msg = 'Insufficient Waves balance' logging.error(msg) yuwaves.throw_error(msg) else: if timestamp == 0: timestamp = int(time.time() * 1000) sData = b'\x09' + \ base58.b58decode(bytes(self.publicKey)) + \ struct.pack(">Q", txFee) + \ struct.pack(">Q", timestamp) + \ base58.b58decode(bytes(leaseId)) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "senderPublicKey": self.publicKey, "txId": leaseId, "fee": txFee, "timestamp": timestamp, "signature": signature }) req = yuwaves.wrapper('/leasing/broadcast/cancel', data) if yuwaves.OFFLINE: return req elif 'leaseId' in req: return req['leaseId']
def issueSmartAsset(self, name, description, quantity, scriptSource, decimals=0, reissuable=False, txFee=yuwaves.DEFAULT_ASSET_FEE): script = yuwaves.wrapper('/utils/script/compile', scriptSource)['script'][7:] if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) elif len(name) < 4 or len(name) > 16: msg = 'Asset name must be between 4 and 16 characters long' logging.error(msg) yuwaves.throw_error(msg) else: compiledScript = base64.b64decode(script) scriptLength = len(compiledScript) timestamp = int(time.time() * 1000) sData = b'\3' + \ b'\2' + \ crypto.str2bytes(str(yuwaves.CHAIN_ID)) + \ base58.b58decode(self.publicKey) + \ struct.pack(">H", len(name)) + \ crypto.str2bytes(name) + \ struct.pack(">H", len(description)) + \ crypto.str2bytes(description) + \ struct.pack(">Q", quantity) + \ struct.pack(">B", decimals) + \ (b'\1' if reissuable else b'\0') + \ struct.pack(">Q", txFee) + \ struct.pack(">Q", timestamp) + \ b'\1' + \ struct.pack(">H", scriptLength) + \ compiledScript signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "type": 3, "senderPublicKey": self.publicKey, "name": name, "version": 2, "quantity": quantity, "timestamp": timestamp, "description": description, "decimals": decimals, "reissuable": reissuable, "fee": txFee, "proofs": [signature], "script": 'base64:' + script }) req = yuwaves.wrapper('/transactions/broadcast', data) if yuwaves.OFFLINE: return req else: return req
def trades(self, *args): if len(args) == 1: limit = args[0] if limit > 0 and limit <= yuwaves.MAX_WDF_REQUEST: return self._getMarketData('/api/trades/', '%d' % limit) else: msg = 'Invalid request. Limit must be >0 and <= 100' yuwaves.throw_error(msg) return logging.error(msg) elif len(args) == 2: fromTimestamp = args[0] toTimestamp = args[1] return self._getMarketData('/api/trades', '%d/%d' % (fromTimestamp, toTimestamp))
def issueAsset(self, name, description, quantity, decimals=0, reissuable=False, txFee=yuwaves.DEFAULT_ASSET_FEE): if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) elif len(name) < 4 or len(name) > 16: msg = 'Asset name must be between 4 and 16 characters long' logging.error(msg) yuwaves.throw_error(msg) else: timestamp = int(time.time() * 1000) sData = b'\3' + \ base58.b58decode(bytes(self.publicKey)) + \ struct.pack(">H", len(name)) + \ crypto.str2bytes(name) + \ struct.pack(">H", len(description)) + \ crypto.str2bytes(description) + \ struct.pack(">Q", quantity) + \ struct.pack(">B", decimals) + \ (b'\1' if reissuable else b'\0') + \ struct.pack(">Q", txFee) + \ struct.pack(">Q", timestamp) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "senderPublicKey": self.publicKey, "name": name, "quantity": quantity, "timestamp": timestamp, "description": description, "decimals": decimals, "reissuable": reissuable, "fee": txFee, "signature": signature }) req = yuwaves.wrapper('/assets/broadcast/issue', data) if yuwaves.OFFLINE: return req else: return yuwaves.Asset(req['assetId'])
def candles(self, *args): if len(args) == 2: timeframe = args[0] limit = args[1] if timeframe not in yuwaves.VALID_TIMEFRAMES: msg = 'Invalid timeframe' yuwaves.throw_error(msg) return logging.error(msg) elif limit > 0 and limit <= yuwaves.MAX_WDF_REQUEST: return self._getMarketData('/api/candles', '%d/%d' % (timeframe, limit)) else: msg = 'Invalid request. Limit must be >0 and <= 100' yuwaves.throw_error(msg) return logging.error(msg) elif len(args) == 3: timeframe = args[0] fromTimestamp = args[1] toTimestamp = args[2] if timeframe not in yuwaves.VALID_TIMEFRAMES: msg = 'Invalid timeframe' yuwaves.throw_error(msg) return logging.error(msg) else: return self._getMarketData( '/api/candles', '%d/%d/%d' % (timeframe, fromTimestamp, toTimestamp))
def getOrderHistory(self, assetPair, timestamp=0): if timestamp == 0: timestamp = int(time.time() * 1000) sData = base58.b58decode(bytes(self.publicKey)) + \ struct.pack(">Q", timestamp) signature = crypto.sign(self.privateKey, sData) data = { "Accept": "application/json", "Timestamp": bytes(timestamp), "Signature": signature } req = yuwaves.wrapper( '/matcher/orderbook/%s/%s/publicKey/%s' % ('WAVES' if assetPair.asset1.assetId == '' else assetPair.asset1.assetId, 'WAVES' if assetPair.asset2.assetId == '' else assetPair.asset2.assetId, self.publicKey), headers=data, host=yuwaves.MATCHER) if 'message' in req: msg = req['message'] logging.error(msg) yuwaves.throw_error(msg) return req
def sendWaves(self, recipient, amount, attachment='', txFee=yuwaves.DEFAULT_TX_FEE, timestamp=0): if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) elif amount <= 0: msg = 'Amount must be > 0' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and self.balance() < amount + txFee: msg = 'Insufficient Waves balance' logging.error(msg) yuwaves.throw_error(msg) else: if timestamp == 0: timestamp = int(time.time() * 1000) sData = b'\4' + \ base58.b58decode(bytes(self.publicKey)) + \ b'\0\0' + \ struct.pack(">Q", timestamp) + \ struct.pack(">Q", amount) + \ struct.pack(">Q", txFee) + \ base58.b58decode(bytes(recipient.address)) + \ struct.pack(">H", len(attachment)) + \ crypto.str2bytes(attachment) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "senderPublicKey": self.publicKey, "recipient": recipient.address, "amount": amount, "fee": txFee, "timestamp": timestamp, "attachment": base58.b58encode(crypto.str2bytes(attachment)), "signature": signature }) return yuwaves.wrapper('/assets/broadcast/transfer', data)
def lease(self, recipient, amount, txFee=yuwaves.DEFAULT_LEASE_FEE, timestamp=0): if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) elif amount <= 0: msg = 'Amount must be > 0' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and self.balance() < amount + txFee: msg = 'Insufficient Waves balance' logging.error(msg) yuwaves.throw_error(msg) else: if timestamp == 0: timestamp = int(time.time() * 1000) sData = b'\x08' + \ base58.b58decode(bytes(self.publicKey)) + \ base58.b58decode(bytes(recipient.address)) + \ struct.pack(">Q", amount) + \ struct.pack(">Q", txFee) + \ struct.pack(">Q", timestamp) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "senderPublicKey": self.publicKey, "recipient": recipient.address, "amount": amount, "fee": txFee, "timestamp": timestamp, "signature": signature }) req = yuwaves.wrapper('/leasing/broadcast/lease', data) return req
def _postOrder(self, amountAsset, priceAsset, orderType, amount, price, maxLifetime=30 * 86400, matcherFee=yuwaves.DEFAULT_MATCHER_FEE, timestamp=0): from decimal import Decimal if not isinstance(amount, Decimal) or not isinstance(price, Decimal): raise Exception('Decimal type expected') amount = int((amount * Decimal( (0, (1, ), amountAsset.decimals))).to_integral_exact()) price = int((price * Decimal( (0, (1, ), priceAsset.decimals))).to_integral_exact()) if timestamp == 0: timestamp = int(time.time() * 1000) expiration = timestamp + maxLifetime * 1000 asset1 = b'\0' if amountAsset.assetId == '' else b'\1' + base58.b58decode( bytes(amountAsset.assetId)) asset2 = b'\0' if priceAsset.assetId == '' else b'\1' + base58.b58decode( bytes(priceAsset.assetId)) sData = base58.b58decode(bytes(self.publicKey)) + \ base58.b58decode(bytes(yuwaves.MATCHER_PUBLICKEY)) + \ asset1 + \ asset2 + \ orderType + \ struct.pack(">Q", price) + \ struct.pack(">Q", amount) + \ struct.pack(">Q", timestamp) + \ struct.pack(">Q", expiration) + \ struct.pack(">Q", matcherFee) signature = crypto.sign(self.privateKey, sData) otype = "buy" if orderType == b'\0' else "sell" data = json.dumps({ "senderPublicKey": self.publicKey, "matcherPublicKey": yuwaves.MATCHER_PUBLICKEY, "assetPair": { "amountAsset": amountAsset.assetId, "priceAsset": priceAsset.assetId, }, "orderType": otype, "price": price, "amount": amount, "timestamp": timestamp, "expiration": expiration, "matcherFee": matcherFee, "signature": signature }) req = yuwaves.wrapper('/matcher/orderbook', data, host=yuwaves.MATCHER) """ {u'status': u'OrderAccepted', u'message': {u'assetPair': {u'priceAsset': u'Ft8X1v1LTa1ABafufpaCWyVj8KkaxUWE6xBhW6sNFJck', u'amountAsset': None}, u'orderType': u'buy', u'price': 268, u'signature': u'4LzSfA4CDLbznAsykB8fHXtvLP6ZvaUYkSowrn6KXgouatSskHRQ1chiPdq6Hyo7yXi9cdfYdTZo6NFVk8APBXuz', u'matcherFee': 300000, u'senderPublicKey': u'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', u'amount': 387444879, u'version': 1, u'expiration': 1553609813760, u'timestamp': 1551017813760, u'proofs': [u'4LzSfA4CDLbznAsykB8fHXtvLP6ZvaUYkSowrn6KXgouatSskHRQ1chiPdq6Hyo7yXi9cdfYdTZo6NFVk8APBXuz'], u'id': u'CGchfxnGKsySb36SPziRXo7AoijPUPvYReuXN9KczRwT', u'matcherPublicKey': u'7kPFrHDiGw1rCm7LPszuECwWYL3dMf6iMifLRDJQZMzy', u'sender': u'3XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'}} """ id = -1 if 'status' in req: if req['status'] == 'OrderRejected': msg = 'Order Rejected - %s' % req['message'] logging.error(msg) yuwaves.throw_error(msg) elif req['status'] == 'OrderAccepted': id = str(req['message']['id']) logging.info('Order Accepted - ID: %s' % id) elif not yuwaves.OFFLINE: logging.error(req) yuwaves.throw_error(req) else: return req return id
def sendAsset(self, recipient, asset, amount, attachment='', feeAsset='', txFee=yuwaves.DEFAULT_TX_FEE, timestamp=0): if not self.privateKey: msg = 'Asset not issued' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and asset and not asset.status(): msg = 'Asset not issued' logging.error(msg) yuwaves.throw_error(msg) elif amount <= 0: msg = 'Amount must be > 0' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and asset and self.balance( asset.assetId) < amount: msg = 'Insufficient asset balance' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and not asset and self.balance() < amount: msg = 'Insufficient Waves balance' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and not feeAsset and self.balance() < txFee: msg = 'Insufficient Waves balance' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and feeAsset and self.balance( feeAsset.assetId) < txFee: msg = 'Insufficient asset balance' logging.error(msg) yuwaves.throw_error(msg) else: if feeAsset: feeInfos = yuwaves.wrapper('/assets/details/' + feeAsset.assetId) if feeInfos['minSponsoredAssetFee']: txFee = feeInfos['minSponsoredAssetFee'] if timestamp == 0: timestamp = int(time.time() * 1000) sData = b'\4' + \ base58.b58decode(bytes(self.publicKey)) + \ (b'\1' + base58.b58decode(bytes(asset.assetId)) if asset else b'\0') + \ (b'\1' + base58.b58decode(bytes(feeAsset.assetId)) if feeAsset else b'\0') + \ struct.pack(">Q", timestamp) + \ struct.pack(">Q", amount) + \ struct.pack(">Q", txFee) + \ base58.b58decode(bytes(recipient.address)) + \ struct.pack(">H", len(attachment)) + \ crypto.str2bytes(attachment) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "assetId": (asset.assetId if asset else ""), "feeAssetId": (feeAsset.assetId if feeAsset else ""), "senderPublicKey": self.publicKey, "recipient": recipient.address, "amount": amount, "fee": txFee, "timestamp": timestamp, "attachment": base58.b58encode(crypto.str2bytes(attachment)), "signature": signature }) return yuwaves.wrapper('/assets/broadcast/transfer', data)
def massTransferWaves(self, transfers, attachment='', timestamp=0): txFee = 100000 + (math.ceil((len(transfers) + 1) / 2 - 0.5)) * 100000 totalAmount = 0 for i in range(0, len(transfers)): totalAmount += transfers[i]['amount'] if not self.privateKey: msg = 'Private key required' logging.error(msg) yuwaves.throw_error(msg) elif len(transfers) > 100: msg = 'Too many recipients' logging.error(msg) yuwaves.throw_error(msg) elif not yuwaves.OFFLINE and self.balance() < totalAmount + txFee: msg = 'Insufficient Waves balance' logging.error(msg) yuwaves.throw_error(msg) else: if timestamp == 0: timestamp = int(time.time() * 1000) transfersData = b'' for i in range(0, len(transfers)): transfersData += base58.b58decode( bytes(transfers[i]['recipient']) + struct.pack(">Q", transfers[i]['amount'])) sData = b'\x0b' + \ b'\1' + \ base58.b58decode(bytes(self.publicKey)) + \ b'\0' + \ struct.pack(">H", len(transfers)) + \ transfersData + \ struct.pack(">Q", timestamp) + \ struct.pack(">Q", txFee) + \ struct.pack(">H", len(attachment)) + \ crypto.str2bytes(attachment) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "type": 11, "version": 1, "assetId": "", "senderPublicKey": self.publicKey, "fee": txFee, "timestamp": timestamp, "transfers": transfers, "attachment": base58.b58encode(crypto.str2bytes(attachment)), "signature": signature, "proofs": [signature] }) return yuwaves.wrapper('/transactions/broadcast', data)