<filename>NemConnect.py
import json
import requests
import base64
import datetime
from binascii import hexlify, unhexlify
from math import floor, ceil, log, atan


def MAIN_NET_VERSION(ver):
    return (0x68000000 | ver)


def TEST_NET_VERSION(ver):
    return (0x98000000 | ver)


CURRENT_MOSAIC_SINK = 'TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC'
CURRENT_NAMESPACE_SINK = 'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35'
CURRENT_NETWORK_VERSION = TEST_NET_VERSION

#CURRENT_MOSAIC_SINK = 'MBMOSAICOD4F54EE5CDMR23CCBGOAM2XSKYHTOJD'
#CURRENT_NAMESPACE_SINK = 'MAMESPACEWH4MKFMBCVFERDPOOP4FK7MTCZTG5E7'
#def CURRENT_NETWORK_VERSION(ver):
#    return (0x60000000 | ver)


class NemConnect:
    def __init__(self, address, port):
        self.address = address
        self.port = port
        self.nemEpoch = datetime.datetime(2015, 3, 29, 0, 6, 25, 0, None)

    def getTimeStamp(self):
        now = datetime.datetime.utcnow()
        return int((now - self.nemEpoch).total_seconds())

    def testnetNodeInfo(self):
        r = self.sendGet('node/info', None)
        if r.ok:
            j = r.json()
            return j
        return None

    def nodeInfo(self):
        r = self.sendGet('node/info', None)
        if r.ok:
            j = r.json()
            print(j)
            if j['metaData']['application'] == 'NIS':
                return j
        return None

    def blockAt(self, h):
        data = {'height': h}
        r = self.sendPost('block/at/public', data)
        return r.json()

    def blocksAfter(self, height):
        data = {'height': height}
        r = self.sendPost('local/chain/blocks-after', data)
        return r.json()

    def chainHeight(self):
        r = self.sendGet('chain/height', None)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def accountGet(self, address):
        data = {'address': address}
        r = self.sendGet('account/get', data)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def accountOwnedMosaicsGet(self, address):
        data = {'address': address}
        r = self.sendGet('account/mosaic/owned', data)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def accountUnlock(self, privatekey):
        data = {'value': privatekey}
        r = self.sendPost('account/unlock', data)
        if r.ok:
            return True, None
        return False, r.json()

    def accountIsUnlocked(self, privatekey):
        data = {'value': privatekey}
        r = self.sendPost('local/account/isunlocked', data)
        if r.ok:
            return True, None
        return False, r.json()

    def accountLock(self, privatekey):
        data = {'value': privatekey}
        r = self.sendPost('account/lock', data)
        if r.ok:
            return True, None
        return False, r.json()

    def namespaceGet(self, namespace):
        data = {'namespace': namespace}
        r = self.sendGet('namespace', data)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def mosaicDefinition(self, mosaicFqdn):
        r = self.sendGet('mosaic/definition', {'mosaicId': mosaicFqdn})
        if r.ok:
            return True, r.json()
        return False, r.json()

    def mosaicSupply(self, mosaicFqdn):
        r = self.sendGet('mosaic/supply', {'mosaicId': mosaicFqdn})
        if r.ok:
            return True, r.json()
        return False, r.json()

    @staticmethod
    def createData(txtype, senderPublicKey, timeStamp, version=CURRENT_NETWORK_VERSION(1)):
        return {'type': txtype,
                'version': version,
                'signer': senderPublicKey,
                'timeStamp': timeStamp,
                'deadline': timeStamp + 60 * 60
                }

    @staticmethod
    def calcMinFee(numNem):
        return int(max(10 - numNem, 2, int(atan(numNem / 150000.0) * 3 * 33)))

    def _constructTransfer(self, senderPublicKey, recipientCompressedKey, amount, message, mosaics, mosaicsFee):
        timeStamp = self.getTimeStamp()
        version = CURRENT_NETWORK_VERSION(2) if mosaics else CURRENT_NETWORK_VERSION(1)
        data = NemConnect.createData(0x101, senderPublicKey, timeStamp, version)
        msgFee = 0 if len(message) == 0 else max(1, len(message) / 16) * 2
        fee = mosaicsFee if mosaics else NemConnect.calcMinFee(amount / 1000000)
        totalFee = (msgFee + fee)
        totalFee *= 1000000
        custom = {
            'recipient': recipientCompressedKey.replace('-', ''),
            'amount': amount,
            'fee': totalFee,
            'message': {'type': 1, 'payload': hexlify(message)}
        }
        if mosaics:
            custom['mosaics'] = mosaics
            print "Attached mosaic:", custom['mosaics']
        entity = dict(data.items() + custom.items())
        return entity

    def _constructImportanceTransfer(self, senderPublicKey, remotePublicKey, doAssign):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x801, senderPublicKey, timeStamp)
        custom = {
            'mode': 1 if doAssign else 2,
            'remoteAccount': remotePublicKey,
            'fee': 8000000,
        }
        entity = dict(data.items() + custom.items())
        return entity

    def _constructModification(self, senderPublicKey, cosignatories):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1001, senderPublicKey, timeStamp)
        custom = {
            'fee': 2 * (5000000 + 3000000 * (len(cosignatories))),
            'modifications': [
                {'modificationType': 2, 'cosignatoryAccount': publicKey}
                for publicKey in cosignatories
                ]
        }
        entity = dict(data.items() + custom.items())
        return entity

    def _constructNamespace(self, senderPublicKey, namespaceFqn):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x2001, senderPublicKey, timeStamp)
        parts = namespaceFqn.split('.')
        rental = 50000 if len(parts) == 1 else 5000
        custom = {
            'rentalFeeSink': CURRENT_NAMESPACE_SINK,
            'fee': 2 * 3 * 18 * 1000000,
            'rentalFee': rental * 1000000,
            'newPart': parts[-1],
        }
        if len(parts) > 1:
            custom['parent'] = '.'.join(parts[:-1])
        entity = dict(data.items() + custom.items())
        return entity

    @staticmethod
    def parseMosaicFqn(mosaicFqn):
        if " * " in mosaicFqn:
            return mosaicFqn.split(" * ")
        else:
            parts = mosaicFqn.split('.')
            return ('.'.join(parts[:-1]), parts[-1])

    def _constructMosaic(self, senderPublicKey, mosaicFqn, description, props):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x4001, senderPublicKey, timeStamp)

        namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(mosaicFqn)
        custom = {
            'mosaicDefinition': {
                'creator': senderPublicKey,
                'id': {
                    'namespaceId': namespaceFqn,
                    'name': mosaicName
                },
                'description': description,
                'properties': [
                    {'name': 'divisibility', 'value': str(props['divisibility'])},
                    {'name': 'initialSupply', 'value': str(props['initialSupply'])},
                    {'name': 'supplyMutable', 'value': str(props['supplyMutable'])},
                    {'name': 'transferable', 'value': str(props['transferable'])}
                ],
            },
            'creationFeeSink': CURRENT_MOSAIC_SINK,
            'creationFee': 50000 * 1000000,
            'fee': 2 * 3 * 18 * 1000000
        }
        if 'levy' in props:
            levyFqn = props['levy']['mosaicFqn']
            namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(levyFqn)

            custom['mosaicDefinition']['levy'] = {
                "type": props['levy']['type'],
                "recipient": props['levy']['recipient'].replace('-', ''),
                "mosaicId": {
                    'namespaceId': namespaceFqn,
                    'name': mosaicName
                },
                "fee": props['levy']['fee']
            }
        entity = dict(data.items() + custom.items())
        return entity

    def _constructMosaicSupply(self, senderPublicKey, mosaicFqn, supplyType, supplyDelta):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x4002, senderPublicKey, timeStamp)

        namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(mosaicFqn)
        custom = {
            'mosaicId': {
                'namespaceId': namespaceFqn,
                'name': mosaicName
            },
            'supplyType': supplyType,
            'delta': int(supplyDelta),
            'fee': 2 * 3 * 18 * 1000000
        }
        entity = dict(data.items() + custom.items())
        return entity

    def _prepare(self, entity):
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def _multisigWrapper(self, senderPublicKey, entity):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1004, senderPublicKey, timeStamp)
        custom = {
            'fee': 18000000,
            'otherTrans': entity
        }
        entity = dict(data.items() + custom.items())
        print " {+} multisig wrapped"
        return entity

    @staticmethod
    def calcXemEquivalent(amount, q, sup, divi):
        if sup == 0:
            return 0

        multiplier = amount  # int(self.transferAmount.get()) * 1000000
        equivalent = 8999999999 * q * multiplier / sup / (10 ** (divi + 6))
        return equivalent

    def calculateMosaicsFee(self, amount, mosaics):
        data = {'fee': 0, 'mosaics': []}
        for m in mosaics:
            quantity = m[1]
            mosaicFqn = m[0]
            namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(mosaicFqn)
            ok, j = self.mosaicDefinition(namespaceFqn + ' * ' + mosaicName)
            if not ok:
                return ok, j
            divisibility = int((x for x in j['properties'] if x['name'] == 'divisibility').next()['value'])

            ok, j = self.mosaicSupply(namespaceFqn + ' * ' + mosaicName)
            if not ok:
                return ok, j

            supply = int(j['supply'])

            numNem = NemConnect.calcXemEquivalent(amount, quantity, supply, divisibility)
            data['fee'] += NemConnect.calcMinFee(numNem)
            data['mosaics'].append(
                {
                    'mosaicId': {
                        'namespaceId': namespaceFqn,
                        'name': mosaicName
                    },
                    'quantity': quantity
                }
            )
        data['fee'] = data['fee'] * 5 / 4
        return True, data

    def prepareTransfer(self, senderPublicKey, multisigPublicKey, recipientCompressedKey, amount, message, mosaics):
        mosaicsFee = 0
        if mosaics:
            ok, j = self.calculateMosaicsFee(amount, mosaics)
            if not ok:
                return ok, j
            mosaicsFee = j['fee']
            mosaics = j['mosaics']

        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructTransfer(actualSender, recipientCompressedKey, amount, message, mosaics, mosaicsFee)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareImportanceTransfer(self, senderPublicKey, multisigPublicKey, remotePublicKey, doAssign):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructImportanceTransfer(actualSender, remotePublicKey, doAssign)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareProvisionNamespace(self, senderPublicKey, multisigPublicKey, namespaceFqn):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructNamespace(actualSender, namespaceFqn)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareMosaicCreation(self, senderPublicKey, multisigPublicKey, mosaicFqn, description, props):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructMosaic(actualSender, mosaicFqn, description, props)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareMosaicSupply(self, senderPublicKey, multisigPublicKey, mosaicFqn, supplyType, quantity):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructMosaicSupply(actualSender, mosaicFqn, supplyType, quantity)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def multisigCreatePrepare(self, senderPublicKey, cosignatories):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1001, senderPublicKey, timeStamp)
        custom = {
            'fee': 2 * (5000000 + 3000000 * (len(cosignatories))),
            'modifications': [
                {'modificationType': 1, 'cosignatoryAccount': publicKey}
                for publicKey in cosignatories
                ]
        }
        entity = dict(data.items() + custom.items())
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def multisigModificationPrepare(self, senderPublicKey, multisig, cosignatories):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1004, senderPublicKey, timeStamp)
        transfer = self.constructModification(multisig, cosignatories)
        custom = {
            'fee': 6000000 * (len(cosignatories) + 1),
            'otherTrans': transfer
        }
        entity = dict(data.items() + custom.items())
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def multisigSignaturePrepare(self, senderPublicKey, multisigAddress, txHash):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1002, senderPublicKey, timeStamp)
        custom = {
            'fee': 2 * 3000000,
            'otherHash': {'data': txHash},
            'otherAccount': multisigAddress
        }
        entity = dict(data.items() + custom.items())
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def transferAnnounce(self, transferData, transferSignature):
        data = {'data': transferData,
                'signature': transferSignature
                }
        r = self.sendPost('transaction/announce', data)
        return r.ok, r.json()

    def sendGet(self, callName, data):
        headers = {'Content-type': 'application/json'}
        uri = 'http://' + self.address + ':' + str(self.port) + '/' + callName
        return requests.get(uri, params=data, headers=headers, timeout=10)

    def sendPost(self, callName, data):
        headers = {'Content-type': 'application/json'}
        uri = 'http://' + self.address + ':' + str(self.port) + '/' + callName
        return requests.post(uri, data=json.dumps(data), headers=headers, timeout=10)

