mirror of
https://git.wownero.com/lza_menace/wownero-python.git
synced 2024-08-15 03:25:25 +00:00
Add sweep_all()
method, close #20
This commit is contained in:
parent
010408dcf9
commit
48cad4007a
7 changed files with 1346 additions and 20 deletions
|
@ -113,8 +113,9 @@ class Account(object):
|
|||
:param unlock_time: the extra unlock delay
|
||||
:param relay: if `True`, the wallet will relay the transaction(s) to the network
|
||||
immediately; when `False`, it will only return the transaction(s)
|
||||
so they might be broadcasted later
|
||||
:rtype: list of :class:`Transaction <monero.transaction.Transaction>`
|
||||
so they might be broadcast later
|
||||
:rtype: list of transaction and amount pairs:
|
||||
[(:class:`Transaction <monero.transaction.Transaction>`, `Decimal`), ...]
|
||||
"""
|
||||
return self._backend.transfer(
|
||||
destinations,
|
||||
|
@ -123,3 +124,32 @@ class Account(object):
|
|||
unlock_time,
|
||||
account=self.index,
|
||||
relay=relay)
|
||||
|
||||
def sweep_all(self, address, priority=prio.NORMAL, payment_id=None,
|
||||
subaddr_indices=None, unlock_time=0, relay=True):
|
||||
"""
|
||||
Sends all unlocked balance to an address. Returns a list of resulting transactions.
|
||||
|
||||
:param address: destination :class:`Address <monero.address.Address>` or subtype
|
||||
:param priority: transaction priority, implies fee. The priority can be a number
|
||||
from 1 to 4 (unimportant, normal, elevated, priority) or a constant
|
||||
from `monero.prio`.
|
||||
:param payment_id: ID for the payment (must be None if
|
||||
:class:`IntegratedAddress <monero.address.IntegratedAddress>`
|
||||
is used as the destination)
|
||||
:param subaddr_indices: a sequence of subaddress indices to sweep from. Empty sequence
|
||||
or `None` means sweep all positive balances.
|
||||
:param unlock_time: the extra unlock delay
|
||||
:param relay: if `True`, the wallet will relay the transaction(s) to the network
|
||||
immediately; when `False`, it will only return the transaction(s)
|
||||
so they might be broadcast later
|
||||
:rtype: list of :class:`Transaction <monero.transaction.Transaction>`
|
||||
"""
|
||||
return self._backend.sweep_all(
|
||||
address,
|
||||
priority,
|
||||
payment_id,
|
||||
subaddr_indices,
|
||||
unlock_time,
|
||||
account=self.index,
|
||||
relay=relay)
|
||||
|
|
|
@ -106,8 +106,6 @@ class JSONRPCDaemon(object):
|
|||
return result['result']
|
||||
|
||||
|
||||
|
||||
|
||||
class JSONRPCWallet(object):
|
||||
"""
|
||||
JSON RPC backend for Monero wallet (``monero-wallet-rpc``)
|
||||
|
@ -121,7 +119,6 @@ class JSONRPCWallet(object):
|
|||
:param timeout: request timeout
|
||||
"""
|
||||
_master_address = None
|
||||
_addresses = None
|
||||
|
||||
def __init__(self, protocol='http', host='127.0.0.1', port=18088, path='/json_rpc',
|
||||
user='', password='', timeout=30):
|
||||
|
@ -313,6 +310,38 @@ class JSONRPCWallet(object):
|
|||
d['payment_id'] = payment_id
|
||||
return [self._tx(data) for data in _pertx]
|
||||
|
||||
def sweep_all(self, destination, priority, payment_id=None, subaddr_indices=None,
|
||||
unlock_time=0, account=0, relay=True):
|
||||
if not subaddr_indices:
|
||||
# retrieve indices of all subaddresses with positive unlocked balance
|
||||
bals = self.raw_request('get_balance', {'account_index': account})
|
||||
subaddr_indices = []
|
||||
for subaddr in bals['per_subaddress']:
|
||||
if subaddr.get('unlocked_balance', 0):
|
||||
subaddr_indices.append(subaddr['address_index'])
|
||||
data = {
|
||||
'account_index': account,
|
||||
'address': str(address(destination)),
|
||||
'subaddr_indices': list(subaddr_indices),
|
||||
'priority': priority,
|
||||
'unlock_time': 0,
|
||||
'get_tx_keys': True,
|
||||
'get_tx_hex': True,
|
||||
'do_not_relay': not relay,
|
||||
}
|
||||
if payment_id is not None:
|
||||
data['payment_id'] = str(PaymentID(payment_id))
|
||||
_transfers = self.raw_request('sweep_all', data)
|
||||
_pertx = [dict(_tx) for _tx in map(
|
||||
lambda vs: zip(('txid', 'amount', 'fee', 'key', 'blob', 'payment_id'), vs),
|
||||
zip(*[_transfers[k] for k in (
|
||||
'tx_hash_list', 'amount_list', 'fee_list', 'tx_key_list', 'tx_blob_list')]))]
|
||||
for d in _pertx:
|
||||
d['payment_id'] = payment_id
|
||||
return list(zip(
|
||||
[self._tx(data) for data in _pertx],
|
||||
map(from_atomic, _transfers['amount_list'])))
|
||||
|
||||
def raw_request(self, method, params=None, squelch_error_logging=False):
|
||||
hdr = {'Content-Type': 'application/json'}
|
||||
data = {'jsonrpc': '2.0', 'id': 0, 'method': method, 'params': params or {}}
|
||||
|
|
|
@ -247,7 +247,7 @@ class Wallet(object):
|
|||
:param unlock_time: the extra unlock delay
|
||||
:param relay: if `True`, the wallet will relay the transaction(s) to the network
|
||||
immediately; when `False`, it will only return the transaction(s)
|
||||
so they might be broadcasted later
|
||||
so they might be broadcast later
|
||||
:rtype: list of :class:`Transaction <monero.transaction.Transaction>`
|
||||
"""
|
||||
return self.accounts[0].transfer(
|
||||
|
@ -263,7 +263,7 @@ class Wallet(object):
|
|||
relay=True):
|
||||
"""
|
||||
Sends a batch of transfers from the default account. Returns a list of resulting
|
||||
transactions.
|
||||
transactions and amounts.
|
||||
|
||||
:param destinations: a list of destination and amount pairs: [(address, amount), ...]
|
||||
:param priority: transaction priority, implies fee. The priority can be a number
|
||||
|
@ -275,8 +275,9 @@ class Wallet(object):
|
|||
:param unlock_time: the extra unlock delay
|
||||
:param relay: if `True`, the wallet will relay the transaction(s) to the network
|
||||
immediately; when `False`, it will only return the transaction(s)
|
||||
so they might be broadcasted later
|
||||
:rtype: list of :class:`Transaction <monero.transaction.Transaction>`
|
||||
so they might be broadcast later
|
||||
:rtype: list of transaction and amount pairs:
|
||||
[(:class:`Transaction <monero.transaction.Transaction>`, `Decimal`), ...]
|
||||
"""
|
||||
return self.accounts[0].transfer_multiple(
|
||||
destinations,
|
||||
|
@ -284,3 +285,32 @@ class Wallet(object):
|
|||
payment_id=payment_id,
|
||||
unlock_time=unlock_time,
|
||||
relay=relay)
|
||||
|
||||
def sweep_all(self, address, priority=prio.NORMAL, payment_id=None,
|
||||
subaddr_indices=None, unlock_time=0, relay=True):
|
||||
"""
|
||||
Sends all unlocked balance from the default account to an address.
|
||||
Returns a list of resulting transactions.
|
||||
|
||||
:param address: destination :class:`Address <monero.address.Address>` or subtype
|
||||
:param priority: transaction priority, implies fee. The priority can be a number
|
||||
from 1 to 4 (unimportant, normal, elevated, priority) or a constant
|
||||
from `monero.prio`.
|
||||
:param payment_id: ID for the payment (must be None if
|
||||
:class:`IntegratedAddress <monero.address.IntegratedAddress>`
|
||||
is used as the destination)
|
||||
:param subaddr_indices: a sequence of subaddress indices to sweep from. Empty sequence
|
||||
or `None` means sweep all positive balances.
|
||||
:param unlock_time: the extra unlock delay
|
||||
:param relay: if `True`, the wallet will relay the transaction(s) to the network
|
||||
immediately; when `False`, it will only return the transaction(s)
|
||||
so they might be broadcast later
|
||||
:rtype: list of :class:`Transaction <monero.transaction.Transaction>`
|
||||
"""
|
||||
return self.accounts[0].sweep_all(
|
||||
address,
|
||||
priority=priority,
|
||||
payment_id=payment_id,
|
||||
subaddr_indices=subaddr_indices,
|
||||
unlock_time=unlock_time,
|
||||
relay=relay)
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"id": 0,
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"subaddress_accounts": [
|
||||
{
|
||||
"account_index": 0,
|
||||
"balance": 111141601989972,
|
||||
"base_address": "56cXYWG13YKaT9z1aEy2hb9TZNnxrW3zE9S4nTQVDux5Qq7UYsmjuux3Zstxkorj9HAufyWLU3FwHW4uERQF6tkeUVogGN3",
|
||||
"label": "Primary account",
|
||||
"tag": "",
|
||||
"unlocked_balance": 111141601989972
|
||||
},
|
||||
{
|
||||
"account_index": 1,
|
||||
"balance": 1000000000000,
|
||||
"base_address": "79kTZg96pMf2Dt9rLEWnLzTUB8XC1wMhxaJyxa79hJu6bK9CfFnfbSL1GJNZbqhv9xPqJhRj2Yfb7QUWa2zeEw56H4KiUfN",
|
||||
"label": "Untitled account",
|
||||
"tag": "",
|
||||
"unlocked_balance": 1000000000000
|
||||
},
|
||||
{
|
||||
"account_index": 2,
|
||||
"balance": 0,
|
||||
"base_address": "73WHDaR3q9D6x8mpUrP8Ux5t2LhF5Mcq9URJ3nRjhkUfAwkLxLFVvkebG8baqxbsrMjHv549rPYsKc6nZGZo5wad1pGRr2J",
|
||||
"label": "",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 3,
|
||||
"balance": 0,
|
||||
"base_address": "73BEwtAeC3pCJwK5cmJLAy4vwCkLLKmfgXW2XsCC7dsZPFwMtA7Sr7ZQWFTAYDFzQFXzcVNTm5jXGb4GqTzJGB7AE7DfwJn",
|
||||
"label": "test",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 4,
|
||||
"balance": 0,
|
||||
"base_address": "75WFcdiyf3z9hvMDu1RDmMFVgRaes41p7GftarFtPet5A9srdWuJpoJCiJyNMAq2oMfyUHLhCDmw4g6Typks3rVw4ipBiK1",
|
||||
"label": "",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 5,
|
||||
"balance": 0,
|
||||
"base_address": "79YfcwoWUBebbnR31sD4Q1FryHUrxExNqjAKukfAnvisLKtyZTVFqwtNcb33hsfrUF58esU7isA831SvWfx6PpDX2mpMPmR",
|
||||
"label": "test",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 6,
|
||||
"balance": 0,
|
||||
"base_address": "79khAXM9X3g6wWv7PBJVsUWqA8kmgGwXiicTsN1856uo17V4ijXTGVfGA3stnB5ur6a3M5rm1Nvdjacj5wM4NzHA6WGyLCT",
|
||||
"label": "",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 7,
|
||||
"balance": 0,
|
||||
"base_address": "78ZoiX5PoxHNLosKUbu8tv3nWSEhT6g1iam5weemsWvPCRPKGSpFJYRirbBz3hJs49R5QM7CpHSnwCwCPX9Qf4PGSachsDh",
|
||||
"label": "test",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 8,
|
||||
"balance": 0,
|
||||
"base_address": "72RBtJcgdtcXWHoWUijK6qfBCRRw2LSJGAeCgfe1eAFZ1Bjtrwwu1GZTQSV3muhhtMjXsAnSYT8mg8CGSCM9B5cT9CeCP2t",
|
||||
"label": "index 8",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 9,
|
||||
"balance": 0,
|
||||
"base_address": "77zDStiZ6XRGGMQ2nKhZi6ewQpaaJhWviQoz9pMrmRvd4yPRJhDurmB74B74pj2oLjcmpta56JFRaAYYBC2hzF8yCpQ7tXA",
|
||||
"label": "index 9",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 10,
|
||||
"balance": 0,
|
||||
"base_address": "7B35hT7MnqUP1uQJaUEZSVWmkcZAUVxXzX3JqKDhhjGv4AVSVWw6AiTJ39a1AjtdWPgGCp1JkgPiDMKM9ktgU7Dx5pGfbdY",
|
||||
"label": "index 10",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 11,
|
||||
"balance": 0,
|
||||
"base_address": "7BraWKhjmaW8ckBYVVmiVbQ3J3cFeKs5JBPTkGcECrHnAq8TwPDRoQe3iv4UDC3Woc7NvVTKZFVNeAQjJws9JEQeVHyoApz",
|
||||
"label": "index 11",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 12,
|
||||
"balance": 0,
|
||||
"base_address": "7Bwqgh7k9w1Xujaxg6v2j4bc73UQKxPq6UiZnh5B7pir5zDws2RunYTN7p8mhbLX6s3M7umCmYvMKSGmfaL5ecMsMBtYFVW",
|
||||
"label": "index 12",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
},
|
||||
{
|
||||
"account_index": 13,
|
||||
"balance": 0,
|
||||
"base_address": "73dhJABxD5sgcuAW3yiQbGLYQWx8SHxK4EmzmuCanRDBJpBR9Ste3BiZU2ZpPyqWbYer1a63N5NFdVWz7LxWxLoJFD9ozp1",
|
||||
"label": "index 13",
|
||||
"tag": "",
|
||||
"unlocked_balance": 0
|
||||
}
|
||||
],
|
||||
"total_balance": 112141601989972,
|
||||
"total_unlocked_balance": 112141601989972
|
||||
}
|
||||
}
|
1072
tests/data/test_jsonrpcwallet/test_sweep_all-10-getbalance.json
Normal file
1072
tests/data/test_jsonrpcwallet/test_sweep_all-10-getbalance.json
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -995,6 +995,26 @@ class JSONRPCWalletTestCase(JSONTestCase):
|
|||
self.assertEqual(txn.key,
|
||||
'7061d4d939b563a11e344c60938410e2e63ea72c43741fae81b8805cebe5570a')
|
||||
|
||||
@responses.activate
|
||||
def test_sweep_all(self):
|
||||
responses.add(responses.POST, self.jsonrpc_url,
|
||||
json=self._read('test_sweep_all-00-get_accounts.json'),
|
||||
status=200)
|
||||
responses.add(responses.POST, self.jsonrpc_url,
|
||||
json=self._read('test_sweep_all-10-getbalance.json'),
|
||||
status=200)
|
||||
responses.add(responses.POST, self.jsonrpc_url,
|
||||
json=self._read('test_sweep_all-20-sweep_all.json'),
|
||||
status=200)
|
||||
w = Wallet(JSONRPCWallet())
|
||||
result = w.sweep_all(
|
||||
'55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt',
|
||||
relay=False)
|
||||
self.assertEqual(len(result), 1)
|
||||
result = result[0]
|
||||
self.assertIsInstance(result[0], Transaction)
|
||||
self.assertEqual(Decimal('111.086545699972'), result[1])
|
||||
|
||||
@patch('monero.backends.jsonrpc.requests.post')
|
||||
def test_dynamic_ring_size_deprecation(self, mock_post):
|
||||
mock_post.return_value.status_code = 200
|
||||
|
|
Loading…
Reference in a new issue