1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#!/usr/bin/env python3
from taler.util.amount import Amount
from tests import check_single_balance
def test_withdrawal(exchange, bank, wallet):
bank_user = bank.register_random_user()
# assert that we start with no transactions
result = wallet.cmd("getTransactions")
assert not result["transactions"]
# test withdrawal
amount_raw = Amount.parse("TESTKUDOS:5")
wallet.testing_withdraw(amount_raw.stringify(), exchange.url, bank.url)
# check that balance is correct
result = wallet.cmd("getBalances")
amount_effective = Amount("TESTKUDOS", 4, 84000000)
check_single_balance(result["balances"], amount_effective)
# assert that withdrawal shows up properly in transactions
result = wallet.cmd("getTransactions")
assert len(result["transactions"]) == 1
transaction = result["transactions"][0]
assert transaction["type"] == "withdrawal"
assert Amount.parse(transaction["amountEffective"]) == amount_effective
assert Amount.parse(transaction["amountRaw"]) == amount_raw
assert transaction["exchangeBaseUrl"] == exchange.url
assert not transaction["pending"]
withdrawal_details = transaction["withdrawalDetails"]
assert withdrawal_details["type"] == "manual-transfer"
payto_list = ["payto://x-taler-bank/localhost/Exchange"]
assert withdrawal_details["exchangePaytoUris"] == payto_list
# get a withdrawal URI
bank_uri_resp = bank.generate_withdraw_uri(bank_user, "TESTKUDOS:5")
uri = bank_uri_resp.taler_withdraw_uri
assert uri.startswith("taler+http://withdraw")
# get withdrawal details from URI
result = wallet.cmd("getWithdrawalDetailsForUri", {"talerWithdrawUri": uri})
assert Amount.parse(result["amount"]) == amount_raw
assert result["defaultExchangeBaseUrl"] == exchange.url
assert len(result["possibleExchanges"]) == 1
assert result["possibleExchanges"][0]["exchangeBaseUrl"] == exchange.url
assert result["possibleExchanges"][0]["currency"] == "TESTKUDOS"
assert result["possibleExchanges"][0]["paytoUris"] == payto_list
# check withdrawal details for amount
request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw.stringify()}
result = wallet.cmd("getWithdrawalDetailsForAmount", request)
assert Amount.parse(result["amountRaw"]) == amount_raw
assert Amount.parse(result["amountEffective"]) == amount_effective
assert result["paytoUris"] == payto_list
assert not result["tosAccepted"]
# get ToS
result = wallet.cmd("getExchangeTos", {"exchangeBaseUrl": exchange.url})
assert result["currentEtag"] == exchange.terms_etag
assert result["tos"] == exchange.tos
# accept ToS
request = {"exchangeBaseUrl": exchange.url, "etag": exchange.terms_etag}
wallet.cmd("setExchangeTosAccepted", request)
# check that ToS are now shown as accepted
request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw.stringify()}
result = wallet.cmd("getWithdrawalDetailsForAmount", request)
assert result["tosAccepted"]
# accept withdrawal
request = {"exchangeBaseUrl": exchange.url, "talerWithdrawUri": uri}
result = wallet.cmd("acceptBankIntegratedWithdrawal", request)
assert result["confirmTransferUrl"].startswith(bank.url + "confirm-withdrawal/")
confirm_url = result["confirmTransferUrl"]
# Let the wallet do its work. At this point, the bank-integrated
# withdrawal won't have succeeded yet, as it's not confirmed at the bank side.
wallet.run_pending()
# check that balance is correct
result = wallet.cmd("getBalances")
check_single_balance(result["balances"], amount_effective, amount_effective)
# assert that 2nd withdrawal shows up properly in transactions
result = wallet.cmd("getTransactions")
assert len(result["transactions"]) == 2
transaction = result["transactions"][0]
assert transaction["type"] == "withdrawal"
assert Amount.parse(transaction["amountEffective"]) == amount_effective
assert Amount.parse(transaction["amountRaw"]) == amount_raw
assert transaction["exchangeBaseUrl"] == exchange.url
assert transaction["pending"]
withdrawal_details = transaction["withdrawalDetails"]
assert withdrawal_details["type"] == "taler-bank-integration-api"
assert not withdrawal_details["confirmed"]
assert withdrawal_details["bankConfirmationUrl"] == confirm_url
# new withdrawal is newer than old one
timestamp0 = result["transactions"][0]["timestamp"]["t_ms"]
timestamp1 = result["transactions"][1]["timestamp"]["t_ms"]
assert timestamp0 > timestamp1
# now we actually confirm the withdrawal
bank.confirm_withdrawal(bank_user, bank_uri_resp.withdrawal_id)
# It might take some time until the exchange knows about the reserve,
# so we'll try until it works.
wallet.run_until_done()
# check that balance is correct
result = wallet.cmd("getBalances")
check_single_balance(
result["balances"], Amount.parse("TESTKUDOS:9.68"), Amount.parse("TESTKUDOS:0"),
)
# check that transaction is no longer pending, but confirmed
result = wallet.cmd("getTransactions")
assert len(result["transactions"]) == 2
transaction = result["transactions"][1] # TODO this transaction should be at the top now
assert transaction["type"] == "withdrawal"
assert not transaction["pending"]
assert transaction["withdrawalDetails"]["confirmed"]
# one more manual withdrawal
request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw.stringify()}
result = wallet.cmd("acceptManualWithdrawal", request)
assert len(result["exchangePaytoUris"]) == 1
result["exchangePaytoUris"][0].startswith(payto_list[0])
# check that balance is correct
result = wallet.cmd("getBalances")
check_single_balance(
result["balances"], amount_effective + amount_effective, amount_effective
)
# assert that 3nd withdrawal shows up properly in transactions
result = wallet.cmd("getTransactions")
assert len(result["transactions"]) == 3
transaction = result["transactions"][0]
assert transaction["type"] == "withdrawal"
assert Amount.parse(transaction["amountEffective"]) == amount_effective
assert Amount.parse(transaction["amountRaw"]) == amount_raw
assert transaction["exchangeBaseUrl"] == exchange.url
assert transaction["pending"]
withdrawal_details = transaction["withdrawalDetails"]
assert withdrawal_details["type"] == "manual-transfer"
assert len(withdrawal_details["exchangePaytoUris"]) == 1
assert withdrawal_details["exchangePaytoUris"][0].startswith(payto_list[0])
# last withdrawal is newest
timestamp3 = transaction["timestamp"]["t_ms"]
assert timestamp3 > timestamp0
assert timestamp3 > timestamp1
|