Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions monero/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,14 @@ def transfer_multiple(self, destinations,
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)
:class:`IntegratedAddress <monero.address.IntegratedAddress>`
is used as the destination)
: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>`
immediately; when `False`, it will only return the transaction(s)
so they might be broadcast later
:rtype: list of transaction and amount pairs:
[(:class:`Transaction <monero.transaction.Transaction>`, `Decimal`), ...]
"""
return self._backend.transfer(
destinations,
Expand All @@ -123,3 +124,32 @@ def transfer_multiple(self, destinations,
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)
35 changes: 32 additions & 3 deletions monero/backends/jsonrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ def raw_jsonrpc_request(self, method, params=None):
return result['result']




class JSONRPCWallet(object):
"""
JSON RPC backend for Monero wallet (``monero-wallet-rpc``)
Expand All @@ -129,7 +127,6 @@ class JSONRPCWallet(object):
a timeout does not mean that the underlying operation was not executed.
"""
_master_address = None
_addresses = None

def __init__(self, protocol='http', host='127.0.0.1', port=18088,
path='/json_rpc', user='', password='', timeout=None):
Expand Down Expand Up @@ -408,6 +405,38 @@ def transfer(self, destinations, priority,
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 {}}
Expand Down
54 changes: 42 additions & 12 deletions monero/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,12 @@ def transfer(self, address, amount,
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)
:class:`IntegratedAddress <monero.address.IntegratedAddress>`
is used as the destination)
: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
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].transfer(
Expand All @@ -301,24 +301,54 @@ def transfer_multiple(self, destinations,
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
from 1 to 4 (unimportant, normal, elevated, priority) or a constant
from `monero.prio`.
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 a destination)
:class:`IntegratedAddress <monero.address.IntegratedAddress>`
is used as a destination)
: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>`
immediately; when `False`, it will only return the transaction(s)
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,
priority=priority,
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)
122 changes: 122 additions & 0 deletions tests/data/test_jsonrpcwallet/test_sweep_all-00-get_accounts.json
Original file line number Diff line number Diff line change
@@ -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
}
}
Loading