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 _generate(self, publicKey='', privateKey='', seed='', nonce=0): self.seed = seed self.nonce = nonce if not publicKey and not privateKey and not seed: from seed import generate_seed self.seed = generate_seed() if publicKey: pubKey = base58.b58decode(bytes(publicKey)) privKey = "" else: seedHash = crypto.hashChain( struct.pack(">L", nonce) + crypto.str2bytes(self.seed)) accountSeedHash = crypto.sha256(seedHash) if not privateKey: privKey = curve.generatePrivateKey(accountSeedHash) else: privKey = base58.b58decode(bytes(privateKey)) pubKey = curve.generatePublicKey(privKey) unhashedAddress = chr(1) + bytes( yuwaves.CHAIN_ID) + crypto.hashChain(pubKey)[0:20] addressHash = crypto.hashChain(crypto.str2bytes(unhashedAddress))[0:4] self.address = base58.b58encode( crypto.str2bytes(unhashedAddress + addressHash)) self.publicKey = base58.b58encode(pubKey) if privKey != "": self.privateKey = base58.b58encode(privKey)
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 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 setScript(self, scriptSource, txFee=yuwaves.DEFAULT_SCRIPT_FEE, timestamp=0): script = yuwaves.wrapper('/utils/script/compile', scriptSource)['script'][7:] if not self.privateKey: logging.error('Private key required') else: compiledScript = base64.b64decode(bytes(script)) scriptLength = len(compiledScript) if timestamp == 0: timestamp = int(time.time() * 1000) sData = b'\x0d' + \ b'\1' + \ crypto.str2bytes(bytes(yuwaves.CHAIN_ID)) + \ base58.b58decode(bytes(self.publicKey)) + \ b'\1' + \ struct.pack(">H", scriptLength) + \ compiledScript + \ struct.pack(">Q", txFee) + \ struct.pack(">Q", timestamp) signature = crypto.sign(self.privateKey, sData) data = json.dumps({ "type": 13, "version": 1, "senderPublicKey": self.publicKey, "fee": txFee, "timestamp": timestamp, "script": 'base64:' + script, "proofs": [signature] }) return yuwaves.wrapper('/transactions/broadcast', data)
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 burnAsset(self, Asset, quantity, txFee=yuwaves.DEFAULT_TX_FEE): timestamp = int(time.time() * 1000) sData = '\6' + \ crypto.bytes2str(base58.b58decode(bytes(self.publicKey))) + \ crypto.bytes2str(base58.b58decode(bytes(Asset.assetId))) + \ crypto.bytes2str(struct.pack(">Q", quantity)) + \ crypto.bytes2str(struct.pack(">Q", txFee)) + \ crypto.bytes2str(struct.pack(">Q", timestamp)) signature = crypto.sign(self.privateKey, crypto.str2bytes(sData)) data = json.dumps({ "senderPublicKey": self.publicKey, "assetId": Asset.assetId, "quantity": quantity, "timestamp": timestamp, "fee": txFee, "signature": signature }) req = yuwaves.wrapper('/assets/broadcast/burn', data) if yuwaves.OFFLINE: return req else: return req.get('id', 'ERROR')
def dataTransaction(self, data, timestamp=0): if not self.privateKey: logging.error('Private key required') else: if timestamp == 0: timestamp = int(time.time() * 1000) dataObject = { "type": 12, "version": 1, "senderPublicKey": self.publicKey, "data": data, "fee": 0, "timestamp": timestamp, "proofs": [''] } dataBinary = b'' for i in range(0, len(data)): d = data[i] keyBytes = crypto.str2bytes(d['key']) dataBinary += struct.pack(">H", len(keyBytes)) dataBinary += keyBytes if d['type'] == 'binary': dataBinary += b'\2' valueAsBytes = d['value'] dataBinary += struct.pack(">H", len(valueAsBytes)) dataBinary += crypto.str2bytes(valueAsBytes) elif d['type'] == 'boolean': if d['value']: dataBinary += b'\1\1' else: dataBinary += b'\1\0' elif d['type'] == 'integer': dataBinary += b'\0' dataBinary += struct.pack(">Q", d['value']) elif d['type'] == 'string': dataBinary += b'\3' dataBinary += struct.pack(">H", len(d['value'])) dataBinary += crypto.str2bytes(d['value']) # check: https://stackoverflow.com/questions/2356501/how-do-you-round-up-a-number-in-python txFee = (int(( (len(crypto.str2bytes(json.dumps(data))) + 2 + 64)) / 1000.0) + 1) * 100000 dataObject['fee'] = txFee sData = b'\x0c' + \ b'\1' + \ base58.b58decode(bytes(self.publicKey)) + \ struct.pack(">H", len(data)) + \ dataBinary + \ struct.pack(">Q", timestamp) + \ struct.pack(">Q", txFee) dataObject['proofs'] = [crypto.sign(self.privateKey, sData)] for entry in dataObject['data']: if entry['type'] == 'binary': base64Encoded = base64.b64encode( crypto.str2bytes(entry['value'])) entry['value'] = 'base64:' + crypto.bytes2str( base64Encoded) dataObjectJSON = json.dumps(dataObject) return yuwaves.wrapper('/transactions/broadcast', dataObjectJSON)
def massTransferAssets(self, transfers, asset, attachment='', timestamp=0): txFee = 100000 + (math.ceil((len(transfers) + 1) / 2 - 0.5)) * 100000 if (asset.scripted): txFee += 400000 totalAmount = 0 if not self.privateKey: logging.error('Private key required') elif len(transfers) > 100: logging.error('Too many recipients') elif not yuwaves.OFFLINE and self.balance() < txFee: logging.error('Insufficient Waves balance') elif not yuwaves.OFFLINE and self.balance( assetId=asset.assetId) < totalAmount: logging.error('Insufficient %s balance' % asset.name) 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'\1' + \ base58.b58decode(bytes(asset.assetId)) + \ 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": asset.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)
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)