def FromJson(jsn, isMultiSig=True): try: parsed = json.loads(jsn) if parsed['type'] == 'Neo.Core.ContractTransaction': verifiable = ContractTransaction() ms = MemoryStream(binascii.unhexlify(parsed['hex'])) r = BinaryReader(ms) verifiable.DeserializeUnsigned(r) context = ContractParametersContext(verifiable, isMultiSig=isMultiSig) for key, value in parsed['items'].items(): if "0x" in key: key = key[2:] key = key.encode() parameterbytes = [] for pt in value['parameters']: if pt['type'] == 'Signature': parameterbytes.append(0) contract = Contract.Create(value['script'], parameterbytes, key) context.ContextItems[key] = ContextItem(contract) if 'signatures' in value: context.ContextItems[key].Signatures = value[ 'signatures'] return context else: raise ("Unsupported transaction type in JSON") except Exception as e: logger.error( "Failed to import ContractParametersContext from JSON: {}". format(e))
def SplitUnspentCoin(wallet, args, prompt_passwd=True): """ example ``wallet split Ab8RGQEWetkhVqXjPHeGN9LJdbhaFLyUXz neo 1 100`` this would split the second unspent neo vin into 100 vouts :param wallet: :param args (list): A list of arguments as [Address, asset type, unspent index, divisions] :return: bool """ try: addr = wallet.ToScriptHash(args[0]) asset = get_asset_id(wallet, args[1]) index = int(args[2]) divisions = int(args[3]) except Exception as e: logger.info("Invalid arguments specified: %s " % e) return None try: unspentItem = wallet.FindUnspentCoinsByAsset(asset, from_addr=addr)[index] except Exception as e: logger.info( "Could not find unspent item for asset with index %s %s : %s" % (asset, index, e)) return None outputs = split_to_vouts(asset, addr, unspentItem.Output.Value, divisions) contract_tx = ContractTransaction(outputs=outputs, inputs=[unspentItem.Reference]) ctx = ContractParametersContext(contract_tx) wallet.Sign(ctx) print("Splitting: %s " % json.dumps(contract_tx.ToJson(), indent=4)) if prompt_passwd: passwd = prompt("[Password]> ", is_password=True) if not wallet.ValidatePassword(passwd): print("incorrect password") return None if ctx.Completed: contract_tx.scripts = ctx.GetScripts() relayed = NodeLeader.Instance().Relay(contract_tx) if relayed: wallet.SaveTransaction(contract_tx) print("Relayed Tx: %s " % contract_tx.Hash.ToString()) return contract_tx else: print("Could not relay tx %s " % contract_tx.Hash.ToString()) return None
def _generate_tx(self): wallet = self.GetWallet1() output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash, Value=Fixed8.One(), script_hash=LeaderTestCase.wallet_1_script_hash) contract_tx = ContractTransaction(outputs=[output]) wallet.MakeTransaction(contract_tx) ctx = ContractParametersContext(contract_tx) wallet.Sign(ctx) contract_tx.scripts = ctx.GetScripts() return contract_tx
def test_9_send_neo_tx(self): wallet = self.GetWallet1() tx = ContractTransaction() tx.outputs = [TransactionOutput(Blockchain.SystemShare().Hash, Fixed8.FromDecimal(10.0), self.import_watch_addr)] tx = wallet.MakeTransaction(tx) cpc = ContractParametersContext(tx) wallet.Sign(cpc) tx.scripts = cpc.GetScripts() result = NodeLeader.Instance().Relay(tx) self.assertEqual(result, True)
def construct_tx(): assetId=get_asset_id(asset_type) scripthash_to=ToScriptHash(address_to) scripthash_from=ToScriptHash(address_from) f8amount_change = Fixed8.TryParse(change, require_positive=True) f8amount = Fixed8.TryParse(amount, require_positive=True) preHash=UInt256(data=binascii.unhexlify(hex_reverse(input_txid))) input_0=TransactionInput(prevHash=preHash,prevIndex=preIndex) output_0 = TransactionOutput(AssetId=assetId, Value=f8amount_change, script_hash=scripthash_from) output_1 = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) data=hex_reverse(scripthash_from.ToString()) tx = ContractTransaction(outputs=[output_0,output_1],inputs=[input_0]) tx.Attributes=[TransactionAttribute(usage=TransactionAttributeUsage.Script, data=bytearray.fromhex(data))] return tx
def parse_send_many_params(self, params): if type(params[0]) is not list: raise JsonRpcError(-32602, "Invalid params") if len(params) not in [1, 2, 3]: raise JsonRpcError(-32602, "Invalid params") output = [] for info in params[0]: asset = get_asset_id(self.wallet, info['asset']) if not type(asset) is UInt256: raise JsonRpcError(-32602, "Invalid params") address = info["address"] try: address = self.wallet.ToScriptHash(address) except Exception: raise JsonRpcError(-32602, "Invalid params") amount = Fixed8.TryParse(info["value"], require_positive=True) if not amount or float(info["value"]) == 0: raise JsonRpcError(-32602, "Invalid params") tx_output = TransactionOutput(AssetId=asset, Value=amount, script_hash=address) output.append(tx_output) contract_tx = ContractTransaction(outputs=output) fee = Fixed8.TryParse(params[1]) if len(params) >= 2 else Fixed8.Zero() if fee < Fixed8.Zero(): raise JsonRpcError(-32602, "Invalid params") change_addr_sh = None if len(params) >= 3: change_addr = params[2] try: change_addr_sh = self.wallet.ToScriptHash(change_addr) except Exception: raise JsonRpcError(-32602, "Invalid params") return contract_tx, fee, change_addr_sh
def _generate_tx(self, amount): wallet = self.GetWallet1() output = TransactionOutput( AssetId=Blockchain.SystemShare().Hash, Value=amount, script_hash=LeaderTestCase.wallet_1_script_hash) contract_tx = ContractTransaction(outputs=[output]) try: wallet.MakeTransaction(contract_tx) except ValueError: pass ctx = ContractParametersContext(contract_tx) wallet.Sign(ctx) contract_tx.scripts = ctx.GetScripts() return contract_tx
def send_to_address(self, params): asset, address, amount, fee = self.parse_send_params(params) standard_contract = self.wallet.GetStandardAddress() signer_contract = self.wallet.GetContract(standard_contract) output = TransactionOutput(AssetId=asset, Value=amount, script_hash=address) contract_tx = ContractTransaction(outputs=[output]) tx = self.wallet.MakeTransaction(tx=contract_tx, change_address=None, fee=fee) if tx is None: raise JsonRpcError(-300, "Insufficient funds") data = standard_contract.Data tx.Attributes = [ TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data) ] context = ContractParametersContext( tx, isMultiSig=signer_contract.IsMultiSigContract) self.wallet.Sign(context) if context.Completed: tx.scripts = context.GetScripts() NodeLeader.Instance().Relay(tx) return tx.ToJson() else: return context.ToJson()
def send_neo(wallet, address_from, address_to, amount): assetId = None assetId = Blockchain.Default().SystemShare().Hash scripthash_to = wallet.ToScriptHash(address_to) scripthash_from = wallet.ToScriptHash(address_from) f8amount = Fixed8.TryParse(amount) if f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0: raise Exception("incorrect amount precision") fee = Fixed8.Zero() output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) tx = ContractTransaction(outputs=[output]) ttx = wallet.MakeTransaction(tx=tx, change_address=None, fee=fee, from_addr=scripthash_from) if ttx is None: raise Exception("insufficient funds, were funds already moved from multi-sig contract?") context = ContractParametersContext(tx, isMultiSig=True) wallet.Sign(context) if context.Completed: raise Exception("Something went wrong, multi-sig transaction failed") else: print("Transaction initiated") return json.dumps(context.ToJson(), separators=(',', ':'))
def parse_send_from_params(self, params): if len(params) not in [4, 5, 6]: raise JsonRpcError(-32602, "Invalid params") asset_id = get_asset_id(self.wallet, params[0]) if not type(asset_id) is UInt256: raise JsonRpcError(-32602, "Invalid params") address_from = params[1] try: address_from_sh = self.wallet.ToScriptHash(address_from) except Exception: raise JsonRpcError(-32602, "Invalid params") address_to = params[2] try: address_to_sh = self.wallet.ToScriptHash(address_to) except Exception: raise JsonRpcError(-32602, "Invalid params") amount = Fixed8.TryParse(params[3], require_positive=True) if not amount or float(params[3]) == 0: raise JsonRpcError(-32602, "Invalid params") output = TransactionOutput(AssetId=asset_id, Value=amount, script_hash=address_to_sh) contract_tx = ContractTransaction(outputs=[output]) fee = Fixed8.TryParse(params[4]) if len(params) >= 5 else Fixed8.Zero() if fee < Fixed8.Zero(): raise JsonRpcError(-32602, "Invalid params") change_addr_sh = None if len(params) >= 6: change_addr = params[5] try: change_addr_sh = self.wallet.ToScriptHash(change_addr) except Exception: raise JsonRpcError(-32602, "Invalid params") return contract_tx, address_from_sh, fee, change_addr_sh
def _make_tx(self, addr_to): """ process transaction """ output1 = TransactionOutput( AssetId = Blockchain.SystemCoin().Hash, # hash of the Gas transaction Value = Fixed8.FromDecimal(2000), # this is how much gas each request will provide script_hash = addr_to # address to send the Gas to ) output2 = TransactionOutput( AssetId = Blockchain.SystemShare().Hash, # hash of the NEO token transaction Value = Fixed8.FromDecimal(100), # this is how much NEO each request will provide script_hash = addr_to # address to send the NEO tokens too ) contract_tx = ContractTransaction() # creates an instance of the transaction contract_tx.outputs = [output1, output2] # outputs the data from the transaction contract_tx = self.wallet.MakeTransaction(contract_tx) # processes transaction print("tx to json: %s " % json.dumps(contract_tx.ToJson(), indent=4)) context = ContractParametersContext(contract_tx, isMultiSig=False) # getting the contract context (listed above) self.wallet.Sign(context) # signs the contract if context.Completed: contract_tx.scripts = context.GetScripts() # gets the script hashes from the context self.wallet.SaveTransaction(contract_tx) # update the state of the coins in the wallet # print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4)) relayed = NodeLeader.Instance().Relay(contract_tx) # relay the transaction to this instance of the node leader if relayed: # if tx relay was successful, inform the user and return the contract transaction print("Relayed Tx: %s " % contract_tx.Hash.ToString()) return contract_tx else: print("Could not relay tx %s " % contract_tx.Hash.ToString()) else: print("Transaction initiated, but the signature is incomplete") print(json.dumps(context.ToJson(), separators=(',', ':'))) return False return False
def _make_tx(self, addr_to): output1 = TransactionOutput( AssetId = Blockchain.SystemCoin().Hash, Value = Fixed8.FromDecimal(2000), script_hash = addr_to ) output2 = TransactionOutput( AssetId = Blockchain.SystemShare().Hash, Value = Fixed8.FromDecimal(100), script_hash = addr_to ) contract_tx = ContractTransaction() contract_tx.outputs = [output1, output2] contract_tx = self.wallet.MakeTransaction(contract_tx) print("tx to json: %s " % json.dumps(contract_tx.ToJson(), indent=4)) context = ContractParametersContext(contract_tx, isMultiSig=False) self.wallet.Sign(context) if context.Completed: contract_tx.scripts = context.GetScripts() self.wallet.SaveTransaction(contract_tx) # print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4)) relayed = NodeLeader.Instance().Relay(contract_tx) if relayed: print("Relayed Tx: %s " % contract_tx.Hash.ToString()) return contract_tx else: print("Could not relay tx %s " % contract_tx.Hash.ToString()) else: print("Transaction initiated, but the signature is incomplete") print(json.dumps(context.ToJson(), separators=(',', ':'))) return False return False
def deploy(from_addr, bytecode, contract_params, return_type, details): response = requests.post('http://127.0.0.1:20332', json={ 'jsonrpc': '2.0', 'id': 1, 'method': 'mw_construct_deploy_tx', 'params': [{ 'from_addr': from_addr, 'bin': bytecode, 'contract_params': contract_params, 'return_type': return_type, 'details': details, }] }).json() if 'error' in response: print(response['error']['message']) return context = response['result']['context'] binary_tx = response['result']['tx'] contract_hash = response['result']['hash'] tx = ContractTransaction.DeserializeFromBufer( binascii.unhexlify(binary_tx)) scripts = requests.post('http://127.0.0.1:5000/neo_sign/', json={ 'binary_tx': binary_tx }).json() tx.scripts = [ Witness( x['invocation'].encode(), x['verification'].encode(), ) for x in scripts ] ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() signed_tx = ms.ToArray() response = requests.post('http://127.0.0.1:20332', json={ 'jsonrpc': '2.0', 'id': 1, 'method': 'sendrawtransaction', 'params': [ signed_tx.decode(), ] }).json() print('contract hash:', contract_hash) print(response)
def construct_send_basic(wallet, arguments): if not wallet: print("please open a wallet") return False if len(arguments) < 3: print("Not enough arguments") return False arguments, from_address = get_from_addr(arguments) arguments, priority_fee = get_fee(arguments) arguments, user_tx_attributes = get_tx_attr_from_args(arguments) arguments, owners = get_owners_from_params(arguments) to_send = get_arg(arguments) address_to = get_arg(arguments, 1) amount = get_arg(arguments, 2) assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") return False scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: logger.debug("invalid address") return False scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if scripthash_from is None: logger.debug("invalid address") return False # if this is a token, we will use a different # transfer mechanism if type(assetId) is NEP5Token: return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), tx_attributes=user_tx_attributes) f8amount = get_asset_amount(amount, assetId) if f8amount is False: logger.debug("invalid amount") return False if float(amount) == 0: print("amount cannot be 0") return False fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee if fee is False: logger.debug("invalid fee") return False output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) contract_tx = ContractTransaction(outputs=[output]) return [contract_tx, scripthash_from, fee, owners, user_tx_attributes]
def send(addr_from, addr_to, asset, amount): response = requests.post('http://127.0.0.1:20332', json={ 'jsonrpc': '2.0', 'id': 1, 'method': 'mw_construct_send_tx', 'params': { 'from': addr_from, 'to': addr_to, 'asset': asset, 'amount': amount, } }).json() print(response) context = response['result']['context'] binary_tx = response['result']['tx'] tx = ContractTransaction.DeserializeFromBufer( binascii.unhexlify(binary_tx)) scripts = requests.post('http://127.0.0.1:5000/neo_sign/', json={ 'binary_tx': binary_tx, 'address': addr_from }).json() print('scripts', scripts) tx.scripts = [ Witness( x['invocation'].encode(), x['verification'].encode(), ) for x in scripts ] print(scripts) ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() signed_tx = ms.ToArray() print(tx.ToJson()) # print('does not send: return') ; return response = requests.post('http://127.0.0.1:20332', json={ 'jsonrpc': '2.0', 'id': 1, 'method': 'sendrawtransaction', 'params': [ signed_tx.decode(), ] }).json() print(response)
def create_withdraw_tx(wallet, hold): f8amount = Fixed8(hold.Amount) coinRef = CoinReference(prev_hash=hold.TXHash, prev_index=hold.Index) requested_vins = [coinRef] use_vins_for_asset = [requested_vins, hold.AssetId] output = TransactionOutput(AssetId=hold.AssetId, Value=f8amount, script_hash=hold.OutputHash) withdraw_tx = ContractTransaction(outputs=[output]) withdraw_tx.withdraw_hold = hold return wallet.MakeTransaction(tx=withdraw_tx, change_address=hold.InputHash, fee=Fixed8.Zero(), from_addr=hold.InputHash, use_standard=False, watch_only_val=64, use_vins_for_asset=use_vins_for_asset)
def test_9_send_neo_tx(self): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): wallet = self.GetWallet1() tx = ContractTransaction() tx.outputs = [TransactionOutput(Blockchain.SystemShare().Hash, Fixed8.FromDecimal(10.0), self.import_watch_addr)] try: tx = wallet.MakeTransaction(tx) except (ValueError): pass cpc = ContractParametersContext(tx) wallet.Sign(cpc) tx.scripts = cpc.GetScripts() nodemgr = NodeManager() # we need at least 1 node for relay to be mocked nodemgr.nodes = [NeoNode(object, object)] result = nodemgr.relay(tx) self.assertEqual(result, True)
def sign_context(binary_tx, private): wallet = Wallet(b'', b'0' * 32, True) wallet.CreateKey(binascii.unhexlify(private)) script_hash = WalletContract.CreateSignatureContract( list(wallet._keys.values())[0].PublicKey) wallet._contracts[script_hash.ScriptHash.ToBytes()] = script_hash tx = ContractTransaction.DeserializeFromBufer( binascii.unhexlify(binary_tx)) context = ContractParametersContext(tx, isMultiSig=False) context.ScriptHashes = [script_hash.ScriptHash] wallet.Sign(context) return [x.ToJson() for x in context.GetScripts()]
def deploy(self, contract_params='0710', return_type='05'): self.compile() from_addr = NETWORKS[self.contract.network.name]['address'] bytecode = self.neo_contract_crowdsale.bytecode neo_int = NeoInt(self.contract.network.name) print('from address', from_addr) details = { 'name': 'WISH', 'description': 'NEO smart contract', 'email': '*****@*****.**', 'version': '1', 'author': 'MyWish' } param_list = { 'from_addr': from_addr, 'bin': bytecode, 'needs_storage': True, 'needs_dynamic_invoke': False, 'contract_params': contract_params, 'return_type': return_type, 'details': details, } response = neo_int.mw_construct_deploy_tx(param_list) print('construct response', response, flush=True) binary_tx = response['tx'] contract_hash = response['hash'] tx = ContractTransaction.DeserializeFromBufer( binascii.unhexlify(binary_tx)) tx = sign_neo_transaction(tx, binary_tx, from_addr) print('after sign', tx.ToJson()['txid'], flush=True) ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() signed_tx = ms.ToArray() print('full tx:', flush=True) print(signed_tx, flush=True) result = neo_int.sendrawtransaction(signed_tx.decode()) print(result, flush=True) if not result: raise TxFail() print('contract hash:', contract_hash) print('result of send raw transaction: ', result) self.neo_contract_crowdsale.address = contract_hash self.neo_contract_crowdsale.tx_hash = tx.ToJson()['txid'] self.neo_contract_crowdsale.save()
def msg_deployed(self, message): neo_int = NeoInt(self.contract.network.name) from_addr = NETWORKS[self.contract.network.name]['address'] param_list = { 'from_addr': from_addr, 'contract_params': [{ 'type': str(ContractParameterType.String), 'value': 'init' }, { 'type': str(ContractParameterType.Array), 'value': [] }], 'addr': self.neo_contract_crowdsale.address, } response = neo_int.mw_construct_invoke_tx(param_list) binary_tx = response['tx'] tx = ContractTransaction.DeserializeFromBufer( binascii.unhexlify(binary_tx)) tx = sign_neo_transaction(tx, binary_tx, from_addr) print('after sign', tx.ToJson()['txid']) ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() signed_tx = ms.ToArray() print('signed_tx', signed_tx) result = neo_int.sendrawtransaction(signed_tx.decode()) print(result, flush=True) if not result: raise TxFail() print('result of send raw transaction: ', result) self.contract.save() self.neo_contract_crowdsale.tx_hash = tx.ToJson()['txid'] self.neo_contract_crowdsale.save() return
def construct_send_many(wallet, arguments): if not wallet: print("please open a wallet") return False if len(arguments) is 0: print("Not enough arguments") return False outgoing = get_arg(arguments, convert_to_int=True) if outgoing is None: print("invalid outgoing number") return False if outgoing < 1: print("outgoing number must be >= 1") return False arguments, from_address = get_from_addr(arguments) arguments, change_address = get_change_addr(arguments) arguments, priority_fee = get_fee(arguments) arguments, owners = get_owners_from_params(arguments) arguments, user_tx_attributes = get_tx_attr_from_args(arguments) output = [] for i in range(outgoing): print('Outgoing Number ', i + 1) to_send = prompt("Asset to send: ") assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") return False if type(assetId) is NEP5Token: print('Sendmany does not support NEP5 tokens') return False address_to = prompt("Address to: ") scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: logger.debug("invalid address") return False amount = prompt("Amount to send: ") f8amount = get_asset_amount(amount, assetId) if f8amount is False: logger.debug("invalid amount") return False if float(amount) == 0: print("amount cannot be 0") return False tx_output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) output.append(tx_output) contract_tx = ContractTransaction(outputs=output) scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if scripthash_from is None: logger.debug("invalid address") return False scripthash_change = None if change_address is not None: scripthash_change = lookup_addr_str(wallet, change_address) if scripthash_change is None: logger.debug("invalid address") return False fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee if fee is False: logger.debug("invalid fee") return False print("sending with fee: %s " % fee.ToString()) return [ contract_tx, scripthash_from, scripthash_change, fee, owners, user_tx_attributes ]
def DeserializeFrom(reader): """ Deserialize full object. Args: reader (neo.IO.BinaryReader): Returns: Transaction: """ ttype = ord(reader.ReadByte()) tx = None from neo.Core.TX.RegisterTransaction import RegisterTransaction from neo.Core.TX.IssueTransaction import IssueTransaction from neo.Core.TX.ClaimTransaction import ClaimTransaction from neo.Core.TX.MinerTransaction import MinerTransaction from neo.Core.TX.PublishTransaction import PublishTransaction from neo.Core.TX.InvocationTransaction import InvocationTransaction from neo.Core.TX.EnrollmentTransaction import EnrollmentTransaction from neo.Core.TX.StateTransaction import StateTransaction from neo.Core.TX.Transaction import ContractTransaction if ttype == int.from_bytes(TransactionType.RegisterTransaction, 'little'): tx = RegisterTransaction() elif ttype == int.from_bytes(TransactionType.MinerTransaction, 'little'): tx = MinerTransaction() elif ttype == int.from_bytes(TransactionType.IssueTransaction, 'little'): tx = IssueTransaction() elif ttype == int.from_bytes(TransactionType.ClaimTransaction, 'little'): tx = ClaimTransaction() elif ttype == int.from_bytes(TransactionType.PublishTransaction, 'little'): tx = PublishTransaction() elif ttype == int.from_bytes(TransactionType.InvocationTransaction, 'little'): tx = InvocationTransaction() elif ttype == int.from_bytes(TransactionType.EnrollmentTransaction, 'little'): tx = EnrollmentTransaction() elif ttype == int.from_bytes(TransactionType.StateTransaction, 'little'): tx = StateTransaction() elif ttype == int.from_bytes(TransactionType.ContractTransaction, 'little'): tx = ContractTransaction() else: tx = Transaction() tx.Type = ttype tx.DeserializeUnsignedWithoutType(reader) tx.scripts = [] byt = reader.ReadVarInt() if byt > 0: for i in range(0, byt): witness = Witness() witness.Deserialize(reader) tx.scripts.append(witness) tx.OnDeserialized() return tx
def construct_send_tx(wallet, arguments): from_address = arguments['from'] to_send = arguments['asset'] address_to = arguments['to'] amount = arguments['amount'] user_tx_attributes = arguments.get('attrs', []) assetId = get_asset_id(wallet, to_send) if assetId is None: raise Exception("Asset id not found") scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: raise Exception("invalid address") scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if type(assetId) is NEP5Token: raise Exception("cannot transfer token in this version") f8amount = Fixed8.TryParse(amount, require_positive=True) if f8amount is None: raise Exception("invalid amount format") if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0: raise Exception("incorrect amount precision") fee = Fixed8.Zero() output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) tx = ContractTransaction(outputs=[output]) ttx = wallet.MakeTransaction(tx=tx, fee=fee, from_addr=scripthash_from) if ttx is None: raise Exception("no funds") standard_contract = wallet.GetStandardAddress() if scripthash_from is not None: signer_contract = wallet.GetContract(scripthash_from) else: signer_contract = wallet.GetContract(standard_contract) if not signer_contract.IsMultiSigContract: data = standard_contract.Data tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data)] # insert any additional user specified tx attributes tx.Attributes = tx.Attributes + user_tx_attributes context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract) logger.info(context.ToJson()) logger.info('*'*60) logger.info(tx.ToJson()) # import pdb # pdb.set_trace() ms = StreamManager.GetStream() writer = BinaryWriter(ms) tx.Serialize(writer) ms.flush() binary_tx = ms.ToArray() print(tx) return {'context': context.ToJson(), 'tx': binary_tx.decode()}
def construct_and_send(prompter, wallet, arguments): try: if not wallet: print("please open a wallet") return if len(arguments) < 3: print("Not enough arguments") return to_send = get_arg(arguments) address_to = get_arg(arguments, 1) amount = get_arg(arguments, 2) address_from = get_arg(arguments, 3) assetId = None if to_send.lower() == 'neo': assetId = Blockchain.Default().SystemShare().Hash elif to_send.lower() == 'gas': assetId = Blockchain.Default().SystemCoin().Hash elif Blockchain.Default().GetAssetState(to_send): assetId = Blockchain.Default().GetAssetState(to_send).AssetId scripthash = wallet.ToScriptHash(address_to) if scripthash is None: print("invalid address") return f8amount = Fixed8.TryParse(amount) if f8amount is None: print("invalid amount format") return if f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0: print("incorrect amount precision") return fee = Fixed8.Zero() if get_arg(arguments, 3): fee = Fixed8.TryParse(get_arg(arguments, 3)) output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash) tx = ContractTransaction(outputs=[output]) ttx = wallet.MakeTransaction(tx=tx, change_address=None, fee=fee) if ttx is None: print("insufficient funds") return passwd = prompt("[Password]> ", completer=prompter.completer, is_password=True, history=prompter.history, get_bottom_toolbar_tokens=prompter.get_bottom_toolbar, style=prompter.token_style) if not wallet.ValidatePassword(passwd): print("incorrect password") return context = ContractParametersContext(tx) wallet.Sign(context) if context.Completed: tx.scripts = context.GetScripts() wallet.SaveTransaction(tx) relayed = NodeLeader.Instance().Relay(tx) if relayed: print("Relayed Tx: %s " % tx.Hash.ToString()) else: print("Could not relay tx %s " % tx.Hash.ToString()) else: print("Could not sign transaction") return except Exception as e: print("could not send: %s " % e) traceback.print_stack() traceback.print_exc()
def do_send(self, arguments): try: if not self.Wallet: print("please open a wallet") return if len(arguments) < 3: print("Not enough arguments") return to_send = get_arg(arguments) address = get_arg(arguments, 1) amount = get_arg(arguments, 2) assetId = None if to_send.lower() == 'neo': assetId = Blockchain.Default().SystemShare().Hash elif to_send.lower() == 'gas': assetId = Blockchain.Default().SystemCoin().Hash elif Blockchain.Default().GetAssetState(to_send): assetId = Blockchain.Default().GetAssetState(to_send).AssetId scripthash = self.Wallet.ToScriptHash(address) if scripthash is None: print("invalid address") return f8amount = Fixed8.TryParse(amount) if f8amount is None: print("invalid amount format") return if f8amount.value % pow( 10, 8 - Blockchain.Default().GetAssetState( assetId.ToBytes()).Precision) != 0: print("incorrect amount precision") return fee = Fixed8.Zero() if get_arg(arguments, 3): fee = Fixed8.TryParse(get_arg(arguments, 3)) output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash) tx = ContractTransaction(outputs=[output]) ttx = self.Wallet.MakeTransaction(tx=tx, change_address=None, fee=fee) if ttx is None: print("insufficient funds") return self._wallet_send_tx = ttx self._num_passwords_req = 1 self._gathered_passwords = [] self._gathering_password = True self._gather_password_action = self.do_send_created_tx except Exception as e: print("could not send: %s " % e) traceback.print_stack() traceback.print_exc()
def construct_send_many(wallet, arguments): if len(arguments) is 0: print("Please specify the required parameter") return outgoing = get_arg(arguments, convert_to_int=True) if outgoing is None: print("Invalid outgoing number") return if outgoing < 1: print("Outgoing number must be >= 1") return arguments, from_address = get_from_addr(arguments) arguments, change_address = get_change_addr(arguments) arguments, priority_fee = get_fee(arguments) arguments, owners = get_owners_from_params(arguments) arguments, user_tx_attributes = get_tx_attr_from_args(arguments) output = [] for i in range(outgoing): try: print('Outgoing Number ', i + 1) to_send = prompt("Asset to send: ") assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") return if type(assetId) is NEP5Token: print('sendmany does not support NEP5 tokens') return address_to = prompt("Address to: ") scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: logger.debug("invalid destination address") return amount = prompt("Amount to send: ") f8amount = get_asset_amount(amount, assetId) if f8amount is False: logger.debug("invalid amount") return if float(amount) == 0: print("Amount cannot be 0") return tx_output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) output.append(tx_output) except KeyboardInterrupt: print('Transaction cancelled') return contract_tx = ContractTransaction(outputs=output) scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if scripthash_from is None: logger.debug("invalid source address") return scripthash_change = None if change_address is not None: scripthash_change = lookup_addr_str(wallet, change_address) if scripthash_change is None: logger.debug("invalid change address") return fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee if fee is False: logger.debug("invalid fee") return print(f"Sending with fee: {fee.ToString()}") return [ contract_tx, scripthash_from, scripthash_change, fee, owners, user_tx_attributes ]
def construct_and_send(prompter, wallet, arguments, prompt_password=True): try: if not wallet: print("please open a wallet") return False if len(arguments) < 3: print("Not enough arguments") return False arguments, from_address = get_from_addr(arguments) arguments, user_tx_attributes = get_tx_attr_from_args(arguments) to_send = get_arg(arguments) address_to = get_arg(arguments, 1) amount = get_arg(arguments, 2) assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") return False scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: print("invalid address") return False scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) # if this is a token, we will use a different # transfer mechanism if type(assetId) is NEP5Token: return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), prompt_passwd=prompt_password) f8amount = Fixed8.TryParse(amount, require_positive=True) if f8amount is None: print("invalid amount format") return False if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0: print("incorrect amount precision") return False fee = Fixed8.Zero() output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) tx = ContractTransaction(outputs=[output]) ttx = wallet.MakeTransaction(tx=tx, change_address=None, fee=fee, from_addr=scripthash_from) if ttx is None: print("insufficient funds") return False if prompt_password: passwd = prompt("[Password]> ", is_password=True) if not wallet.ValidatePassword(passwd): print("incorrect password") return False standard_contract = wallet.GetStandardAddress() if scripthash_from is not None: signer_contract = wallet.GetContract(scripthash_from) else: signer_contract = wallet.GetContract(standard_contract) if not signer_contract.IsMultiSigContract: data = standard_contract.Data tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data)] # insert any additional user specified tx attributes tx.Attributes = tx.Attributes + user_tx_attributes context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract) wallet.Sign(context) if context.Completed: tx.scripts = context.GetScripts() # print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4)) relayed = NodeLeader.Instance().Relay(tx) if relayed: wallet.SaveTransaction(tx) print("Relayed Tx: %s " % tx.Hash.ToString()) return tx else: print("Could not relay tx %s " % tx.Hash.ToString()) else: print("Transaction initiated, but the signature is incomplete") print(json.dumps(context.ToJson(), separators=(',', ':'))) return False except Exception as e: print("could not send: %s " % e) traceback.print_stack() traceback.print_exc() return False
def construct_and_send(prompter, wallet, arguments, prompt_password=True): try: if not wallet: print("please open a wallet") return False if len(arguments) < 3: print("Not enough arguments") return False arguments, from_address = get_from_addr(arguments) arguments, user_tx_attributes = get_tx_attr_from_args(arguments) arguments, owners = get_owners_from_params(arguments) arguments, priority_fee = get_fee(arguments) to_send = get_arg(arguments) address_to = get_arg(arguments, 1) amount = get_arg(arguments, 2) assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") return False scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: print("invalid address") return False scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) # if this is a token, we will use a different # transfer mechanism if type(assetId) is NEP5Token: return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), prompt_passwd=prompt_password, tx_attributes=user_tx_attributes) f8amount = Fixed8.TryParse(amount, require_positive=True) if f8amount is None: print("invalid amount format") return False if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0: print("incorrect amount precision") return False fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee print("sending with fee: %s " % fee.ToString()) output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) tx = ContractTransaction(outputs=[output]) ttx = wallet.MakeTransaction(tx=tx, change_address=None, fee=fee, from_addr=scripthash_from) if ttx is None: print("insufficient funds") return False if prompt_password: passwd = prompt("[Password]> ", is_password=True) if not wallet.ValidatePassword(passwd): print("incorrect password") return False standard_contract = wallet.GetStandardAddress() if scripthash_from is not None: signer_contract = wallet.GetContract(scripthash_from) else: signer_contract = wallet.GetContract(standard_contract) if not signer_contract.IsMultiSigContract and owners is None: data = standard_contract.Data tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data)] # insert any additional user specified tx attributes tx.Attributes = tx.Attributes + user_tx_attributes if owners: owners = list(owners) for owner in owners: tx.Attributes.append( TransactionAttribute(usage=TransactionAttributeUsage.Script, data=owner)) context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract) wallet.Sign(context) if owners: owners = list(owners) gather_signatures(context, tx, owners) if context.Completed: tx.scripts = context.GetScripts() # print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4)) relayed = NodeLeader.Instance().Relay(tx) if relayed: wallet.SaveTransaction(tx) print("Relayed Tx: %s " % tx.Hash.ToString()) return tx else: print("Could not relay tx %s " % tx.Hash.ToString()) else: print("Transaction initiated, but the signature is incomplete") print(json.dumps(context.ToJson(), separators=(',', ':'))) return False except Exception as e: print("could not send: %s " % e) traceback.print_stack() traceback.print_exc() return False
def SplitUnspentCoin(wallet, asset_id, from_addr, index, divisions, fee=Fixed8.Zero()): """ Split unspent asset vins into several vouts Args: wallet (neo.Wallet): wallet to show unspent coins from. asset_id (UInt256): a bytearray (len 32) representing an asset on the blockchain. from_addr (UInt160): a bytearray (len 20) representing an address. index (int): index of the unspent vin to split divisions (int): number of vouts to create fee (Fixed8): A fee to be attached to the Transaction for network processing purposes. Returns: neo.Core.TX.Transaction.ContractTransaction: contract transaction created """ if wallet is None: print("Please open a wallet.") return unspent_items = wallet.FindUnspentCoinsByAsset(asset_id, from_addr=from_addr) if not unspent_items: print(f"No unspent assets matching the arguments.") return if index < len(unspent_items): unspent_item = unspent_items[index] else: print(f"unspent-items: {unspent_items}") print(f"Could not find unspent item for asset {asset_id} with index {index}") return outputs = split_to_vouts(asset_id, from_addr, unspent_item.Output.Value, divisions) # subtract a fee from the first vout if outputs[0].Value > fee: outputs[0].Value -= fee else: print("Fee could not be subtracted from outputs.") return contract_tx = ContractTransaction(outputs=outputs, inputs=[unspent_item.Reference]) ctx = ContractParametersContext(contract_tx) wallet.Sign(ctx) print("Splitting: %s " % json.dumps(contract_tx.ToJson(), indent=4)) try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Splitting cancelled") return if not wallet.ValidatePassword(passwd): print("incorrect password") return if ctx.Completed: contract_tx.scripts = ctx.GetScripts() relayed = NodeLeader.Instance().Relay(contract_tx) if relayed: wallet.SaveTransaction(contract_tx) print("Relayed Tx: %s " % contract_tx.Hash.ToString()) return contract_tx else: print("Could not relay tx %s " % contract_tx.Hash.ToString())
def example1(): neo_asset_id = Blockchain.GetSystemShare().Hash gas_asset_id = Blockchain.GetSystemCoin().Hash source_address = "AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3" source_script_hash = address_to_scripthash(source_address) destination_address = "Ad9A1xPbuA5YBFr1XPznDwBwQzdckAjCev" destination_script_hash = address_to_scripthash(destination_address) # Let's start with building a ContractTransaction # The constructor already sets the correct `Type` and `Version` fields, so we do not have to worry about that contract_tx = ContractTransaction() # the ContractTransaction type has no special data, so we do not have to do anything there # Next we can add Attributes if we want. Again the various types are described in point 4. of the main link above # We will add a simple "description" contract_tx.Attributes.append( TransactionAttribute(usage=TransactionAttributeUsage.Description, data="My raw contract transaction description")) # The next field we will set are the inputs. The inputs neo-python expects are of the type ``CoinReference`` # To create these inputs we will need the usual `PrevHash` and `PrevIndex` values. # You can get the required data by using e.g. the neoscan.io API: https://api.neoscan.io/docs/index.html#api-v1-get-3 # The `PrevHash` field equals to neoscan's `balance.unspent[index].txid` key, and `PrevIndex` comes from `balance.unspent[index].n` # It is up to the transaction creator to make sure that the sum of all input ``value`` fields is equal to or bigger than the amount that's intended to be send # The below values are taken from data out of the `neo-test1-w.wallet` fixture wallet (a wallet neo-python uses for internal testing) input1 = CoinReference(prev_hash=UInt256(data=binascii.unhexlify( '949354ea0a8b57dfee1e257a1aedd1e0eea2e5837de145e8da9c0f101bfccc8e')), prev_index=1) contract_tx.inputs = [input1] # Next we will create the outputs. # The above input has a value of 50. We will create 2 outputs. # 1 output for sending 3 NEO to a specific destination address send_to_destination_output = TransactionOutput( AssetId=neo_asset_id, Value=Fixed8.FromDecimal(3), script_hash=destination_script_hash) # and a second output for sending the change back to ourselves return_change_output = TransactionOutput(AssetId=neo_asset_id, Value=Fixed8.FromDecimal(47), script_hash=source_script_hash) contract_tx.outputs = [send_to_destination_output, return_change_output] # at this point we've build our unsigned transaction and it's time to sign it before we get the raw output that we can send to the network via RPC # we need to create a Wallet instance for helping us with signing wallet = UserWallet.Create('path', to_aes_key('mypassword'), generate_default_key=False) # if you have a WIF use the following # this WIF comes from the `neo-test1-w.wallet` fixture wallet private_key = KeyPair.PrivateKeyFromWIF( "Ky94Rq8rb1z8UzTthYmy1ApbZa9xsKTvQCiuGUZJZbaDJZdkvLRV") # if you have a NEP2 encrypted key use the following instead # private_key = KeyPair.PrivateKeyFromNEP2("NEP2 key string", "password string") # we add the key to our wallet wallet.CreateKey(private_key) # and now we're ready to sign context = ContractParametersContext(contract_tx) wallet.Sign(context) contract_tx.scripts = context.GetScripts() print(contract_tx.Hash.ToString()) raw_tx = contract_tx.ToArray()