summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/demobank-ui/src/pages/OperationState/views.tsx6
-rw-r--r--packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx7
-rw-r--r--packages/demobank-ui/src/pages/WalletWithdrawForm.tsx11
-rw-r--r--packages/taler-harness/src/http-client/bank-core.ts1006
-rw-r--r--packages/taler-util/src/http-client/bank-core.ts2
-rw-r--r--packages/taler-util/src/operation.ts2
6 files changed, 534 insertions, 500 deletions
diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx b/packages/demobank-ui/src/pages/OperationState/views.tsx
index 4001fd093..ea38525b9 100644
--- a/packages/demobank-ui/src/pages/OperationState/views.tsx
+++ b/packages/demobank-ui/src/pages/OperationState/views.tsx
@@ -338,6 +338,12 @@ export function FailedView({ error }: State.Failed) {
{error.detail.hint}
</div>
</Attention>
+ case "account-not-found": return <Attention type="danger"
+ title={i18n.str`The operation was rejected due to insufficient funds.`}>
+ <div class="mt-2 text-sm text-red-700">
+ {error.detail.hint}
+ </div>
+ </Attention>
default: assertUnreachable(error)
}
}
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index 6649d224e..97e38d75e 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -122,6 +122,7 @@ export function PaytoWireTransferForm({
async function doSend() {
let payto_uri: PaytoString | undefined;
let sendingAmount: AmountString | undefined;
+
if (credentials.status !== "loggedIn") return;
if (rawPaytoInput) {
const p = parsePaytoUri(rawPaytoInput)
@@ -159,6 +160,12 @@ export function PaytoWireTransferForm({
description: res.detail.hint as TranslatedString,
debug: res.detail,
})
+ case "account-not-found": return notify({
+ type: "error",
+ title: i18n.str`The destination account "${puri}" was not found.`,
+ description: res.detail.hint as TranslatedString,
+ debug: res.detail,
+ })
default: assertUnreachable(res)
}
}
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index abdebf9bf..e3a713fdd 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -121,6 +121,15 @@ function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: {
})
break;
}
+ case "account-not-found": {
+ notify({
+ type: "error",
+ title: i18n.str`Account not found`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ })
+ break;
+ }
default: assertUnreachable(resp)
}
}
@@ -135,7 +144,7 @@ function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: {
e.preventDefault()
}}
>
- <ShowLocalNotification notification={notification} />
+ <ShowLocalNotification notification={notification} />
<div class="px-4 py-6 ">
<div class="grid max-w-xs grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
diff --git a/packages/taler-harness/src/http-client/bank-core.ts b/packages/taler-harness/src/http-client/bank-core.ts
index 25e67b031..6f9641dc9 100644
--- a/packages/taler-harness/src/http-client/bank-core.ts
+++ b/packages/taler-harness/src/http-client/bank-core.ts
@@ -1,530 +1,540 @@
-import { AccessToken, Amounts, TalerCoreBankHttpClient, TalerCorebankApi, encodeCrock, failOrThrow, getRandomBytes, parsePaytoUri, stringifyPaytoUri, succeedOrThrow } from "@gnu-taler/taler-util"
+import { AccessToken, Amounts, TalerCoreBankHttpClient, TalerCorebankApi, buildPayto, encodeCrock, failOrThrow, getRandomBytes, parsePaytoUri, stringifyPaytoUri, succeedOrThrow } from "@gnu-taler/taler-util"
export class BankCoreSmokeTest {
- constructor(readonly api:TalerCoreBankHttpClient) {
+ constructor(readonly api: TalerCoreBankHttpClient) {
}
-async testConfig() {
- const config = await this.api.getConfig()
- if (!this.api.isCompatible(config.body.version)) {
- throw Error(`not compatible with server ${config.body.version}`)
+ async testConfig() {
+ const config = await this.api.getConfig()
+ if (!this.api.isCompatible(config.body.version)) {
+ throw Error(`not compatible with server ${config.body.version}`)
+ }
+ return config.body
}
- return config.body
-}
-
-async testCashouts(adminPassword: string) {
-}
-async testMonitor(adminPassword: string) {
- const { access_token: adminToken } = await succeedOrThrow(() =>
- this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
- scope: "readwrite"
- })
- )
-
- await succeedOrThrow(() => (
- this.api.getMonitor()
- ))
-
- await succeedOrThrow(() => (
- this.api.getMonitor({
- timeframe: TalerCorebankApi.MonitorTimeframeParam.day,
- which: (new Date()).getDate() -1
- })
- ))
-}
-
-async testAccountManagement(adminPassword: string) {
-
- const { access_token: adminToken } = await succeedOrThrow(() =>
- this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
- scope: "readwrite"
- })
- )
-
- /**
- * Create account
- */
- {
- const username = "harness-" + encodeCrock(getRandomBytes(10)).toLowerCase();
-
- // await failOrThrow("invalid-input",() =>
- // this.api.createAccount(adminToken, {
- // name: username,
- // username, password: "123",
- // challenge_contact_data: {
- // email: "invalid email",
- // phone: "invalid phone",
- // }
- // })
- // )
-
- // await failOrThrow("unable-to-create",() =>
- // this.api.createAccount(adminToken, {
- // name: "admin",
- // username, password: "123"
- // })
- // )
-
- // await failOrThrow("unable-to-create",() =>
- // this.api.createAccount(adminToken, {
- // name: "bank",
- // username, password: "123"
- // })
- // )
-
- await succeedOrThrow(() =>
- this.api.createAccount(adminToken, {
- name: username,
- username, password: "123"
- })
- )
-
- await failOrThrow("already-exist", () =>
- this.api.createAccount(adminToken, {
- name: username,
- username, password: "123"
- })
- );
- }
-
- /**
- * Delete account
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
-
- await failOrThrow("not-found", () =>
- this.api.deleteAccount({ username: "not-found", token: adminToken })
- )
- await failOrThrow("unable-to-delete", () =>
- this.api.deleteAccount({ username: "admin", token: adminToken })
- )
- await failOrThrow("unable-to-delete", () =>
- this.api.deleteAccount({ username: "bank", token: adminToken })
- )
-
- await failOrThrow("balance-not-zero", () =>
- this.api.deleteAccount({ username, token: adminToken })
- )
-
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
-
- const adminInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username: "admin", token: adminToken })
- )
-
- const adminAccount = parsePaytoUri(adminInfo.payto_uri)!
- adminAccount.params["message"] = "all my money"
- const withSubject = stringifyPaytoUri(adminAccount)
-
- await succeedOrThrow(() =>
- this.api.createTransaction({ username, token }, {
- payto_uri: withSubject,
- amount: userInfo.balance.amount
- })
- )
-
-
- const otherUsername = "harness-" + encodeCrock(getRandomBytes(10)).toLowerCase();
-
- await succeedOrThrow(() =>
- this.api.createAccount(adminToken, {
- name: otherUsername,
- username: otherUsername, password: "123"
- })
- )
-
- await failOrThrow("unauthorized", () =>
- this.api.deleteAccount({ username: otherUsername, token })
- )
-
- await succeedOrThrow(() =>
- this.api.deleteAccount({ username, token: adminToken })
- )
- }
-
- /**
- * Update account
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
-
- await failOrThrow("cant-change-legal-name-or-admin", () =>
- this.api.updateAccount({ username, token }, {
- name: "something else",
- })
- )
-
- // await failOrThrow("not-found", () =>
- // this.api.updateAccount({ username: "notfound", token }, {
- // challenge_contact_data: {
- // email: "asd@Aasd.com"
- // }
- // })
- // )
-
- await failOrThrow("unauthorized", () =>
- this.api.updateAccount({ username: "notfound", token: "wrongtoken" as AccessToken }, {
- challenge_contact_data: {
- email: "asd@Aasd.com"
- }
- })
- )
-
- await succeedOrThrow(() =>
- this.api.updateAccount({ username, token }, {
- challenge_contact_data: {
- email: "asd@Aasd.com"
- }
- })
- )
- }
-
- /**
- * Update password
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
-
- await succeedOrThrow(() =>
- this.api.updatePassword({ username, token }, {
- old_password: "123",
- new_password: "234"
- })
- )
- // await failOrThrow("not-found",() =>
- // this.api.updatePassword({ username:"notfound", token: userTempToken }, {
- // old_password: "123",
- // new_password: "234"
- // })
- // )
- await failOrThrow("unauthorized", () =>
- this.api.updatePassword({ username: "admin", token }, {
- old_password: "123",
- new_password: "234"
- })
- )
- // await failOrThrow("old-password-invalid-or-not-allowed",() =>
- // this.api.updatePassword({ username, token: userTempToken }, {
- // old_password: "123",
- // new_password: "234"
- // })
- // )
-
- }
-
- /**
- * public accounts
- */
- {
- const acs = await succeedOrThrow(() => this.api.getPublicAccounts())
-
- }
- /**
- * get accounts
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
- // await failOrThrow("no-rights",() =>
- // this.api.getAccounts(token)
- // )
- await failOrThrow("unauthorized", () =>
- this.api.getAccounts("ASDASD" as AccessToken)
- )
-
- const acs = await succeedOrThrow(() =>
- this.api.getAccounts(adminToken)
- )
- }
-
-}
-
-async testWithdrawals(adminPassword: string) {
- const { access_token: adminToken } = await succeedOrThrow(() =>
- this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
- scope: "readwrite"
- })
- )
- /**
- * create withdrawals
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
-
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
-
- const balance = Amounts.parseOrThrow(userInfo.balance.amount)
- const moreThanBalance = Amounts.stringify(Amounts.mult(balance, 5).amount)
- await failOrThrow("insufficient-funds", () =>
- this.api.createWithdrawal({ username, token }, {
- amount: moreThanBalance
- })
- )
-
- await failOrThrow("unauthorized", () =>
- this.api.createWithdrawal({ username, token: "wrongtoken" as AccessToken }, {
- amount: userInfo.balance.amount
- })
- )
- await succeedOrThrow(() =>
- this.api.createWithdrawal({ username, token }, {
- amount: userInfo.balance.amount
- })
- )
+ async testCashouts(adminPassword: string) {
}
-
- /**
- * get withdrawal
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
-
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
-
- const { withdrawal_id } = await succeedOrThrow(() =>
- this.api.createWithdrawal({ username, token }, {
- amount: userInfo.balance.amount
+ async testMonitor(adminPassword: string) {
+ const { access_token: adminToken } = await succeedOrThrow(() =>
+ this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
+ scope: "readwrite"
})
)
- await succeedOrThrow(() =>
- this.api.getWithdrawalById(withdrawal_id)
- )
-
- await failOrThrow("invalid-id", () =>
- this.api.getWithdrawalById("invalid")
- )
- await failOrThrow("not-found", () =>
- this.api.getWithdrawalById("11111111-1111-1111-1111-111111111111")
- )
- }
-
- /**
- * abort withdrawal
- */
- {
- const { username:exchangeUser, token: exchangeToken } = await createRandomTestUser(this.api, adminToken, {is_taler_exchange: true})
- const { username, token } = await createRandomTestUser(this.api, adminToken)
+ await succeedOrThrow(() => (
+ this.api.getMonitor()
+ ))
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
- const exchangeInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username:exchangeUser, token:exchangeToken })
- )
-
- await failOrThrow("invalid-id", () =>
- this.api.abortWithdrawalById("invalid")
- )
- await failOrThrow("not-found", () =>
- this.api.abortWithdrawalById("11111111-1111-1111-1111-111111111111")
- )
-
- const { withdrawal_id:firstWithdrawal } = await succeedOrThrow(() =>
- this.api.createWithdrawal({ username, token }, {
- amount: userInfo.balance.amount
- })
- )
-
- await succeedOrThrow(() =>
- this.api.abortWithdrawalById(firstWithdrawal)
- )
-
- const { taler_withdraw_uri: uri, withdrawal_id:secondWithdrawal } = await succeedOrThrow(() =>
- this.api.createWithdrawal({ username, token }, {
- amount: userInfo.balance.amount
+ await succeedOrThrow(() => (
+ this.api.getMonitor({
+ timeframe: TalerCorebankApi.MonitorTimeframeParam.day,
+ which: (new Date()).getDate() - 1
})
- )
-
- await succeedOrThrow(() =>
- this.api.getIntegrationAPI().completeWithdrawalOperationById(secondWithdrawal, {
- reserve_pub: encodeCrock(getRandomBytes(32)),
- selected_exchange: exchangeInfo.payto_uri,
- })
- )
- await succeedOrThrow(() =>
- this.api.confirmWithdrawalById(secondWithdrawal)
- )
- await failOrThrow("previously-confirmed", () =>
- this.api.abortWithdrawalById(secondWithdrawal)
- )
+ ))
}
- /**
- * confirm withdrawal
- */
- {
- const { username:exchangeUser, token: exchangeToken } = await createRandomTestUser(this.api, adminToken, {is_taler_exchange: true})
- const { username, token } = await createRandomTestUser(this.api, adminToken)
-
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
- const exchangeInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username:exchangeUser, token:exchangeToken })
- )
-
- await failOrThrow("invalid-id", () =>
- this.api.confirmWithdrawalById("invalid")
- )
- await failOrThrow("not-found", () =>
- this.api.confirmWithdrawalById("11111111-1111-1111-1111-111111111111")
- )
-
- const { withdrawal_id:firstWithdrawal } = await succeedOrThrow(() =>
- this.api.createWithdrawal({ username, token }, {
- amount: userInfo.balance.amount
- })
- )
-
- await failOrThrow("no-exchange-or-reserve-selected", () =>
- this.api.confirmWithdrawalById(firstWithdrawal)
- )
-
- await succeedOrThrow(() =>
- this.api.getIntegrationAPI().completeWithdrawalOperationById(firstWithdrawal, {
- reserve_pub: encodeCrock(getRandomBytes(32)),
- selected_exchange: exchangeInfo.payto_uri,
- })
- )
-
- await succeedOrThrow(() =>
- this.api.confirmWithdrawalById(firstWithdrawal)
- )
+ async testAccountManagement(adminPassword: string) {
- const { withdrawal_id:secondWithdrawal } = await succeedOrThrow(() =>
- this.api.createWithdrawal({ username, token }, {
- amount: userInfo.balance.amount
+ const { access_token: adminToken } = await succeedOrThrow(() =>
+ this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
+ scope: "readwrite"
})
)
- await succeedOrThrow(() =>
- this.api.abortWithdrawalById(secondWithdrawal)
- )
- await failOrThrow("previously-aborted", () =>
- this.api.confirmWithdrawalById(secondWithdrawal)
- )
- }
-}
+ /**
+ * Create account
+ */
+ {
+ const username = "harness-" + encodeCrock(getRandomBytes(10)).toLowerCase();
+
+ // await failOrThrow("invalid-input",() =>
+ // this.api.createAccount(adminToken, {
+ // name: username,
+ // username, password: "123",
+ // challenge_contact_data: {
+ // email: "invalid email",
+ // phone: "invalid phone",
+ // }
+ // })
+ // )
+
+ // await failOrThrow("unable-to-create",() =>
+ // this.api.createAccount(adminToken, {
+ // name: "admin",
+ // username, password: "123"
+ // })
+ // )
+
+ // await failOrThrow("unable-to-create",() =>
+ // this.api.createAccount(adminToken, {
+ // name: "bank",
+ // username, password: "123"
+ // })
+ // )
+
+ await succeedOrThrow(() =>
+ this.api.createAccount(adminToken, {
+ name: username,
+ username, password: "123"
+ })
+ )
+
+ await failOrThrow("already-exist", () =>
+ this.api.createAccount(adminToken, {
+ name: username,
+ username, password: "123"
+ })
+ );
+ }
+
+ /**
+ * Delete account
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ await failOrThrow("not-found", () =>
+ this.api.deleteAccount({ username: "not-found", token: adminToken })
+ )
+ await failOrThrow("unable-to-delete", () =>
+ this.api.deleteAccount({ username: "admin", token: adminToken })
+ )
+ await failOrThrow("unable-to-delete", () =>
+ this.api.deleteAccount({ username: "bank", token: adminToken })
+ )
+
+ await failOrThrow("balance-not-zero", () =>
+ this.api.deleteAccount({ username, token: adminToken })
+ )
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+
+ const adminInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username: "admin", token: adminToken })
+ )
+
+ const adminAccount = parsePaytoUri(adminInfo.payto_uri)!
+ adminAccount.params["message"] = "all my money"
+ const withSubject = stringifyPaytoUri(adminAccount)
+
+ await succeedOrThrow(() =>
+ this.api.createTransaction({ username, token }, {
+ payto_uri: withSubject,
+ amount: userInfo.balance.amount
+ })
+ )
+
+
+ const otherUsername = "harness-" + encodeCrock(getRandomBytes(10)).toLowerCase();
+
+ await succeedOrThrow(() =>
+ this.api.createAccount(adminToken, {
+ name: otherUsername,
+ username: otherUsername, password: "123"
+ })
+ )
+
+ await failOrThrow("unauthorized", () =>
+ this.api.deleteAccount({ username: otherUsername, token })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.deleteAccount({ username, token: adminToken })
+ )
+ }
+
+ /**
+ * Update account
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ await failOrThrow("cant-change-legal-name-or-admin", () =>
+ this.api.updateAccount({ username, token }, {
+ name: "something else",
+ })
+ )
+
+ // await failOrThrow("not-found", () =>
+ // this.api.updateAccount({ username: "notfound", token }, {
+ // challenge_contact_data: {
+ // email: "asd@Aasd.com"
+ // }
+ // })
+ // )
+
+ await failOrThrow("unauthorized", () =>
+ this.api.updateAccount({ username: "notfound", token: "wrongtoken" as AccessToken }, {
+ challenge_contact_data: {
+ email: "asd@Aasd.com"
+ }
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.updateAccount({ username, token }, {
+ challenge_contact_data: {
+ email: "asd@Aasd.com"
+ }
+ })
+ )
+ }
+
+ /**
+ * Update password
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ await succeedOrThrow(() =>
+ this.api.updatePassword({ username, token }, {
+ old_password: "123",
+ new_password: "234"
+ })
+ )
+ // await failOrThrow("not-found",() =>
+ // this.api.updatePassword({ username:"notfound", token: userTempToken }, {
+ // old_password: "123",
+ // new_password: "234"
+ // })
+ // )
+ await failOrThrow("unauthorized", () =>
+ this.api.updatePassword({ username: "admin", token }, {
+ old_password: "123",
+ new_password: "234"
+ })
+ )
+ // await failOrThrow("old-password-invalid-or-not-allowed",() =>
+ // this.api.updatePassword({ username, token: userTempToken }, {
+ // old_password: "123",
+ // new_password: "234"
+ // })
+ // )
+
+ }
+
+ /**
+ * public accounts
+ */
+ {
+ const acs = await succeedOrThrow(() => this.api.getPublicAccounts())
+
+ }
+ /**
+ * get accounts
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+ // await failOrThrow("no-rights",() =>
+ // this.api.getAccounts(token)
+ // )
+ await failOrThrow("unauthorized", () =>
+ this.api.getAccounts("ASDASD" as AccessToken)
+ )
+
+ const acs = await succeedOrThrow(() =>
+ this.api.getAccounts(adminToken)
+ )
+ }
-async testTransactions(adminPassword: string) {
- const { access_token: adminToken } = await succeedOrThrow(() =>
- this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
- scope: "readwrite"
- })
- )
- // get transactions
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
- // await succeedOrThrow(() => this.api.getTransactions(creds))
- const txs = await succeedOrThrow(() => this.api.getTransactions({ username, token }, {
- limit: 5,
- order: "asc"
- }))
- // await failOrThrow("not-found",() => this.api.getTransactions({
- // username:"not-found",
- // token: creds.token,
- // }))
- await failOrThrow("unauthorized", () => this.api.getTransactions({
- username: username,
- token: "wrongtoken" as AccessToken,
- }))
}
- /**
- * getTxby id
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
- const { username: otherUser, token: otherToken } = await createRandomTestUser(this.api, adminToken)
-
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
- const otherInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username: otherUser, token: otherToken })
- )
- const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
- otherAccount.params["message"] = "all"
-
- await succeedOrThrow(() =>
- this.api.createTransaction({ username, token }, {
- payto_uri: stringifyPaytoUri(otherAccount),
- amount: userInfo.balance.amount
+ async testWithdrawals(adminPassword: string) {
+ const { access_token: adminToken } = await succeedOrThrow(() =>
+ this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
+ scope: "readwrite"
})
)
-
- const txs = await succeedOrThrow(() => this.api.getTransactions({ username, token }, {
- limit: 5,
- order: "asc"
- }))
- const rowId = txs.transactions[0].row_id
-
- await succeedOrThrow(() =>
- this.api.getTransactionById({ username, token }, rowId)
- )
-
- await failOrThrow("not-found", () =>
- this.api.getTransactionById({ username, token }, 123123123)
- )
-
- await failOrThrow("unauthorized", () =>
- this.api.getTransactionById({ username, token: "wrongtoken" as AccessToken }, 123123123)
- )
+ /**
+ * create withdrawals
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+
+ const balance = Amounts.parseOrThrow(userInfo.balance.amount)
+ const moreThanBalance = Amounts.stringify(Amounts.mult(balance, 5).amount)
+ await failOrThrow("insufficient-funds", () =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: moreThanBalance
+ })
+ )
+
+ await failOrThrow("unauthorized", () =>
+ this.api.createWithdrawal({ username, token: "wrongtoken" as AccessToken }, {
+ amount: userInfo.balance.amount
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: userInfo.balance.amount
+ })
+ )
+ }
+
+ /**
+ * get withdrawal
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+
+ const { withdrawal_id } = await succeedOrThrow(() =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: userInfo.balance.amount
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.getWithdrawalById(withdrawal_id)
+ )
+
+ await failOrThrow("invalid-id", () =>
+ this.api.getWithdrawalById("invalid")
+ )
+ await failOrThrow("not-found", () =>
+ this.api.getWithdrawalById("11111111-1111-1111-1111-111111111111")
+ )
+ }
+
+ /**
+ * abort withdrawal
+ */
+ {
+ const { username: exchangeUser, token: exchangeToken } = await createRandomTestUser(this.api, adminToken, { is_taler_exchange: true })
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+ const exchangeInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username: exchangeUser, token: exchangeToken })
+ )
+
+ await failOrThrow("invalid-id", () =>
+ this.api.abortWithdrawalById("invalid")
+ )
+ await failOrThrow("not-found", () =>
+ this.api.abortWithdrawalById("11111111-1111-1111-1111-111111111111")
+ )
+
+ const { withdrawal_id: firstWithdrawal } = await succeedOrThrow(() =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: userInfo.balance.amount
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.abortWithdrawalById(firstWithdrawal)
+ )
+
+ const { taler_withdraw_uri: uri, withdrawal_id: secondWithdrawal } = await succeedOrThrow(() =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: userInfo.balance.amount
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.getIntegrationAPI().completeWithdrawalOperationById(secondWithdrawal, {
+ reserve_pub: encodeCrock(getRandomBytes(32)),
+ selected_exchange: exchangeInfo.payto_uri,
+ })
+ )
+ await succeedOrThrow(() =>
+ this.api.confirmWithdrawalById(secondWithdrawal)
+ )
+ await failOrThrow("previously-confirmed", () =>
+ this.api.abortWithdrawalById(secondWithdrawal)
+ )
+ }
+
+ /**
+ * confirm withdrawal
+ */
+ {
+ const { username: exchangeUser, token: exchangeToken } = await createRandomTestUser(this.api, adminToken, { is_taler_exchange: true })
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+ const exchangeInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username: exchangeUser, token: exchangeToken })
+ )
+
+ await failOrThrow("invalid-id", () =>
+ this.api.confirmWithdrawalById("invalid")
+ )
+ await failOrThrow("not-found", () =>
+ this.api.confirmWithdrawalById("11111111-1111-1111-1111-111111111111")
+ )
+
+ const { withdrawal_id: firstWithdrawal } = await succeedOrThrow(() =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: userInfo.balance.amount
+ })
+ )
+
+ await failOrThrow("no-exchange-or-reserve-selected", () =>
+ this.api.confirmWithdrawalById(firstWithdrawal)
+ )
+
+ await succeedOrThrow(() =>
+ this.api.getIntegrationAPI().completeWithdrawalOperationById(firstWithdrawal, {
+ reserve_pub: encodeCrock(getRandomBytes(32)),
+ selected_exchange: exchangeInfo.payto_uri,
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.confirmWithdrawalById(firstWithdrawal)
+ )
+
+ const { withdrawal_id: secondWithdrawal } = await succeedOrThrow(() =>
+ this.api.createWithdrawal({ username, token }, {
+ amount: userInfo.balance.amount
+ })
+ )
+
+ await succeedOrThrow(() =>
+ this.api.abortWithdrawalById(secondWithdrawal)
+ )
+ //FIXME: skip
+ // await failOrThrow("previously-aborted", () =>
+ // this.api.confirmWithdrawalById(secondWithdrawal)
+ // )
+ }
}
- /**
- * create transactions
- */
- {
- const { username, token } = await createRandomTestUser(this.api, adminToken)
- const { username: otherUser, token: otherToken } = await createRandomTestUser(this.api, adminToken)
-
- const userInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username, token })
- )
- const otherInfo = await succeedOrThrow(() =>
- this.api.getAccount({ username: otherUser, token: otherToken })
- )
- const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
- otherAccount.params["message"] = "all"
-
- await succeedOrThrow(() =>
- this.api.createTransaction({ username, token }, {
- payto_uri: stringifyPaytoUri(otherAccount),
- amount: userInfo.balance.amount
- })
- )
- //missing amount
- await failOrThrow("invalid-input", () =>
- this.api.createTransaction({ username, token }, {
- payto_uri: stringifyPaytoUri(otherAccount),
- // amount: userInfo.balance.amount
- })
- )
- //missing subject
- await failOrThrow("invalid-input", () =>
- this.api.createTransaction({ username, token }, {
- payto_uri: otherInfo.payto_uri,
- amount: userInfo.balance.amount
- })
- )
- await failOrThrow("unauthorized", () =>
- this.api.createTransaction({ username, token: "wrongtoken" as AccessToken }, {
- payto_uri: otherInfo.payto_uri,
- amount: userInfo.balance.amount
+ async testTransactions(adminPassword: string) {
+ const { access_token: adminToken } = await succeedOrThrow(() =>
+ this.api.getAuthenticationAPI("admin").createAccessToken(adminPassword, {
+ scope: "readwrite"
})
)
+ // get transactions
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+ // await succeedOrThrow(() => this.api.getTransactions(creds))
+ const txs = await succeedOrThrow(() => this.api.getTransactions({ username, token }, {
+ limit: 5,
+ order: "asc"
+ }))
+ // await failOrThrow("not-found",() => this.api.getTransactions({
+ // username:"not-found",
+ // token: creds.token,
+ // }))
+ await failOrThrow("unauthorized", () => this.api.getTransactions({
+ username: username,
+ token: "wrongtoken" as AccessToken,
+ }))
+ }
+
+ /**
+ * getTxby id
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+ const { username: otherUser, token: otherToken } = await createRandomTestUser(this.api, adminToken)
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+ const otherInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username: otherUser, token: otherToken })
+ )
+ const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+ otherAccount.params["message"] = "all"
+
+ await succeedOrThrow(() =>
+ this.api.createTransaction({ username, token }, {
+ payto_uri: stringifyPaytoUri(otherAccount),
+ amount: userInfo.balance.amount
+ })
+ )
+
+ const txs = await succeedOrThrow(() => this.api.getTransactions({ username, token }, {
+ limit: 5,
+ order: "asc"
+ }))
+ const rowId = txs.transactions[0].row_id
+
+ await succeedOrThrow(() =>
+ this.api.getTransactionById({ username, token }, rowId)
+ )
+
+ await failOrThrow("not-found", () =>
+ this.api.getTransactionById({ username, token }, 123123123)
+ )
+
+ await failOrThrow("unauthorized", () =>
+ this.api.getTransactionById({ username, token: "wrongtoken" as AccessToken }, 123123123)
+ )
+ }
+
+ /**
+ * create transactions
+ */
+ {
+ const { username, token } = await createRandomTestUser(this.api, adminToken)
+ const { username: otherUser, token: otherToken } = await createRandomTestUser(this.api, adminToken)
+
+ const userInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username, token })
+ )
+ const otherInfo = await succeedOrThrow(() =>
+ this.api.getAccount({ username: otherUser, token: otherToken })
+ )
+ const otherAccount = parsePaytoUri(otherInfo.payto_uri)!
+ otherAccount.params["message"] = "all"
+
+ await succeedOrThrow(() =>
+ this.api.createTransaction({ username, token }, {
+ payto_uri: stringifyPaytoUri(otherAccount),
+ amount: userInfo.balance.amount
+ })
+ )
+ //missing amount
+ await failOrThrow("invalid-input", () =>
+ this.api.createTransaction({ username, token }, {
+ payto_uri: stringifyPaytoUri(otherAccount),
+ // amount: userInfo.balance.amount
+ })
+ )
+ //missing subject
+ await failOrThrow("invalid-input", () =>
+ this.api.createTransaction({ username, token }, {
+ payto_uri: otherInfo.payto_uri,
+ amount: userInfo.balance.amount
+ })
+ )
+ await failOrThrow("unauthorized", () =>
+ this.api.createTransaction({ username, token: "wrongtoken" as AccessToken }, {
+ payto_uri: otherInfo.payto_uri,
+ amount: userInfo.balance.amount
+ })
+ )
+
+ const notFoundAccount = buildPayto("iban", "DE1231231231", undefined)
+ notFoundAccount.params["message"] = "not-found"
+ await failOrThrow("account-not-found", () =>
+ this.api.createTransaction({ username, token }, {
+ payto_uri: stringifyPaytoUri(notFoundAccount),
+ amount: userInfo.balance.amount
+ })
+ )
+ }
}
-}
}
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts
index e214f6dcd..35f216220 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -316,6 +316,7 @@ export class TalerCoreBankHttpClient {
//FIXME: remove this after server has been updated
case HttpStatusCode.Ok: return opEmptySuccess()
case HttpStatusCode.NoContent: return opEmptySuccess()
+ case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", resp);
//FIXME: check when the server add codes spec
case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp);
case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
@@ -344,6 +345,7 @@ export class TalerCoreBankHttpClient {
case HttpStatusCode.Ok: return opSuccess(resp, codecForBankAccountCreateWithdrawalResponse())
case HttpStatusCode.Conflict: return opKnownFailure("insufficient-funds", resp);
case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", resp);
//FIXME: remove when server is updated
case HttpStatusCode.Forbidden: return opKnownFailure("insufficient-funds", resp);
default: return opUnknownFailure(resp, await resp.text())
diff --git a/packages/taler-util/src/operation.ts b/packages/taler-util/src/operation.ts
index aab5dc022..8adbbb0e2 100644
--- a/packages/taler-util/src/operation.ts
+++ b/packages/taler-util/src/operation.ts
@@ -60,7 +60,7 @@ export async function failOrThrow<E>(s: E, cb: () => Promise<OperationResult<unk
if (resp.case === s) {
return resp.detail
}
- throw TalerError.fromException(new Error(`request failed but case "${s}" was expected`))
+ throw TalerError.fromException(new Error(`request failed with "${resp.case}" but case "${s}" was expected`))
}