Skip to content

Commit 7db54f4

Browse files
authored
Merge pull request #41 from CityOfZion/development
Merge CoZ Development into jseagrave21 Development
2 parents e41e950 + 173342a commit 7db54f4

File tree

5 files changed

+547
-149
lines changed

5 files changed

+547
-149
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project are documented in this file.
88
- Add ExtendedJsonRpcApi, Add ``getnodestate`` RPC extended method, Add ``gettxhistory`` RPC extended method
99
- Fix return types of ``claimGas`` function.
1010
- Update compiler version ``v0.5.4``
11+
- Adds ``sendmany`` feature to prompt.py, integrates with ``send`` feature, and adds provisions for sending with a negative fee and bad from_address
1112

1213
[0.8.1] 2018-10-06
1314
------------------

neo/Prompt/Commands/Send.py

Lines changed: 136 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from neo.Core.TX.TransactionAttribute import TransactionAttribute, TransactionAttributeUsage
44
from neo.SmartContract.ContractParameterContext import ContractParametersContext
55
from neo.Network.NodeLeader import NodeLeader
6-
from neo.Prompt.Utils import get_arg, get_from_addr, get_asset_id, lookup_addr_str, get_tx_attr_from_args, get_owners_from_params, get_fee
6+
from neo.Prompt.Utils import get_arg, get_from_addr, get_asset_id, lookup_addr_str, get_tx_attr_from_args, \
7+
get_owners_from_params, get_fee, get_change_addr, get_asset_amount
78
from neo.Prompt.Commands.Tokens import do_token_transfer, amount_from_string
89
from neo.Prompt.Commands.Invoke import gather_signatures
910
from neo.Wallets.NEP5Token import NEP5Token
@@ -12,87 +13,160 @@
1213
import json
1314
from prompt_toolkit import prompt
1415
import traceback
15-
16-
17-
def construct_and_send(prompter, wallet, arguments, prompt_password=True):
18-
try:
19-
if not wallet:
20-
print("please open a wallet")
21-
return False
22-
if len(arguments) < 3:
23-
print("Not enough arguments")
16+
from logzero import logger
17+
18+
19+
def construct_send_basic(wallet, arguments):
20+
if not wallet:
21+
print("please open a wallet")
22+
return False
23+
if len(arguments) < 3:
24+
print("Not enough arguments")
25+
return False
26+
27+
arguments, from_address = get_from_addr(arguments)
28+
arguments, priority_fee = get_fee(arguments)
29+
arguments, user_tx_attributes = get_tx_attr_from_args(arguments)
30+
arguments, owners = get_owners_from_params(arguments)
31+
to_send = get_arg(arguments)
32+
address_to = get_arg(arguments, 1)
33+
amount = get_arg(arguments, 2)
34+
35+
assetId = get_asset_id(wallet, to_send)
36+
if assetId is None:
37+
print("Asset id not found")
38+
return False
39+
40+
scripthash_to = lookup_addr_str(wallet, address_to)
41+
if scripthash_to is None:
42+
logger.debug("invalid address")
43+
return False
44+
45+
scripthash_from = None
46+
if from_address is not None:
47+
scripthash_from = lookup_addr_str(wallet, from_address)
48+
if scripthash_from is None:
49+
logger.debug("invalid address")
2450
return False
2551

26-
arguments, from_address = get_from_addr(arguments)
27-
arguments, user_tx_attributes = get_tx_attr_from_args(arguments)
28-
arguments, owners = get_owners_from_params(arguments)
29-
arguments, priority_fee = get_fee(arguments)
30-
to_send = get_arg(arguments)
31-
address_to = get_arg(arguments, 1)
32-
amount = get_arg(arguments, 2)
33-
34-
try:
35-
if float(amount) == 0:
36-
print("amount cannot be 0")
37-
return False
38-
except ValueError:
39-
# float parse error
52+
# if this is a token, we will use a different
53+
# transfer mechanism
54+
if type(assetId) is NEP5Token:
55+
return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), tx_attributes=user_tx_attributes)
56+
57+
f8amount = get_asset_amount(amount, assetId)
58+
if f8amount is False:
59+
logger.debug("invalid amount")
60+
return False
61+
if float(amount) == 0:
62+
print("amount cannot be 0")
63+
return False
64+
65+
fee = Fixed8.Zero()
66+
if priority_fee is not None:
67+
fee = priority_fee
68+
if fee is False:
69+
logger.debug("invalid fee")
4070
return False
4171

