Skip to content

Commit fcda547

Browse files
committed
Added Transfers endpoint
1 parent 67000ff commit fcda547

6 files changed

Lines changed: 280 additions & 2 deletions

File tree

CHANGELOG.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
Changelog
22
=========
33

4-
1.1.2 (current)
4+
1.1.3 (current)
5+
------------------
6+
7+
- Added transfer endpoint
8+
9+
1.1.2 (2018-03-20)
510
------------------
611

712
- Added bank card endpoint

hyperwallet/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
__email__ = 'devsupport@hyperwallet.com'
77
__copyright__ = 'Copyright (c) 2017 Hyperwallet'
88
__license__ = 'MIT'
9-
__version__ = '1.1.2'
9+
__version__ = '1.1.3'
1010
__url__ = 'https://github.com/hyperwallet/python-sdk'
1111
__download_url__ = 'https://pypi.python.org/pypi/hyperwallet-sdk'
1212
__description__ = 'A Python wrapper around the Hyperwallet API'
@@ -20,6 +20,7 @@
2020
BankCard, # noqa
2121
PrepaidCard, # noqa
2222
PaperCheck, # noqa
23+
Transfer, # noqa
2324
Payment, # noqa
2425
Balance, # noqa
2526
Receipt, # noqa

hyperwallet/api.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
BankCard,
1414
PrepaidCard,
1515
PaperCheck,
16+
Transfer,
1617
Payment,
1718
Balance,
1819
Receipt,
@@ -1450,6 +1451,115 @@ def deactivatePaperCheck(self,
14501451

14511452
'''
14521453
1454+
Transfers
1455+
https://portal.hyperwallet.com/docs/api/v3/resources/transfers
1456+
1457+
'''
1458+
1459+
def createTransfer(self,
1460+
data=None):
1461+
'''
1462+
Create a Transfer.
1463+
1464+
:param data:
1465+
A dictionary containing Transfer information. **REQUIRED**
1466+
:returns:
1467+
A Transfer.
1468+
'''
1469+
1470+
if not data:
1471+
raise HyperwalletException('data is required')
1472+
1473+
if not('sourceToken' in data) or not(data['sourceToken']):
1474+
raise HyperwalletException('sourceToken is required')
1475+
1476+
if not('destinationToken' in data) or not(data['destinationToken']):
1477+
raise HyperwalletException('destinationToken is required')
1478+
1479+
if not('clientTransferId' in data) or not(data['clientTransferId']):
1480+
raise HyperwalletException('clientTransferId is required')
1481+
1482+
response = self.apiClient.doPost(
1483+
os.path.join('transfers'),
1484+
data
1485+
)
1486+
1487+
return Transfer(response)
1488+
1489+
def getTransfer(self,
1490+
transferToken=None):
1491+
'''
1492+
Retrieve a Transfer.
1493+
1494+
:param transferToken:
1495+
A token identifying the Transfer. **REQUIRED**
1496+
:returns:
1497+
A Transfer.
1498+
'''
1499+
1500+
if not transferToken:
1501+
raise HyperwalletException('transferToken is required')
1502+
1503+
response = self.apiClient.doGet(
1504+
os.path.join(
1505+
'transfers',
1506+
transferToken
1507+
)
1508+
)
1509+
1510+
return Transfer(response)
1511+
1512+
def listTransfers(self,
1513+
params=None):
1514+
'''
1515+
List Transfers.
1516+
1517+
:param params:
1518+
A dictionary containing query parameters.
1519+
:returns:
1520+
An array of Transfers.
1521+
'''
1522+
1523+
response = self.apiClient.doGet(
1524+
os.path.join('transfers'),
1525+
params
1526+
)
1527+
1528+
return [Transfer(x) for x in response.get('data', [])]
1529+
1530+
def createTransferStatusTransition(self,
1531+
transferToken=None,
1532+
data=None):
1533+
'''
1534+
Create a Transfer Status Transition.
1535+
1536+
:param transferToken:
1537+
A token identifying the Transfer. **REQUIRED**
1538+
:param data:
1539+
A dictionary containing Transfer Status Transition information. **REQUIRED**
1540+
:returns:
1541+
A Transfer Status Transition.
1542+
'''
1543+
1544+
if not transferToken:
1545+
raise HyperwalletException('transferToken is required')
1546+
1547+
if not data:
1548+
raise HyperwalletException('data is required')
1549+
1550+
response = self.apiClient.doPost(
1551+
os.path.join(
1552+
'transfers',
1553+
transferToken,
1554+
'status-transitions'
1555+
),
1556+
data
1557+
)
1558+
1559+
return StatusTransition(response)
1560+
1561+
'''
1562+
14531563
Payments
14541564
https://portal.hyperwallet.com/docs/api/v3/resources/payments
14551565

hyperwallet/models.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,50 @@ def __repr__(self):
363363
)
364364

365365

366+
class Transfer(HyperwalletModel):
367+
'''
368+
The Transfer Model.
369+
370+
:param data:
371+
A dictionary containing the attributes for the Transfer.
372+
'''
373+
374+
def __init__(self, data):
375+
'''
376+
Create a new Transfer with the provided attributes.
377+
'''
378+
379+
super(Transfer, self).__init__(data)
380+
381+
self.defaults = {
382+
'token': None,
383+
'status': None,
384+
'createdOn': None,
385+
'clientTransferId': None,
386+
'sourceToken': None,
387+
'sourceAmount': None,
388+
'sourceFeeAmount': None,
389+
'sourceCurrency': None,
390+
'destinationToken': None,
391+
'destinationAmount': None,
392+
'destinationFeeAmount': None,
393+
'destinationCurrency': None,
394+
'foreignExchanges': None,
395+
'notes': None,
396+
'memo': None,
397+
'expiresOn': None
398+
}
399+
400+
for (param, default) in self.defaults.items():
401+
setattr(self, param, data.get(param, default))
402+
403+
def __repr__(self):
404+
return "Transfer({date}, {token})".format(
405+
date=self.createdOn,
406+
token=self.token
407+
)
408+
409+
366410
class Payment(HyperwalletModel):
367411
'''
368412
The Payment Model.

hyperwallet/tests/test_api.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,105 @@ def test_deactivate_paper_check_success_with_notes(self, mock_post):
11631163

11641164
'''
11651165
1166+
Transfers
1167+
1168+
'''
1169+
1170+
def test_create_transfer_fail_need_data(self):
1171+
1172+
with self.assertRaises(HyperwalletException) as exc:
1173+
self.api.createTransfer()
1174+
1175+
self.assertEqual(exc.exception.message, 'data is required')
1176+
1177+
def test_create_transfer_fail_need_source_token(self):
1178+
1179+
with self.assertRaises(HyperwalletException) as exc:
1180+
self.api.createTransfer(self.data)
1181+
1182+
self.assertEqual(exc.exception.message, 'sourceToken is required')
1183+
1184+
def test_create_transfer_fail_need_destination_token(self):
1185+
1186+
transfer_data = {
1187+
'sourceToken' : 'test-source-token'
1188+
}
1189+
with self.assertRaises(HyperwalletException) as exc:
1190+
self.api.createTransfer(transfer_data)
1191+
1192+
self.assertEqual(exc.exception.message, 'destinationToken is required')
1193+
1194+
def test_create_transfer_fail_need_client_transfer_id(self):
1195+
1196+
transfer_data = {
1197+
'sourceToken' : 'test-source-token',
1198+
'destinationToken' : 'test-destination-token'
1199+
}
1200+
with self.assertRaises(HyperwalletException) as exc:
1201+
self.api.createTransfer(transfer_data)
1202+
1203+
self.assertEqual(exc.exception.message, 'clientTransferId is required')
1204+
1205+
@mock.patch('hyperwallet.utils.ApiClient._makeRequest')
1206+
def test_create_transfer_success(self, mock_post):
1207+
1208+
transfer_data = {
1209+
'sourceToken' : 'test-source-token',
1210+
'destinationToken' : 'test-destination-token',
1211+
'clientTransferId' : 'test-clientTransferId'
1212+
}
1213+
mock_post.return_value = transfer_data
1214+
response = self.api.createTransfer(transfer_data)
1215+
1216+
self.assertTrue(response.sourceToken, transfer_data.get('sourceToken'))
1217+
1218+
def test_get_transfer_fail_need_transfer_token(self):
1219+
1220+
with self.assertRaises(HyperwalletException) as exc:
1221+
self.api.getTransfer()
1222+
1223+
self.assertEqual(exc.exception.message, 'transferToken is required')
1224+
1225+
@mock.patch('hyperwallet.utils.ApiClient._makeRequest')
1226+
def test_get_transfer_success(self, mock_get):
1227+
1228+
mock_get.return_value = self.data
1229+
response = self.api.getTransfer('token')
1230+
1231+
self.assertTrue(response.token, self.data.get('token'))
1232+
1233+
@mock.patch('hyperwallet.utils.ApiClient._makeRequest')
1234+
def test_list_transfers_success(self, mock_get):
1235+
1236+
mock_get.return_value = {'data': [self.data]}
1237+
response = self.api.listTransfers('token')
1238+
1239+
self.assertTrue(response[0].token, self.data.get('token'))
1240+
1241+
def test_create_transfer_status_transition_fail_need_transfer_token(self):
1242+
1243+
with self.assertRaises(HyperwalletException) as exc:
1244+
self.api.createTransferStatusTransition()
1245+
1246+
self.assertEqual(exc.exception.message, 'transferToken is required')
1247+
1248+
def test_create_transfer_status_transition_fail_need_data(self):
1249+
1250+
with self.assertRaises(HyperwalletException) as exc:
1251+
self.api.createTransferStatusTransition('token')
1252+
1253+
self.assertEqual(exc.exception.message, 'data is required')
1254+
1255+
@mock.patch('hyperwallet.utils.ApiClient._makeRequest')
1256+
def test_create_transfer_status_transition_success(self, mock_post):
1257+
1258+
mock_post.return_value = self.data
1259+
response = self.api.createTransferStatusTransition('token', self.data)
1260+
1261+
self.assertTrue(response.token, self.data.get('token'))
1262+
1263+
'''
1264+
11661265
Payments
11671266
11681267
'''

hyperwallet/tests/test_models.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
BankCard,
1212
PrepaidCard,
1313
PaperCheck,
14+
Transfer,
1415
Payment,
1516
Balance,
1617
Receipt,
@@ -223,6 +224,24 @@ def test_paper_check_model(self):
223224

224225
'''
225226
227+
Transfer
228+
229+
'''
230+
231+
def test_transfer_model(self):
232+
233+
test_transfer = Transfer(self.transfer_method_data)
234+
235+
self.assertEqual(
236+
test_transfer.__repr__(),
237+
'Transfer({date}, {token})'.format(
238+
date=self.transfer_method_data.get('createdOn'),
239+
token=self.transfer_method_data.get('token')
240+
)
241+
)
242+
243+
'''
244+
226245
Payment
227246
228247
'''

0 commit comments

Comments
 (0)