<filename>NemConnect.py
import json
import requests
import base64
import datetime
from binascii import hexlify, unhexlify
from math import floor, ceil, log, atan


def MAIN_NET_VERSION(ver):
    return (0x68000000 | ver)


def TEST_NET_VERSION(ver):
    return (0x98000000 | ver)


CURRENT_MOSAIC_SINK = 'TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC'
CURRENT_NAMESPACE_SINK = 'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35'
CURRENT_NETWORK_VERSION = TEST_NET_VERSION

#CURRENT_MOSAIC_SINK = 'MBMOSAICOD4F54EE5CDMR23CCBGOAM2XSKYHTOJD'
#CURRENT_NAMESPACE_SINK = 'MAMESPACEWH4MKFMBCVFERDPOOP4FK7MTCZTG5E7'
#def CURRENT_NETWORK_VERSION(ver):
#    return (0x60000000 | ver)


class NemConnect:
    def __init__(self, address, port):
        self.address = address
        self.port = port
        self.nemEpoch = datetime.datetime(2015, 3, 29, 0, 6, 25, 0, None)

    def getTimeStamp(self):
        now = datetime.datetime.utcnow()
        return int((now - self.nemEpoch).total_seconds())

    def testnetNodeInfo(self):
        r = self.sendGet('node/info', None)
        if r.ok:
            j = r.json()
            return j
        return None

    def nodeInfo(self):
        r = self.sendGet('node/info', None)
        if r.ok:
            j = r.json()
            print(j)
            if j['metaData']['application'] == 'NIS':
                return j
        return None

    def blockAt(self, h):
        data = {'height': h}
        r = self.sendPost('block/at/public', data)
        return r.json()

    def blocksAfter(self, height):
        data = {'height': height}
        r = self.sendPost('local/chain/blocks-after', data)
        return r.json()

    def chainHeight(self):
        r = self.sendGet('chain/height', None)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def accountGet(self, address):
        data = {'address': address}
        r = self.sendGet('account/get', data)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def accountOwnedMosaicsGet(self, address):
        data = {'address': address}
        r = self.sendGet('account/mosaic/owned', data)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def accountUnlock(self, privatekey):
        data = {'value': privatekey}
        r = self.sendPost('account/unlock', data)
        if r.ok:
            return True, None
        return False, r.json()

    def accountIsUnlocked(self, privatekey):
        data = {'value': privatekey}
        r = self.sendPost('local/account/isunlocked', data)
        if r.ok:
            return True, None
        return False, r.json()

    def accountLock(self, privatekey):
        data = {'value': privatekey}
        r = self.sendPost('account/lock', data)
        if r.ok:
            return True, None
        return False, r.json()

    def namespaceGet(self, namespace):
        data = {'namespace': namespace}
        r = self.sendGet('namespace', data)
        if r.ok:
            return True, r.json()
        return False, r.json()

    def mosaicDefinition(self, mosaicFqdn):
        r = self.sendGet('mosaic/definition', {'mosaicId': mosaicFqdn})
        if r.ok:
            return True, r.json()
        return False, r.json()

    def mosaicSupply(self, mosaicFqdn):
        r = self.sendGet('mosaic/supply', {'mosaicId': mosaicFqdn})
        if r.ok:
            return True, r.json()
        return False, r.json()

    @staticmethod
    def createData(txtype, senderPublicKey, timeStamp, version=CURRENT_NETWORK_VERSION(1)):
        return {'type': txtype,
                'version': version,
                'signer': senderPublicKey,
                'timeStamp': timeStamp,
                'deadline': timeStamp + 60 * 60
                }

    @staticmethod
    def calcMinFee(numNem):
        return int(max(10 - numNem, 2, int(atan(numNem / 150000.0) * 3 * 33)))

    def _constructTransfer(self, senderPublicKey, recipientCompressedKey, amount, message, mosaics, mosaicsFee):
        timeStamp = self.getTimeStamp()
        version = CURRENT_NETWORK_VERSION(2) if mosaics else CURRENT_NETWORK_VERSION(1)
        data = NemConnect.createData(0x101, senderPublicKey, timeStamp, version)
        msgFee = 0 if len(message) == 0 else max(1, len(message) / 16) * 2
        fee = mosaicsFee if mosaics else NemConnect.calcMinFee(amount / 1000000)
        totalFee = (msgFee + fee)
        totalFee *= 1000000
        custom = {
            'recipient': recipientCompressedKey.replace('-', ''),
            'amount': amount,
            'fee': totalFee,
            'message': {'type': 1, 'payload': hexlify(message)}
        }
        if mosaics:
            custom['mosaics'] = mosaics
            print "Attached mosaic:", custom['mosaics']
        entity = dict(data.items() + custom.items())
        return entity

    def _constructImportanceTransfer(self, senderPublicKey, remotePublicKey, doAssign):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x801, senderPublicKey, timeStamp)
        custom = {
            'mode': 1 if doAssign else 2,
            'remoteAccount': remotePublicKey,
            'fee': 8000000,
        }
        entity = dict(data.items() + custom.items())
        return entity

    def _constructModification(self, senderPublicKey, cosignatories):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1001, senderPublicKey, timeStamp)
        custom = {
            'fee': 2 * (5000000 + 3000000 * (len(cosignatories))),
            'modifications': [
                {'modificationType': 2, 'cosignatoryAccount': publicKey}
                for publicKey in cosignatories
                ]
        }
        entity = dict(data.items() + custom.items())
        return entity

    def _constructNamespace(self, senderPublicKey, namespaceFqn):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x2001, senderPublicKey, timeStamp)
        parts = namespaceFqn.split('.')
        rental = 50000 if len(parts) == 1 else 5000
        custom = {
            'rentalFeeSink': CURRENT_NAMESPACE_SINK,
            'fee': 2 * 3 * 18 * 1000000,
            'rentalFee': rental * 1000000,
            'newPart': parts[-1],
        }
        if len(parts) > 1:
            custom['parent'] = '.'.join(parts[:-1])
        entity = dict(data.items() + custom.items())
        return entity

    @staticmethod
    def parseMosaicFqn(mosaicFqn):
        if " * " in mosaicFqn:
            return mosaicFqn.split(" * ")
        else:
            parts = mosaicFqn.split('.')
            return ('.'.join(parts[:-1]), parts[-1])

    def _constructMosaic(self, senderPublicKey, mosaicFqn, description, props):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x4001, senderPublicKey, timeStamp)

        namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(mosaicFqn)
        custom = {
            'mosaicDefinition': {
                'creator': senderPublicKey,
                'id': {
                    'namespaceId': namespaceFqn,
                    'name': mosaicName
                },
                'description': description,
                'properties': [
                    {'name': 'divisibility', 'value': str(props['divisibility'])},
                    {'name': 'initialSupply', 'value': str(props['initialSupply'])},
                    {'name': 'supplyMutable', 'value': str(props['supplyMutable'])},
                    {'name': 'transferable', 'value': str(props['transferable'])}
                ],
            },
            'creationFeeSink': CURRENT_MOSAIC_SINK,
            'creationFee': 50000 * 1000000,
            'fee': 2 * 3 * 18 * 1000000
        }
        if 'levy' in props:
            levyFqn = props['levy']['mosaicFqn']
            namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(levyFqn)

            custom['mosaicDefinition']['levy'] = {
                "type": props['levy']['type'],
                "recipient": props['levy']['recipient'].replace('-', ''),
                "mosaicId": {
                    'namespaceId': namespaceFqn,
                    'name': mosaicName
                },
                "fee": props['levy']['fee']
            }
        entity = dict(data.items() + custom.items())
        return entity

    def _constructMosaicSupply(self, senderPublicKey, mosaicFqn, supplyType, supplyDelta):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x4002, senderPublicKey, timeStamp)

        namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(mosaicFqn)
        custom = {
            'mosaicId': {
                'namespaceId': namespaceFqn,
                'name': mosaicName
            },
            'supplyType': supplyType,
            'delta': int(supplyDelta),
            'fee': 2 * 3 * 18 * 1000000
        }
        entity = dict(data.items() + custom.items())
        return entity

    def _prepare(self, entity):
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def _multisigWrapper(self, senderPublicKey, entity):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1004, senderPublicKey, timeStamp)
        custom = {
            'fee': 18000000,
            'otherTrans': entity
        }
        entity = dict(data.items() + custom.items())
        print " {+} multisig wrapped"
        return entity

    @staticmethod
    def calcXemEquivalent(amount, q, sup, divi):
        if sup == 0:
            return 0

        multiplier = amount  # int(self.transferAmount.get()) * 1000000
        equivalent = 8999999999 * q * multiplier / sup / (10 ** (divi + 6))
        return equivalent

    def calculateMosaicsFee(self, amount, mosaics):
        data = {'fee': 0, 'mosaics': []}
        for m in mosaics:
            quantity = m[1]
            mosaicFqn = m[0]
            namespaceFqn,mosaicName = NemConnect.parseMosaicFqn(mosaicFqn)
            ok, j = self.mosaicDefinition(namespaceFqn + ' * ' + mosaicName)
            if not ok:
                return ok, j
            divisibility = int((x for x in j['properties'] if x['name'] == 'divisibility').next()['value'])

            ok, j = self.mosaicSupply(namespaceFqn + ' * ' + mosaicName)
            if not ok:
                return ok, j

            supply = int(j['supply'])

            numNem = NemConnect.calcXemEquivalent(amount, quantity, supply, divisibility)
            data['fee'] += NemConnect.calcMinFee(numNem)
            data['mosaics'].append(
                {
                    'mosaicId': {
                        'namespaceId': namespaceFqn,
                        'name': mosaicName
                    },
                    'quantity': quantity
                }
            )
        data['fee'] = data['fee'] * 5 / 4
        return True, data

    def prepareTransfer(self, senderPublicKey, multisigPublicKey, recipientCompressedKey, amount, message, mosaics):
        mosaicsFee = 0
        if mosaics:
            ok, j = self.calculateMosaicsFee(amount, mosaics)
            if not ok:
                return ok, j
            mosaicsFee = j['fee']
            mosaics = j['mosaics']

        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructTransfer(actualSender, recipientCompressedKey, amount, message, mosaics, mosaicsFee)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareImportanceTransfer(self, senderPublicKey, multisigPublicKey, remotePublicKey, doAssign):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructImportanceTransfer(actualSender, remotePublicKey, doAssign)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareProvisionNamespace(self, senderPublicKey, multisigPublicKey, namespaceFqn):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructNamespace(actualSender, namespaceFqn)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareMosaicCreation(self, senderPublicKey, multisigPublicKey, mosaicFqn, description, props):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructMosaic(actualSender, mosaicFqn, description, props)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def prepareMosaicSupply(self, senderPublicKey, multisigPublicKey, mosaicFqn, supplyType, quantity):
        actualSender = multisigPublicKey or senderPublicKey
        entity = self._constructMosaicSupply(actualSender, mosaicFqn, supplyType, quantity)
        if multisigPublicKey:
            entity = self._multisigWrapper(senderPublicKey, entity)
        return self._prepare(entity)

    def multisigCreatePrepare(self, senderPublicKey, cosignatories):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1001, senderPublicKey, timeStamp)
        custom = {
            'fee': 2 * (5000000 + 3000000 * (len(cosignatories))),
            'modifications': [
                {'modificationType': 1, 'cosignatoryAccount': publicKey}
                for publicKey in cosignatories
                ]
        }
        entity = dict(data.items() + custom.items())
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def multisigModificationPrepare(self, senderPublicKey, multisig, cosignatories):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1004, senderPublicKey, timeStamp)
        transfer = self.constructModification(multisig, cosignatories)
        custom = {
            'fee': 6000000 * (len(cosignatories) + 1),
            'otherTrans': transfer
        }
        entity = dict(data.items() + custom.items())
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def multisigSignaturePrepare(self, senderPublicKey, multisigAddress, txHash):
        timeStamp = self.getTimeStamp()
        data = NemConnect.createData(0x1002, senderPublicKey, timeStamp)
        custom = {
            'fee': 2 * 3000000,
            'otherHash': {'data': txHash},
            'otherAccount': multisigAddress
        }
        entity = dict(data.items() + custom.items())
        r = self.sendPost('transaction/prepare', entity)
        return r.ok, r.json()

    def transferAnnounce(self, transferData, transferSignature):
        data = {'data': transferData,
                'signature': transferSignature
                }
        r = self.sendPost('transaction/announce', data)
        return r.ok, r.json()

    def sendGet(self, callName, data):
        headers = {'Content-type': 'application/json'}
        uri = 'http://' + self.address + ':' + str(self.port) + '/' + callName
        return requests.get(uri, params=data, headers=headers, timeout=10)

    def sendPost(self, callName, data):
        headers = {'Content-type': 'application/json'}
        uri = 'http://' + self.address + ':' + str(self.port) + '/' + callName
        return requests.post(uri, data=json.dumps(data), headers=headers, timeout=10)

#CURRENT_MOSAIC_SINK = 'MBMOSAICOD4F54EE5CDMR23CCBGOAM2XSKYHTOJD' #CURRENT_NAMESPACE_SINK = 'MAMESPACEWH4MKFMBCVFERDPOOP4FK7MTCZTG5E7' #def CURRENT_NETWORK_VERSION(ver): #    return (0x60000000 | ver) # int(self.transferAmount.get()) * 1000000