72+
output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to)
73+
contract_tx = ContractTransaction(outputs=[output])
74+
return [contract_tx, scripthash_from, fee, owners, user_tx_attributes]
75+
76+
77+
def construct_send_many(wallet, arguments):
78+
if not wallet:
79+
print("please open a wallet")
80+
return False
81+
if len(arguments) is 0:
82+
print("Not enough arguments")
83+
return False
84+
85+
outgoing = get_arg(arguments, convert_to_int=True)
86+
if outgoing is None:
87+
print("invalid outgoing number")
88+
return False
89+
if outgoing < 1:
90+
print("outgoing number must be >= 1")
91+
return False
92+
93+
arguments, from_address = get_from_addr(arguments)
94+
arguments, change_address = get_change_addr(arguments)
95+
arguments, priority_fee = get_fee(arguments)
96+
arguments, owners = get_owners_from_params(arguments)
97+
arguments, user_tx_attributes = get_tx_attr_from_args(arguments)
98+
99+
output = []
100+
for i in range(outgoing):
101+
print('Outgoing Number ', i + 1)
102+
to_send = prompt("Asset to send: ")
42103
assetId = get_asset_id(wallet, to_send)
43-
44104
if assetId is None:
45105
print("Asset id not found")
46106
return False
47-
107+
if type(assetId) is NEP5Token:
108+
print('Sendmany does not support NEP5 tokens')
109+
return False
110+
address_to = prompt("Address to: ")
48111
scripthash_to = lookup_addr_str(wallet, address_to)
49112
if scripthash_to is None:
50-
print("invalid address")
113+
logger.debug("invalid address")
114+
return False
115+
amount = prompt("Amount to send: ")
116+
f8amount = get_asset_amount(amount, assetId)
117+
if f8amount is False:
118+
logger.debug("invalid amount")
51119
return False
120+
if float(amount) == 0:
121+
print("amount cannot be 0")
122+
return False
123+
tx_output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to)
124+
output.append(tx_output)
125+
contract_tx = ContractTransaction(outputs=output)
52126

53-
scripthash_from = None
127+
scripthash_from = None
54128

55-
if from_address is not None:
56-
scripthash_from = lookup_addr_str(wallet, from_address)
129+
if from_address is not None:
130+
scripthash_from = lookup_addr_str(wallet, from_address)
131+
if scripthash_from is None:
132+
logger.debug("invalid address")
133+
return False
57134

58-
# if this is a token, we will use a different
59-
# transfer mechanism
60-
if type(assetId) is NEP5Token:
61-
return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), prompt_passwd=prompt_password, tx_attributes=user_tx_attributes)
135+
scripthash_change = None
62136

63-
f8amount = Fixed8.TryParse(amount, require_positive=True)
64-
if f8amount is None:
65-
print("invalid amount format")
137+
if change_address is not None:
138+
scripthash_change = lookup_addr_str(wallet, change_address)
139+
if scripthash_change is None:
140+
logger.debug("invalid address")
66141
return False
67142

68-
if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0:
69-
print("incorrect amount precision")
143+
fee = Fixed8.Zero()
144+
if priority_fee is not None:
145+
fee = priority_fee
146+
if fee is False:
147+
logger.debug("invalid fee")
70148
return False
71149

72-
fee = Fixed8.Zero()
73-
if priority_fee is not None:
74-
fee = priority_fee
150+
print("sending with fee: %s " % fee.ToString())
151+
return [contract_tx, scripthash_from, scripthash_change, fee, owners, user_tx_attributes]
75152

76-
print("sending with fee: %s " % fee.ToString())
77153

78-
output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to)
79-
tx = ContractTransaction(outputs=[output])
80-
81-
ttx = wallet.MakeTransaction(tx=tx,
82-
change_address=None,
83-
fee=fee,
84-
from_addr=scripthash_from)
154+
def process_transaction(wallet, contract_tx, scripthash_from=None, scripthash_change=None, fee=None, owners=None, user_tx_attributes=None):
155+
try:
156+
tx = wallet.MakeTransaction(tx=contract_tx,
157+
change_address=scripthash_change,
158+
fee=fee,
159+
from_addr=scripthash_from)
85160

86-
if ttx is None:
87-
print("insufficient funds")
161+
if tx is None:
162+
logger.debug("insufficient funds")
88163
return False
89164

90-
if prompt_password:
91-
passwd = prompt("[Password]> ", is_password=True)
92-
93-
if not wallet.ValidatePassword(passwd):
94-
print("incorrect password")
95-
return False
165+
# password prompt
166+
passwd = prompt("[Password]> ", is_password=True)
167+
if not wallet.ValidatePassword(passwd):
168+
print("incorrect password")
169+
return False
96170

97171
standard_contract = wallet.GetStandardAddress()
98172

@@ -102,6 +176,7 @@ def construct_and_send(prompter, wallet, arguments, prompt_password=True):
102176
signer_contract = wallet.GetContract(standard_contract)
103177

104178
if not signer_contract.IsMultiSigContract and owners is None:
179+
105180
data = standard_contract.Data
106181
tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
107182
data=data)]
@@ -126,7 +201,7 @@ def construct_and_send(prompter, wallet, arguments, prompt_password=True):
126201

127202
tx.scripts = context.GetScripts()
128203

129-
# print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))
204+
# print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))
130205

131206
relayed = NodeLeader.Instance().Relay(tx)
132207

@@ -152,7 +227,8 @@ def construct_and_send(prompter, wallet, arguments, prompt_password=True):
152227
return False
153228

154229

155-
def parse_and_sign(prompter, wallet, jsn):
230+
def parse_and_sign(wallet, jsn):
231+
156232
try:
157233
context = ContractParametersContext.FromJson(jsn)
158234
if context is None:

0 commit comments

Comments
 (0)