summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-03-18 15:32:41 +0100
committerFlorian Dold <florian@dold.me>2022-03-21 19:20:48 +0100
commitf8d12f7b0d4af1b1769b89e80c87f9c169678564 (patch)
tree2478696c7bc1efc6d090b93aa340de542a7dccd9
parent32cd54e11d80bde0274b3c0238f8f5bd00ff83cb (diff)
downloadwallet-core-f8d12f7b0d4af1b1769b89e80c87f9c169678564.tar.gz
wallet-core-f8d12f7b0d4af1b1769b89e80c87f9c169678564.tar.bz2
wallet-core-f8d12f7b0d4af1b1769b89e80c87f9c169678564.zip
wallet: t_s/d_us migration
-rw-r--r--contrib/sample-data/history1.json402
-rw-r--r--packages/anastasis-core/src/index.ts28
-rw-r--r--packages/anastasis-core/src/reducer-types.ts11
-rw-r--r--packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx4
-rw-r--r--packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx4
-rw-r--r--packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx2
-rw-r--r--packages/taler-util/src/RequestThrottler.ts10
-rw-r--r--packages/taler-util/src/ReserveTransaction.ts96
-rw-r--r--packages/taler-util/src/backupTypes.ts74
-rw-r--r--packages/taler-util/src/talerTypes.ts51
-rw-r--r--packages/taler-util/src/time.ts356
-rw-r--r--packages/taler-util/src/transactionsTypes.ts4
-rw-r--r--packages/taler-util/src/types-test.ts16
-rw-r--r--packages/taler-util/src/walletTypes.ts14
-rw-r--r--packages/taler-wallet-cli/src/harness/harness.ts18
-rw-r--r--packages/taler-wallet-cli/src/harness/merchantApiTypes.ts12
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts4
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts24
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts5
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts2
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts15
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts10
-rw-r--r--packages/taler-wallet-core/src/bank-api-client.ts12
-rw-r--r--packages/taler-wallet-core/src/common.ts11
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/cryptoApi.ts2
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts16
-rw-r--r--packages/taler-wallet-core/src/db.ts100
-rw-r--r--packages/taler-wallet-core/src/dbless.ts9
-rw-r--r--packages/taler-wallet-core/src/operations/backup/export.ts11
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts10
-rw-r--r--packages/taler-wallet-core/src/operations/backup/index.ts40
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts59
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts66
-rw-r--r--packages/taler-wallet-core/src/operations/pay.ts33
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts42
-rw-r--r--packages/taler-wallet-core/src/operations/recoup.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts74
-rw-r--r--packages/taler-wallet-core/src/operations/refund.ts41
-rw-r--r--packages/taler-wallet-core/src/operations/reserves.ts19
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/tip.ts11
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts29
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.test.ts60
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts37
-rw-r--r--packages/taler-wallet-core/src/pending-types.ts11
-rw-r--r--packages/taler-wallet-core/src/util/http.ts17
-rw-r--r--packages/taler-wallet-core/src/util/retries.ts26
-rw-r--r--packages/taler-wallet-core/src/wallet.ts19
-rw-r--r--packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx62
-rw-r--r--packages/taler-wallet-webextension/src/components/PendingTransactions.tsx13
-rw-r--r--packages/taler-wallet-webextension/src/components/Time.tsx4
-rw-r--r--packages/taler-wallet-webextension/src/components/TransactionItem.tsx16
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip.stories.tsx9
-rw-r--r--packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx16
-rw-r--r--packages/taler-wallet-webextension/src/wallet/BackupPage.tsx18
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.stories.tsx7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx26
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx5
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx13
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.tsx20
62 files changed, 903 insertions, 1237 deletions
diff --git a/contrib/sample-data/history1.json b/contrib/sample-data/history1.json
deleted file mode 100644
index 8d0076a31..000000000
--- a/contrib/sample-data/history1.json
+++ /dev/null
@@ -1,402 +0,0 @@
-{
- "history": [
- {
- "type": "exchange-added",
- "builtIn": false,
- "eventId": "exchange-added;https%3A%2F%2Fexchange.demo.taler.net%2F",
- "exchangeBaseUrl": "https://exchange.demo.taler.net/",
- "timestamp": {
- "t_ms": 1578334008633
- }
- },
- {
- "type": "exchange-updated",
- "eventId": "exchange-updated;https%3A%2F%2Fexchange.demo.taler.net%2F",
- "exchangeBaseUrl": "https://exchange.demo.taler.net/",
- "timestamp": {
- "t_ms": 1578334009266
- }
- },
- {
- "type": "reserve-balance-updated",
- "eventId": "reserve-balance-updated;HHG1KBFSW4PM8J43D14GVJYB8F5J56RDHANY1EQSW6RTYDAQJC6G",
- "amountExpected": "KUDOS:5",
- "amountReserveBalance": "KUDOS:5",
- "timestamp": {
- "t_ms": 1578334039291
- },
- "newHistoryTransactions": [
- {
- "amount": "KUDOS:5",
- "sender_account_url": "payto://x-taler-bank/bank.demo.taler.net/65",
- "timestamp": {
- "t_ms": 1578334028000
- },
- "wire_reference": "000000000038Y",
- "type": "DEPOSIT"
- }
- ],
- "reserveShortInfo": {
- "exchangeBaseUrl": "https://exchange.demo.taler.net/",
- "reserveCreationDetail": {
- "type": "taler-bank-withdraw",
- "bankUrl": "https://bank.demo.taler.net/api/withdraw-operation/6fd6a78f-3d12-4c91-b5e4-c6fc31f44e8d"
- },
- "reservePub": "JPE7VR8R985WQ7ZX3EEYRTEGJQ1FAFE7P3JK1J7WFJEP7AGNTJD0"
- }
- },
- {
- "type": "withdrawn",
- "withdrawSessionId": "SFW3JS0JV0GZQQ1W07TNQEAGBD84X2QMH38PJ2CCTTKSDKQFCBY0",
- "eventId": "withdrawn;SFW3JS0JV0GZQQ1W07TNQEAGBD84X2QMH38PJ2CCTTKSDKQFCBY0",
- "amountWithdrawnEffective": "KUDOS:4.8",
- "amountWithdrawnRaw": "KUDOS:5",
- "exchangeBaseUrl": "https://exchange.demo.taler.net/",
- "timestamp": {
- "t_ms": 1578334039853
- },
- "withdrawalSource": {
- "type": "reserve",
- "reservePub": "JPE7VR8R985WQ7ZX3EEYRTEGJQ1FAFE7P3JK1J7WFJEP7AGNTJD0"
- }
- },
- {
- "type": "order-accepted",
- "eventId": "order-accepted;RNFEQ2FHF6NPM5M58HJH635TD4CE9S2SRNK3VN9SCMH3H7H0REBG",
- "orderShortInfo": {
- "amount": "KUDOS:0.5",
- "orderId": "2020.006-G1NT65XRPQ8GP",
- "merchantBaseUrl": "https://backend.demo.taler.net/public/instances/FSF/",
- "proposalId": "RNFEQ2FHF6NPM5M58HJH635TD4CE9S2SRNK3VN9SCMH3H7H0REBG",
- "summary": "Essay: 2. The GNU Project"
- },
- "timestamp": {
- "t_ms": 1578334078823
- }
- },
- {
- "type": "order-redirected",
- "eventId": "order-redirected;0W4EBHQJ90XX4TSQ9C0M6K9MBFJ1ENKTWH4R3CXFT986A2QHCESG",
- "alreadyPaidOrderShortInfo": {
- "amount": "KUDOS:0.5",
- "orderId": "2020.006-G1NT65XRPQ8GP",
- "merchantBaseUrl": "https://backend.demo.taler.net/public/instances/FSF/",
- "proposalId": "RNFEQ2FHF6NPM5M58HJH635TD4CE9S2SRNK3VN9SCMH3H7H0REBG",
- "summary": "Essay: 2. The GNU Project"
- },
- "newOrderShortInfo": {
- "amount": "KUDOS:0.5",
- "orderId": "2020.006-00W4ANVVKAHAP",
- "merchantBaseUrl": "https://backend.demo.taler.net/public/instances/FSF/",
- "proposalId": "0W4EBHQJ90XX4TSQ9C0M6K9MBFJ1ENKTWH4R3CXFT986A2QHCESG",
- "summary": "Essay: 2. The GNU Project"
- },
- "timestamp": {
- "t_ms": 1578334108380
- }
- },
- {
- "type": "payment-sent",
- "eventId": "payment-sent;RNFEQ2FHF6NPM5M58HJH635TD4CE9S2SRNK3VN9SCMH3H7H0REBG",
- "orderShortInfo": {
- "amount": "KUDOS:0.5",
- "orderId": "2020.006-G1NT65XRPQ8GP",
- "merchantBaseUrl": "https://backend.demo.taler.net/public/instances/FSF/",
- "proposalId": "RNFEQ2FHF6NPM5M58HJH635TD4CE9S2SRNK3VN9SCMH3H7H0REBG",
- "summary": "Essay: 2. The GNU Project"
- },
- "replay": true,
- "sessionId": "ab48396f-3aa1-4e1f-bfb5-30852d1e0d5e",
- "timestamp": {
- "t_ms": 1578334108677
- },
- "numCoins": 6,
- "amountPaidWithFees": "KUDOS:0.54"
- },
- {
- "type": "exchange-added",
- "builtIn": false,
- "eventId": "exchange-added;https%3A%2F%2Fexchange.test.taler.net%2F",
- "exchangeBaseUrl": "https://exchange.test.taler.net/",
- "timestamp": {
- "t_ms": 1578334134741
- }
- },
- {
- "type": "exchange-updated",
- "eventId": "exchange-updated;https%3A%2F%2Fexchange.test.taler.net%2F",
- "exchangeBaseUrl": "https://exchange.test.taler.net/",
- "timestamp": {
- "t_ms": 1578334135451
- }
- },
- {
- "type": "reserve-balance-updated",
- "eventId": "reserve-balance-updated;498DDH4ZB41QX45FH38T4Y8JM14WX8Q2J1VKKZTE0CMS6TCPYZAG",
- "amountExpected": "TESTKUDOS:5",
- "amountReserveBalance": "TESTKUDOS:5",
- "timestamp": {
- "t_ms": 1578334141843
- },
- "newHistoryTransactions": [
- {
- "amount": "TESTKUDOS:5",
- "sender_account_url": "payto://x-taler-bank/bank.test.taler.net/9",
- "timestamp": {
- "t_ms": 1578334138000
- },
- "wire_reference": "0000000000184",
- "type": "DEPOSIT"
- }
- ],
- "reserveShortInfo": {
- "exchangeBaseUrl": "https://exchange.test.taler.net/",
- "reserveCreationDetail": {
- "type": "taler-bank-withdraw",
- "bankUrl": "https://bank.test.taler.net/api/withdraw-operation/e6210f62-d27b-4f58-815c-c5160de8804c"
- },
- "reservePub": "ZQ2N7V8M035HAD1HTW7ZX22NM9GAXDCGX6GSJECD2KEY9TN3C0V0"
- }
- },
- {
- "type": "withdrawn",
- "withdrawSessionId": "AAVX0GVZ8GRPYX2RWANQ9J279ABA7KNFYEQ3A0C63TW7NMV0GAT0",
- "eventId": "withdrawn;AAVX0GVZ8GRPYX2RWANQ9J279ABA7KNFYEQ3A0C63TW7NMV0GAT0",
- "amountWithdrawnEffective": "TESTKUDOS:5",
- "amountWithdrawnRaw": "TESTKUDOS:5",
- "exchangeBaseUrl": "https://exchange.test.taler.net/",
- "timestamp": {
- "t_ms": 1578334142432
- },
- "withdrawalSource": {
- "type": "reserve",
- "reservePub": "ZQ2N7V8M035HAD1HTW7ZX22NM9GAXDCGX6GSJECD2KEY9TN3C0V0"
- }
- },
- {
- "type": "refreshed",
- "refreshGroupId": "2TARBASBNCE0X7F0D89Z3TJGPXKRARFSBH3HKZ5JFQRKPV9CA5C0",
- "eventId": "refreshed;2TARBASBNCE0X7F0D89Z3TJGPXKRARFSBH3HKZ5JFQRKPV9CA5C0",
- "timestamp": {
- "t_ms": 1578334142528
- },
- "refreshReason": "pay",
- "amountRefreshedEffective": "KUDOS:0",
- "amountRefreshedRaw": "KUDOS:0.06",
- "numInputCoins": 6,
- "numOutputCoins": 0,
- "numRefreshedInputCoins": 0
- },
- {
- "type": "order-accepted",
- "eventId": "order-accepted;W39MQT31M1ZY3NPF9ZSGXM8Q1K5XS5D5R1J10ZSHBREC6EZ570F0",
- "orderShortInfo": {
- "amount": "TESTKUDOS:1",
- "orderId": "2020.006-00GBW7AD1VFRW",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/GNUnet/",
- "proposalId": "W39MQT31M1ZY3NPF9ZSGXM8Q1K5XS5D5R1J10ZSHBREC6EZ570F0",
- "summary": "Donation to GNUnet"
- },
- "timestamp": {
- "t_ms": 1578334230099
- }
- },
- {
- "type": "payment-sent",
- "eventId": "payment-sent;W39MQT31M1ZY3NPF9ZSGXM8Q1K5XS5D5R1J10ZSHBREC6EZ570F0",
- "orderShortInfo": {
- "amount": "TESTKUDOS:1",
- "orderId": "2020.006-00GBW7AD1VFRW",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/GNUnet/",
- "proposalId": "W39MQT31M1ZY3NPF9ZSGXM8Q1K5XS5D5R1J10ZSHBREC6EZ570F0",
- "summary": "Donation to GNUnet"
- },
- "replay": false,
- "timestamp": {
- "t_ms": 1578334232527
- },
- "numCoins": 4,
- "amountPaidWithFees": "TESTKUDOS:1"
- },
- {
- "type": "order-accepted",
- "eventId": "order-accepted;Y8230SR6DP52J61CHEAPM5NHRVK408YP5KJP6VRBGZ3QZ0TBZQ90",
- "orderShortInfo": {
- "amount": "TESTKUDOS:0.1",
- "orderId": "2020.006-02RFGFSSAZY9Y",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/Taler/",
- "proposalId": "Y8230SR6DP52J61CHEAPM5NHRVK408YP5KJP6VRBGZ3QZ0TBZQ90",
- "summary": "Donation to Taler"
- },
- "timestamp": {
- "t_ms": 1578334258703
- }
- },
- {
- "type": "payment-sent",
- "eventId": "payment-sent;Y8230SR6DP52J61CHEAPM5NHRVK408YP5KJP6VRBGZ3QZ0TBZQ90",
- "orderShortInfo": {
- "amount": "TESTKUDOS:0.1",
- "orderId": "2020.006-02RFGFSSAZY9Y",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/Taler/",
- "proposalId": "Y8230SR6DP52J61CHEAPM5NHRVK408YP5KJP6VRBGZ3QZ0TBZQ90",
- "summary": "Donation to Taler"
- },
- "replay": false,
- "timestamp": {
- "t_ms": 1578334260497
- },
- "numCoins": 1,
- "amountPaidWithFees": "TESTKUDOS:0.1"
- },
- {
- "type": "reserve-balance-updated",
- "eventId": "reserve-balance-updated;NBZX24YB4GEHFXFXD5NJAC84ZZD63DFAD6Q7YFJQGX8WX9YQ7B90",
- "amountExpected": "TESTKUDOS:15",
- "amountReserveBalance": "TESTKUDOS:15",
- "timestamp": {
- "t_ms": 1578334530519
- },
- "newHistoryTransactions": [
- {
- "amount": "TESTKUDOS:15",
- "sender_account_url": "payto://x-taler-bank/bank.test.taler.net/9",
- "timestamp": {
- "t_ms": 1578334522000
- },
- "wire_reference": "000000000018C",
- "type": "DEPOSIT"
- }
- ],
- "reserveShortInfo": {
- "exchangeBaseUrl": "https://exchange.test.taler.net/",
- "reserveCreationDetail": {
- "type": "taler-bank-withdraw",
- "bankUrl": "https://bank.test.taler.net/api/withdraw-operation/6b5fae55-3634-4e6b-a877-2f8bd76dfaf9"
- },
- "reservePub": "5XZC4DQMNR3482443727Q2RNKRVEBEW7SFJ8N9TYV5AZ74AZJB4G"
- }
- },
- {
- "type": "withdrawn",
- "withdrawSessionId": "312AKNY5BGF08PY1ZK0Z2QBEZ3481NFP9BN36Z08FHJQQZW80EZG",
- "eventId": "withdrawn;312AKNY5BGF08PY1ZK0Z2QBEZ3481NFP9BN36Z08FHJQQZW80EZG",
- "amountWithdrawnEffective": "TESTKUDOS:15",
- "amountWithdrawnRaw": "TESTKUDOS:15",
- "exchangeBaseUrl": "https://exchange.test.taler.net/",
- "timestamp": {
- "t_ms": 1578334531085
- },
- "withdrawalSource": {
- "type": "reserve",
- "reservePub": "5XZC4DQMNR3482443727Q2RNKRVEBEW7SFJ8N9TYV5AZ74AZJB4G"
- }
- },
- {
- "type": "refreshed",
- "refreshGroupId": "3FN9PFD2JCPS3FDHZDPRS50VQT4G7SE54JDTG2ZW2HV1R3PJ9KBG",
- "eventId": "refreshed;3FN9PFD2JCPS3FDHZDPRS50VQT4G7SE54JDTG2ZW2HV1R3PJ9KBG",
- "timestamp": {
- "t_ms": 1578334532478
- },
- "refreshReason": "pay",
- "amountRefreshedEffective": "TESTKUDOS:2.46",
- "amountRefreshedRaw": "TESTKUDOS:2.46",
- "numInputCoins": 1,
- "numOutputCoins": 6,
- "numRefreshedInputCoins": 1
- },
- {
- "type": "refreshed",
- "refreshGroupId": "DF0DQ6MGJ39R0891B0P86MY2QTMPF9FPDJN30PRBMXBZ8XEVHZE0",
- "eventId": "refreshed;DF0DQ6MGJ39R0891B0P86MY2QTMPF9FPDJN30PRBMXBZ8XEVHZE0",
- "timestamp": {
- "t_ms": 1578334533177
- },
- "refreshReason": "pay",
- "amountRefreshedEffective": "TESTKUDOS:1.12",
- "amountRefreshedRaw": "TESTKUDOS:1.12",
- "numInputCoins": 4,
- "numOutputCoins": 3,
- "numRefreshedInputCoins": 1
- },
- {
- "type": "order-accepted",
- "eventId": "order-accepted;KYSVHAENJFQB308KF6ENPM46VJRFAXFRDGW856P7MM90AW60REZ0",
- "orderShortInfo": {
- "amount": "TESTKUDOS:0.5",
- "orderId": "2020.006-03WSPCDEZK6HG",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/FSF/",
- "proposalId": "KYSVHAENJFQB308KF6ENPM46VJRFAXFRDGW856P7MM90AW60REZ0",
- "summary": "Essay: 6. Why Software Should Be Free"
- },
- "timestamp": {
- "t_ms": 1578334554161
- }
- },
- {
- "type": "payment-sent",
- "eventId": "payment-sent;KYSVHAENJFQB308KF6ENPM46VJRFAXFRDGW856P7MM90AW60REZ0",
- "orderShortInfo": {
- "amount": "TESTKUDOS:0.5",
- "orderId": "2020.006-03WSPCDEZK6HG",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/FSF/",
- "proposalId": "KYSVHAENJFQB308KF6ENPM46VJRFAXFRDGW856P7MM90AW60REZ0",
- "summary": "Essay: 6. Why Software Should Be Free"
- },
- "replay": false,
- "sessionId": "489c048b-7702-49e8-b66f-2de5e33f0008",
- "timestamp": {
- "t_ms": 1578334556292
- },
- "numCoins": 5,
- "amountPaidWithFees": "TESTKUDOS:0.5"
- },
- {
- "type": "refreshed",
- "refreshGroupId": "NG8Z05Q8CM7KCC98PDNDQR0G920J2SGYM15ACBV0PMBE6XA8Q87G",
- "eventId": "refreshed;NG8Z05Q8CM7KCC98PDNDQR0G920J2SGYM15ACBV0PMBE6XA8Q87G",
- "timestamp": {
- "t_ms": 1578334568850
- },
- "refreshReason": "pay",
- "amountRefreshedEffective": "TESTKUDOS:0.06",
- "amountRefreshedRaw": "TESTKUDOS:0.06",
- "numInputCoins": 5,
- "numOutputCoins": 2,
- "numRefreshedInputCoins": 1
- },
- {
- "type": "refund",
- "eventId": "refund;FRW9DGXKPFS9HZEGFYMABDF6FRXDYNMFHH23FT71AAKN8FHGV2EG",
- "refundGroupId": "FRW9DGXKPFS9HZEGFYMABDF6FRXDYNMFHH23FT71AAKN8FHGV2EG",
- "orderShortInfo": {
- "amount": "TESTKUDOS:0.5",
- "orderId": "2020.006-03WSPCDEZK6HG",
- "merchantBaseUrl": "https://backend.test.taler.net/public/instances/FSF/",
- "proposalId": "KYSVHAENJFQB308KF6ENPM46VJRFAXFRDGW856P7MM90AW60REZ0",
- "summary": "Essay: 6. Why Software Should Be Free"
- },
- "timestamp": {
- "t_ms": 1578334581129
- },
- "amountRefundedEffective": "TESTKUDOS:0.5",
- "amountRefundedRaw": "TESTKUDOS:0.5",
- "amountRefundedInvalid": "TESTKUDOS:0"
- },
- {
- "type": "refreshed",
- "refreshGroupId": "TY8G0FDE83YJY3CWBYKMV891CADG06X8MTBZHE42XNQV2B2C95RG",
- "eventId": "refreshed;TY8G0FDE83YJY3CWBYKMV891CADG06X8MTBZHE42XNQV2B2C95RG",
- "timestamp": {
- "t_ms": 1578334585583
- },
- "refreshReason": "refund",
- "amountRefreshedEffective": "TESTKUDOS:0.5",
- "amountRefreshedRaw": "TESTKUDOS:0.5",
- "numInputCoins": 5,
- "numOutputCoins": 6,
- "numRefreshedInputCoins": 5
- }
- ]
-}
diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts
index 15e1e5d97..d1afc706b 100644
--- a/packages/anastasis-core/src/index.ts
+++ b/packages/anastasis-core/src/index.ts
@@ -19,8 +19,9 @@ import {
parsePayUri,
stringToBytes,
TalerErrorCode,
+ TalerProtocolTimestamp,
TalerSignaturePurpose,
- Timestamp,
+ AbsoluteTime,
} from "@gnu-taler/taler-util";
import { anastasisData } from "./anastasis-data.js";
import {
@@ -631,15 +632,13 @@ async function uploadSecret(
logger.info(`got response for policy upload (http status ${resp.status})`);
if (resp.status === HttpStatusCode.NoContent) {
let policyVersion = 0;
- let policyExpiration: Timestamp = { t_ms: 0 };
+ let policyExpiration: TalerProtocolTimestamp = { t_s: 0 };
try {
policyVersion = Number(resp.headers.get("Anastasis-Version") ?? "0");
} catch (e) {}
try {
policyExpiration = {
- t_ms:
- 1000 *
- Number(resp.headers.get("Anastasis-Policy-Expiration") ?? "0"),
+ t_s: Number(resp.headers.get("Anastasis-Policy-Expiration") ?? "0"),
};
} catch (e) {}
successDetails[prov.provider_url] = {
@@ -1187,7 +1186,7 @@ async function addProviderBackup(
state: ReducerStateBackup,
args: ActionArgsAddProvider,
): Promise<ReducerStateBackup> {
- const info = await getProviderInfo(args.provider_url)
+ const info = await getProviderInfo(args.provider_url);
return {
...state,
authentication_providers: {
@@ -1202,8 +1201,10 @@ async function deleteProviderBackup(
state: ReducerStateBackup,
args: ActionArgsDeleteProvider,
): Promise<ReducerStateBackup> {
- const authentication_providers = {... state.authentication_providers ?? {} }
- delete authentication_providers[args.provider_url]
+ const authentication_providers = {
+ ...(state.authentication_providers ?? {}),
+ };
+ delete authentication_providers[args.provider_url];
return {
...state,
authentication_providers,
@@ -1214,7 +1215,7 @@ async function addProviderRecovery(
state: ReducerStateRecovery,
args: ActionArgsAddProvider,
): Promise<ReducerStateRecovery> {
- const info = await getProviderInfo(args.provider_url)
+ const info = await getProviderInfo(args.provider_url);
return {
...state,
authentication_providers: {
@@ -1228,8 +1229,10 @@ async function deleteProviderRecovery(
state: ReducerStateRecovery,
args: ActionArgsDeleteProvider,
): Promise<ReducerStateRecovery> {
- const authentication_providers = {... state.authentication_providers ?? {} }
- delete authentication_providers[args.provider_url]
+ const authentication_providers = {
+ ...(state.authentication_providers ?? {}),
+ };
+ delete authentication_providers[args.provider_url];
return {
...state,
authentication_providers,
@@ -1347,7 +1350,8 @@ async function updateUploadFees(
x,
).amount;
};
- const years = Duration.toIntegerYears(Duration.getRemaining(expiration));
+ const expirationTime = AbsoluteTime.fromTimestamp(expiration);
+ const years = Duration.toIntegerYears(Duration.getRemaining(expirationTime));
logger.info(`computing fees for ${years} years`);
// For now, we compute fees for *all* available providers.
for (const provUrl in state.authentication_providers ?? {}) {
diff --git a/packages/anastasis-core/src/reducer-types.ts b/packages/anastasis-core/src/reducer-types.ts
index 8d375552f..2a869fe47 100644
--- a/packages/anastasis-core/src/reducer-types.ts
+++ b/packages/anastasis-core/src/reducer-types.ts
@@ -7,7 +7,8 @@ import {
codecForString,
codecForTimestamp,
Duration,
- Timestamp,
+ TalerProtocolTimestamp,
+ AbsoluteTime,
} from "@gnu-taler/taler-util";
import { ChallengeFeedback } from "./challenge-feedback-types.js";
import { KeyShare } from "./crypto.js";
@@ -43,7 +44,7 @@ export interface PolicyProvider {
export interface SuccessDetails {
[provider_url: string]: {
policy_version: number;
- policy_expiration: Timestamp;
+ policy_expiration: TalerProtocolTimestamp;
};
}
@@ -112,7 +113,7 @@ export interface ReducerStateBackup {
core_secret?: CoreSecret;
- expiration?: Timestamp;
+ expiration?: TalerProtocolTimestamp;
upload_fees?: { fee: AmountString }[];
@@ -369,7 +370,7 @@ export interface ActionArgsEnterSecret {
value: string;
mime?: string;
};
- expiration: Timestamp;
+ expiration: TalerProtocolTimestamp;
}
export interface ActionArgsSelectContinent {
@@ -438,7 +439,7 @@ export interface ActionArgsAddPolicy {
}
export interface ActionArgsUpdateExpiration {
- expiration: Timestamp;
+ expiration: TalerProtocolTimestamp;
}
export interface ActionArgsChangeVersion {
diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
index bb0c3c4b6..1c6ae4b22 100644
--- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
@@ -51,13 +51,13 @@ export const WithDetails = createExample(TestedComponent, {
success_details: {
"https://anastasis.demo.taler.net/": {
policy_expiration: {
- t_ms: "never",
+ t_s: "never",
},
policy_version: 0,
},
"https://kudos.demo.anastasis.lu/": {
policy_expiration: {
- t_ms: new Date().getTime() + 60 * 60 * 24 * 1000,
+ t_s: new Date().getTime() + 60 * 60 * 24,
},
policy_version: 1,
},
diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
index 66473345f..d6272d843 100644
--- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
@@ -35,9 +35,9 @@ export function BackupFinishedScreen(): VNode {
</a>
<p>
version {sd.policy_version}
- {sd.policy_expiration.t_ms !== "never"
+ {sd.policy_expiration.t_s !== "never"
? ` expires at: ${format(
- new Date(sd.policy_expiration.t_ms),
+ new Date(sd.policy_expiration.t_s),
"dd-MM-yyyy",
)}`
: " without expiration date"}
diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
index e401c3d73..d9bf084ab 100644
--- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
@@ -52,7 +52,7 @@ export function SecretEditorScreen(): VNode {
await tx.transition("enter_secret", {
secret,
expiration: {
- t_ms: new Date().getTime() + 1000 * 60 * 60 * 24 * 365 * 5,
+ t_s: new Date().getTime() + 60 * 60 * 24 * 365 * 5,
},
});
await tx.transition("next", {});
diff --git a/packages/taler-util/src/RequestThrottler.ts b/packages/taler-util/src/RequestThrottler.ts
index 7689b4215..a151cc634 100644
--- a/packages/taler-util/src/RequestThrottler.ts
+++ b/packages/taler-util/src/RequestThrottler.ts
@@ -15,7 +15,7 @@
*/
import { Logger } from "./logging.js";
-import { getTimestampNow, timestampCmp, timestampDifference } from "./time.js";
+import { AbsoluteTime } from "./time.js";
/**
* Implementation of token bucket throttling.
@@ -46,16 +46,16 @@ class OriginState {
tokensSecond: number = MAX_PER_SECOND;
tokensMinute: number = MAX_PER_MINUTE;
tokensHour: number = MAX_PER_HOUR;
- private lastUpdate = getTimestampNow();
+ private lastUpdate = AbsoluteTime.now();
private refill(): void {
- const now = getTimestampNow();
- if (timestampCmp(now, this.lastUpdate) < 0) {
+ const now = AbsoluteTime.now();
+ if (AbsoluteTime.cmp(now, this.lastUpdate) < 0) {
// Did the system time change?
this.lastUpdate = now;
return;
}
- const d = timestampDifference(now, this.lastUpdate);
+ const d = AbsoluteTime.difference(now, this.lastUpdate);
if (d.d_ms === "forever") {
throw Error("assertion failed");
}
diff --git a/packages/taler-util/src/ReserveTransaction.ts b/packages/taler-util/src/ReserveTransaction.ts
index b282ef189..50610483f 100644
--- a/packages/taler-util/src/ReserveTransaction.ts
+++ b/packages/taler-util/src/ReserveTransaction.ts
@@ -38,7 +38,11 @@ import {
EddsaPublicKeyString,
CoinPublicKeyString,
} from "./talerTypes";
-import { Timestamp, codecForTimestamp } from "./time.js";
+import {
+ AbsoluteTime,
+ codecForTimestamp,
+ TalerProtocolTimestamp,
+} from "./time.js";
export enum ReserveTransactionType {
Withdraw = "WITHDRAW",
@@ -98,7 +102,7 @@ export interface ReserveCreditTransaction {
/**
* Timestamp of the incoming wire transfer.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
}
export interface ReserveClosingTransaction {
@@ -139,7 +143,7 @@ export interface ReserveClosingTransaction {
/**
* Time when the reserve was closed.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
}
export interface ReserveRecoupTransaction {
@@ -165,7 +169,7 @@ export interface ReserveRecoupTransaction {
/**
* Time when the funds were paid back into the reserve.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
/**
* Public key of the coin that was paid back.
@@ -182,46 +186,50 @@ export type ReserveTransaction =
| ReserveClosingTransaction
| ReserveRecoupTransaction;
-export const codecForReserveWithdrawTransaction = (): Codec<ReserveWithdrawTransaction> =>
- buildCodecForObject<ReserveWithdrawTransaction>()
- .property("amount", codecForString())
- .property("h_coin_envelope", codecForString())
- .property("h_denom_pub", codecForString())
- .property("reserve_sig", codecForString())
- .property("type", codecForConstString(ReserveTransactionType.Withdraw))
- .property("withdraw_fee", codecForString())
- .build("ReserveWithdrawTransaction");
-
-export const codecForReserveCreditTransaction = (): Codec<ReserveCreditTransaction> =>
- buildCodecForObject<ReserveCreditTransaction>()
- .property("amount", codecForString())
- .property("sender_account_url", codecForString())
- .property("timestamp", codecForTimestamp)
- .property("wire_reference", codecForNumber())
- .property("type", codecForConstString(ReserveTransactionType.Credit))
- .build("ReserveCreditTransaction");
-
-export const codecForReserveClosingTransaction = (): Codec<ReserveClosingTransaction> =>
- buildCodecForObject<ReserveClosingTransaction>()
- .property("amount", codecForString())
- .property("closing_fee", codecForString())
- .property("exchange_pub", codecForString())
- .property("exchange_sig", codecForString())
- .property("h_wire", codecForString())
- .property("timestamp", codecForTimestamp)
- .property("type", codecForConstString(ReserveTransactionType.Closing))
- .property("wtid", codecForString())
- .build("ReserveClosingTransaction");
-
-export const codecForReserveRecoupTransaction = (): Codec<ReserveRecoupTransaction> =>
- buildCodecForObject<ReserveRecoupTransaction>()
- .property("amount", codecForString())
- .property("coin_pub", codecForString())
- .property("exchange_pub", codecForString())
- .property("exchange_sig", codecForString())
- .property("timestamp", codecForTimestamp)
- .property("type", codecForConstString(ReserveTransactionType.Recoup))
- .build("ReserveRecoupTransaction");
+export const codecForReserveWithdrawTransaction =
+ (): Codec<ReserveWithdrawTransaction> =>
+ buildCodecForObject<ReserveWithdrawTransaction>()
+ .property("amount", codecForString())
+ .property("h_coin_envelope", codecForString())
+ .property("h_denom_pub", codecForString())
+ .property("reserve_sig", codecForString())
+ .property("type", codecForConstString(ReserveTransactionType.Withdraw))
+ .property("withdraw_fee", codecForString())
+ .build("ReserveWithdrawTransaction");
+
+export const codecForReserveCreditTransaction =
+ (): Codec<ReserveCreditTransaction> =>
+ buildCodecForObject<ReserveCreditTransaction>()
+ .property("amount", codecForString())
+ .property("sender_account_url", codecForString())
+ .property("timestamp", codecForTimestamp)
+ .property("wire_reference", codecForNumber())
+ .property("type", codecForConstString(ReserveTransactionType.Credit))
+ .build("ReserveCreditTransaction");
+
+export const codecForReserveClosingTransaction =
+ (): Codec<ReserveClosingTransaction> =>
+ buildCodecForObject<ReserveClosingTransaction>()
+ .property("amount", codecForString())
+ .property("closing_fee", codecForString())
+ .property("exchange_pub", codecForString())
+ .property("exchange_sig", codecForString())
+ .property("h_wire", codecForString())
+ .property("timestamp", codecForTimestamp)
+ .property("type", codecForConstString(ReserveTransactionType.Closing))
+ .property("wtid", codecForString())
+ .build("ReserveClosingTransaction");
+
+export const codecForReserveRecoupTransaction =
+ (): Codec<ReserveRecoupTransaction> =>
+ buildCodecForObject<ReserveRecoupTransaction>()
+ .property("amount", codecForString())
+ .property("coin_pub", codecForString())
+ .property("exchange_pub", codecForString())
+ .property("exchange_sig", codecForString())
+ .property("timestamp", codecForTimestamp)
+ .property("type", codecForConstString(ReserveTransactionType.Recoup))
+ .build("ReserveRecoupTransaction");
export const codecForReserveTransaction = (): Codec<ReserveTransaction> =>
buildCodecForUnion<ReserveTransaction>()
diff --git a/packages/taler-util/src/backupTypes.ts b/packages/taler-util/src/backupTypes.ts
index 41a9ce98e..b31a83831 100644
--- a/packages/taler-util/src/backupTypes.ts
+++ b/packages/taler-util/src/backupTypes.ts
@@ -54,7 +54,7 @@
* Imports.
*/
import { DenominationPubKey, UnblindedSignature } from "./talerTypes.js";
-import { Duration, Timestamp } from "./time.js";
+import { TalerProtocolDuration, TalerProtocolTimestamp } from "./time.js";
/**
* Type alias for strings that are to be treated like amounts.
@@ -120,7 +120,7 @@ export interface WalletBackupContentV1 {
* This timestamp should only be advanced if the content
* of the backup changes.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
/**
* Per-exchange data sorted by exchange master public key.
@@ -333,10 +333,10 @@ export interface BackupRecoupGroup {
/**
* Timestamp when the recoup was started.
*/
- timestamp_created: Timestamp;
+ timestamp_created: TalerProtocolTimestamp;
- timestamp_finish?: Timestamp;
- finish_clock?: Timestamp;
+ timestamp_finish?: TalerProtocolTimestamp;
+ finish_clock?: TalerProtocolTimestamp;
finish_is_failure?: boolean;
/**
@@ -486,14 +486,14 @@ export interface BackupTip {
* Has the user accepted the tip? Only after the tip has been accepted coins
* withdrawn from the tip may be used.
*/
- timestamp_accepted: Timestamp | undefined;
+ timestamp_accepted: TalerProtocolTimestamp | undefined;
/**
* When was the tip first scanned by the wallet?
*/
- timestamp_created: Timestamp;
+ timestamp_created: TalerProtocolTimestamp;
- timestamp_finished?: Timestamp;
+ timestamp_finished?: TalerProtocolTimestamp;
finish_is_failure?: boolean;
/**
@@ -504,7 +504,7 @@ export interface BackupTip {
/**
* Timestamp, the tip can't be picked up anymore after this deadline.
*/
- timestamp_expiration: Timestamp;
+ timestamp_expiration: TalerProtocolTimestamp;
/**
* The exchange that will sign our coins, chosen by the merchant.
@@ -613,9 +613,9 @@ export interface BackupRefreshGroup {
*/
old_coins: BackupRefreshOldCoin[];
- timestamp_created: Timestamp;
+ timestamp_created: TalerProtocolTimestamp;
- timestamp_finish?: Timestamp;
+ timestamp_finish?: TalerProtocolTimestamp;
finish_is_failure?: boolean;
}
@@ -636,9 +636,9 @@ export interface BackupWithdrawalGroup {
* When was the withdrawal operation started started?
* Timestamp in milliseconds.
*/
- timestamp_created: Timestamp;
+ timestamp_created: TalerProtocolTimestamp;
- timestamp_finish?: Timestamp;
+ timestamp_finish?: TalerProtocolTimestamp;
finish_is_failure?: boolean;
/**
@@ -672,12 +672,12 @@ export interface BackupRefundItemCommon {
/**
* Execution time as claimed by the merchant
*/
- execution_time: Timestamp;
+ execution_time: TalerProtocolTimestamp;
/**
* Time when the wallet became aware of the refund.
*/
- obtained_time: Timestamp;
+ obtained_time: TalerProtocolTimestamp;
/**
* Amount refunded for the coin.
@@ -788,7 +788,7 @@ export interface BackupPurchase {
* Timestamp of the first time that sending a payment to the merchant
* for this purchase was successful.
*/
- timestamp_first_successful_pay: Timestamp | undefined;
+ timestamp_first_successful_pay: TalerProtocolTimestamp | undefined;
/**
* Signature by the merchant confirming the payment.
@@ -799,7 +799,7 @@ export interface BackupPurchase {
* When was the purchase made?
* Refers to the time that the user accepted.
*/
- timestamp_accept: Timestamp;
+ timestamp_accept: TalerProtocolTimestamp;
/**
* Pending refunds for the purchase. A refund is pending
@@ -815,7 +815,7 @@ export interface BackupPurchase {
/**
* Continue querying the refund status until this deadline has expired.
*/
- auto_refund_deadline: Timestamp | undefined;
+ auto_refund_deadline: TalerProtocolTimestamp | undefined;
}
/**
@@ -857,22 +857,22 @@ export interface BackupDenomination {
/**
* Validity start date of the denomination.
*/
- stamp_start: Timestamp;
+ stamp_start: TalerProtocolTimestamp;
/**
* Date after which the currency can't be withdrawn anymore.
*/
- stamp_expire_withdraw: Timestamp;
+ stamp_expire_withdraw: TalerProtocolTimestamp;
/**
* Date after the denomination officially doesn't exist anymore.
*/
- stamp_expire_legal: Timestamp;
+ stamp_expire_legal: TalerProtocolTimestamp;
/**
* Data after which coins of this denomination can't be deposited anymore.
*/
- stamp_expire_deposit: Timestamp;
+ stamp_expire_deposit: TalerProtocolTimestamp;
/**
* Signature by the exchange's master key over the denomination
@@ -903,7 +903,7 @@ export interface BackupDenomination {
* The list issue date of the exchange "/keys" response
* that this denomination was last seen in.
*/
- list_issue_date: Timestamp;
+ list_issue_date: TalerProtocolTimestamp;
}
/**
@@ -923,14 +923,14 @@ export interface BackupReserve {
/**
* Time when the reserve was created.
*/
- timestamp_created: Timestamp;
+ timestamp_created: TalerProtocolTimestamp;
/**
* Timestamp of the last observed activity.
*
* Used to compute when to give up querying the exchange.
*/
- timestamp_last_activity: Timestamp;
+ timestamp_last_activity: TalerProtocolTimestamp;
/**
* Timestamp of when the reserve closed.
@@ -938,7 +938,7 @@ export interface BackupReserve {
* Note that the last activity can be after the closing time
* due to recouping.
*/
- timestamp_closed?: Timestamp;
+ timestamp_closed?: TalerProtocolTimestamp;
/**
* Wire information (as payto URI) for the bank account that
@@ -977,14 +977,14 @@ export interface BackupReserve {
/**
* Time when the information about this reserve was posted to the bank.
*/
- timestamp_reserve_info_posted: Timestamp | undefined;
+ timestamp_reserve_info_posted: TalerProtocolTimestamp | undefined;
/**
* Time when the reserve was confirmed by the bank.
*
* Set to undefined if not confirmed yet.
*/
- timestamp_bank_confirmed: Timestamp | undefined;
+ timestamp_bank_confirmed: TalerProtocolTimestamp | undefined;
};
/**
@@ -1033,12 +1033,12 @@ export interface BackupExchangeWireFee {
/**
* Start date of the fee.
*/
- start_stamp: Timestamp;
+ start_stamp: TalerProtocolTimestamp;
/**
* End date of the fee.
*/
- end_stamp: Timestamp;
+ end_stamp: TalerProtocolTimestamp;
/**
* Signature made by the exchange master key.
@@ -1050,9 +1050,9 @@ export interface BackupExchangeWireFee {
* Structure of one exchange signing key in the /keys response.
*/
export class BackupExchangeSignKey {
- stamp_start: Timestamp;
- stamp_expire: Timestamp;
- stamp_end: Timestamp;
+ stamp_start: TalerProtocolTimestamp;
+ stamp_expire: TalerProtocolTimestamp;
+ stamp_end: TalerProtocolTimestamp;
key: string;
master_sig: string;
}
@@ -1112,7 +1112,7 @@ export interface BackupExchange {
*
* Used to facilitate automatic merging.
*/
- update_clock: Timestamp;
+ update_clock: TalerProtocolTimestamp;
}
/**
@@ -1161,7 +1161,7 @@ export interface BackupExchangeDetails {
/**
* Closing delay of reserves.
*/
- reserve_closing_delay: Duration;
+ reserve_closing_delay: TalerProtocolDuration;
/**
* Signing keys we got from the exchange, can also contain
@@ -1187,7 +1187,7 @@ export interface BackupExchangeDetails {
/**
* Timestamp when the ToS has been accepted.
*/
- tos_accepted_timestamp: Timestamp | undefined;
+ tos_accepted_timestamp: TalerProtocolTimestamp | undefined;
}
export enum BackupProposalStatus {
@@ -1248,7 +1248,7 @@ export interface BackupProposal {
* Timestamp of when the record
* was created.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
/**
* Private key for the nonce.
diff --git a/packages/taler-util/src/talerTypes.ts b/packages/taler-util/src/talerTypes.ts
index 4ccfffce0..b1bf6ab38 100644
--- a/packages/taler-util/src/talerTypes.ts
+++ b/packages/taler-util/src/talerTypes.ts
@@ -38,15 +38,14 @@ import {
codecForConstNumber,
buildCodecForUnion,
codecForConstString,
- codecForEither,
} from "./codec.js";
import {
- Timestamp,
codecForTimestamp,
- Duration,
codecForDuration,
+ TalerProtocolTimestamp,
+ TalerProtocolDuration,
} from "./time.js";
-import { Amounts, codecForAmountString } from "./amounts.js";
+import { codecForAmountString } from "./amounts.js";
import { strcmp } from "./helpers.js";
/**
@@ -86,24 +85,24 @@ export class ExchangeDenomination {
/**
* Start date from which withdraw is allowed.
*/
- stamp_start: Timestamp;
+ stamp_start: TalerProtocolTimestamp;
/**
* End date for withdrawing.
*/
- stamp_expire_withdraw: Timestamp;
+ stamp_expire_withdraw: TalerProtocolTimestamp;
/**
* Expiration date after which the exchange can forget about
* the currency.
*/
- stamp_expire_legal: Timestamp;
+ stamp_expire_legal: TalerProtocolTimestamp;
/**
* Date after which the coins of this denomination can't be
* deposited anymore.
*/
- stamp_expire_deposit: Timestamp;
+ stamp_expire_deposit: TalerProtocolTimestamp;
/**
* Signature over the denomination information by the exchange's master
@@ -394,7 +393,7 @@ export interface Product {
taxes?: Tax[];
// time indicating when this product should be delivered
- delivery_date?: Timestamp;
+ delivery_date?: TalerProtocolTimestamp;
}
export interface InternationalizedString {
@@ -413,7 +412,7 @@ export interface ContractTerms {
/**
* Hash of the merchant's wire details.
*/
- auto_refund?: Duration;
+ auto_refund?: TalerProtocolDuration;
/**
* Wire method the merchant wants to use.
@@ -445,7 +444,7 @@ export interface ContractTerms {
/**
* Deadline to pay for the contract.
*/
- pay_deadline: Timestamp;
+ pay_deadline: TalerProtocolTimestamp;
/**
* Maximum deposit fee covered by the merchant.
@@ -466,7 +465,7 @@ export interface ContractTerms {
* Time indicating when the order should be delivered.
* May be overwritten by individual products.
*/
- delivery_date?: Timestamp;
+ delivery_date?: TalerProtocolTimestamp;
/**
* Delivery location for (all!) products.
@@ -486,17 +485,17 @@ export interface ContractTerms {
/**
* Deadline for refunds.
*/
- refund_deadline: Timestamp;
+ refund_deadline: TalerProtocolTimestamp;
/**
* Deadline for the wire transfer.
*/
- wire_transfer_deadline: Timestamp;
+ wire_transfer_deadline: TalerProtocolTimestamp;
/**
* Time when the contract was generated by the merchant.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
/**
* Order id to uniquely identify the purchase within
@@ -700,9 +699,9 @@ export class Recoup {
* Structure of one exchange signing key in the /keys response.
*/
export class ExchangeSignKeyJson {
- stamp_start: Timestamp;
- stamp_expire: Timestamp;
- stamp_end: Timestamp;
+ stamp_start: TalerProtocolTimestamp;
+ stamp_expire: TalerProtocolTimestamp;
+ stamp_end: TalerProtocolTimestamp;
key: EddsaPublicKeyString;
master_sig: EddsaSignatureString;
}
@@ -729,7 +728,7 @@ export class ExchangeKeysJson {
/**
* Timestamp when this response was issued.
*/
- list_issue_date: Timestamp;
+ list_issue_date: TalerProtocolTimestamp;
/**
* List of revoked denominations.
@@ -747,7 +746,7 @@ export class ExchangeKeysJson {
*/
version: string;
- reserve_closing_delay: Duration;
+ reserve_closing_delay: TalerProtocolDuration;
}
/**
@@ -774,12 +773,12 @@ export class WireFeesJson {
/**
* Date from which the fee applies.
*/
- start_date: Timestamp;
+ start_date: TalerProtocolTimestamp;
/**
* Data after which the fee doesn't apply anymore.
*/
- end_date: Timestamp;
+ end_date: TalerProtocolTimestamp;
}
export interface AccountInfo {
@@ -850,7 +849,7 @@ export class TipPickupGetResponse {
exchange_url: string;
- expiration: Timestamp;
+ expiration: TalerProtocolTimestamp;
}
export enum DenomKeyType {
@@ -1067,7 +1066,7 @@ export interface MerchantCoinRefundSuccessStatus {
// to the customer.
refund_amount: AmountString;
- execution_time: Timestamp;
+ execution_time: TalerProtocolTimestamp;
}
export interface MerchantCoinRefundFailureStatus {
@@ -1092,7 +1091,7 @@ export interface MerchantCoinRefundFailureStatus {
// to the customer.
refund_amount: AmountString;
- execution_time: Timestamp;
+ execution_time: TalerProtocolTimestamp;
}
export interface MerchantOrderStatusUnpaid {
@@ -1733,7 +1732,7 @@ export interface DepositSuccess {
transaction_base_url?: string;
// timestamp when the deposit was received by the exchange.
- exchange_timestamp: Timestamp;
+ exchange_timestamp: TalerProtocolTimestamp;
// the EdDSA signature of TALER_DepositConfirmationPS using a current
// signing key of the exchange affirming the successful
diff --git a/packages/taler-util/src/time.ts b/packages/taler-util/src/time.ts
index 9f9571019..43cb7ad4d 100644
--- a/packages/taler-util/src/time.ts
+++ b/packages/taler-util/src/time.ts
@@ -23,13 +23,41 @@
*/
import { Codec, renderContext, Context } from "./codec.js";
-export interface Timestamp {
+export interface AbsoluteTime {
/**
* Timestamp in milliseconds.
*/
readonly t_ms: number | "never";
}
+export interface TalerProtocolTimestamp {
+ readonly t_s: number | "never";
+}
+
+export namespace TalerProtocolTimestamp {
+ export function now(): TalerProtocolTimestamp {
+ return AbsoluteTime.toTimestamp(AbsoluteTime.now());
+ }
+
+ export function zero(): TalerProtocolTimestamp {
+ return {
+ t_s: 0,
+ };
+ }
+
+ export function never(): TalerProtocolTimestamp {
+ return {
+ t_s: "never",
+ };
+ }
+
+ export function fromSeconds(s: number): TalerProtocolTimestamp {
+ return {
+ t_s: s,
+ };
+ }
+}
+
export interface Duration {
/**
* Duration in milliseconds.
@@ -37,40 +65,32 @@ export interface Duration {
readonly d_ms: number | "forever";
}
+export interface TalerProtocolDuration {
+ readonly d_us: number | "forever";
+}
+
let timeshift = 0;
export function setDangerousTimetravel(dt: number): void {
timeshift = dt;
}
-export function getTimestampNow(): Timestamp {
- return {
- t_ms: new Date().getTime() + timeshift,
- };
-}
-
-export function isTimestampExpired(t: Timestamp) {
- return timestampCmp(t, getTimestampNow()) <= 0;
-}
-
-export function getDurationRemaining(
- deadline: Timestamp,
- now = getTimestampNow(),
-): Duration {
- if (deadline.t_ms === "never") {
- return { d_ms: "forever" };
- }
- if (now.t_ms === "never") {
- throw Error("invalid argument for 'now'");
- }
- if (deadline.t_ms < now.t_ms) {
- return { d_ms: 0 };
- }
- return { d_ms: deadline.t_ms - now.t_ms };
-}
-
export namespace Duration {
- export const getRemaining = getDurationRemaining;
+ export function getRemaining(
+ deadline: AbsoluteTime,
+ now = AbsoluteTime.now(),
+ ): Duration {
+ if (deadline.t_ms === "never") {
+ return { d_ms: "forever" };
+ }
+ if (now.t_ms === "never") {
+ throw Error("invalid argument for 'now'");
+ }
+ if (deadline.t_ms < now.t_ms) {
+ return { d_ms: 0 };
+ }
+ return { d_ms: deadline.t_ms - now.t_ms };
+ }
export function toIntegerYears(d: Duration): number {
if (typeof d.d_ms !== "number") {
throw Error("infinite duration");
@@ -81,33 +101,152 @@ export namespace Duration {
export function getForever(): Duration {
return { d_ms: "forever" };
}
+ export function fromTalerProtocolDuration(
+ d: TalerProtocolDuration,
+ ): Duration {
+ if (d.d_us === "forever") {
+ return {
+ d_ms: "forever",
+ };
+ }
+ return {
+ d_ms: d.d_us / 1000,
+ };
+ }
}
-export namespace Timestamp {
- export const now = getTimestampNow;
- export const min = timestampMin;
- export const isExpired = isTimestampExpired;
- export const truncateToSecond = timestampTruncateToSecond;
-}
+export namespace AbsoluteTime {
+ export function now(): AbsoluteTime {
+ return {
+ t_ms: new Date().getTime() + timeshift,
+ };
+ }
-export function timestampMin(t1: Timestamp, t2: Timestamp): Timestamp {
- if (t1.t_ms === "never") {
- return { t_ms: t2.t_ms };
+ export function never(): AbsoluteTime {
+ return {
+ t_ms: "never",
+ };
}
- if (t2.t_ms === "never") {
- return { t_ms: t2.t_ms };
+
+ export function cmp(t1: AbsoluteTime, t2: AbsoluteTime): number {
+ if (t1.t_ms === "never") {
+ if (t2.t_ms === "never") {
+ return 0;
+ }
+ return 1;
+ }
+ if (t2.t_ms === "never") {
+ return -1;
+ }
+ if (t1.t_ms == t2.t_ms) {
+ return 0;
+ }
+ if (t1.t_ms > t2.t_ms) {
+ return 1;
+ }
+ return -1;
+ }
+
+ export function min(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime {
+ if (t1.t_ms === "never") {
+ return { t_ms: t2.t_ms };
+ }
+ if (t2.t_ms === "never") {
+ return { t_ms: t2.t_ms };
+ }
+ return { t_ms: Math.min(t1.t_ms, t2.t_ms) };
}
- return { t_ms: Math.min(t1.t_ms, t2.t_ms) };
-}
-export function timestampMax(t1: Timestamp, t2: Timestamp): Timestamp {
- if (t1.t_ms === "never") {
- return { t_ms: "never" };
+ export function max(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime {
+ if (t1.t_ms === "never") {
+ return { t_ms: "never" };
+ }
+ if (t2.t_ms === "never") {
+ return { t_ms: "never" };
+ }
+ return { t_ms: Math.max(t1.t_ms, t2.t_ms) };
}
- if (t2.t_ms === "never") {
- return { t_ms: "never" };
+
+ export function difference(t1: AbsoluteTime, t2: AbsoluteTime): Duration {
+ if (t1.t_ms === "never") {
+ return { d_ms: "forever" };
+ }
+ if (t2.t_ms === "never") {
+ return { d_ms: "forever" };
+ }
+ return { d_ms: Math.abs(t1.t_ms - t2.t_ms) };
+ }
+
+ export function isExpired(t: AbsoluteTime) {
+ return cmp(t, now()) <= 0;
+ }
+
+ export function fromTimestamp(t: TalerProtocolTimestamp): AbsoluteTime {
+ if (t.t_s === "never") {
+ return { t_ms: "never" };
+ }
+ return {
+ t_ms: t.t_s * 1000,
+ };
+ }
+
+ export function toTimestamp(at: AbsoluteTime): TalerProtocolTimestamp {
+ if (at.t_ms === "never") {
+ return { t_s: "never" };
+ }
+ return {
+ t_s: Math.floor(at.t_ms / 1000),
+ };
+ }
+
+ export function isBetween(
+ t: AbsoluteTime,
+ start: AbsoluteTime,
+ end: AbsoluteTime,
+ ): boolean {
+ if (cmp(t, start) < 0) {
+ return false;
+ }
+ if (cmp(t, end) > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ export function toIsoString(t: AbsoluteTime): string {
+ if (t.t_ms === "never") {
+ return "<never>";
+ } else {
+ return new Date(t.t_ms).toISOString();
+ }
+ }
+
+ export function addDuration(t1: AbsoluteTime, d: Duration): AbsoluteTime {
+ if (t1.t_ms === "never" || d.d_ms === "forever") {
+ return { t_ms: "never" };
+ }
+ return { t_ms: t1.t_ms + d.d_ms };
+ }
+
+ export function subtractDuraction(
+ t1: AbsoluteTime,
+ d: Duration,
+ ): AbsoluteTime {
+ if (t1.t_ms === "never") {
+ return { t_ms: "never" };
+ }
+ if (d.d_ms === "forever") {
+ return { t_ms: 0 };
+ }
+ return { t_ms: Math.max(0, t1.t_ms - d.d_ms) };
+ }
+
+ export function stringify(t: AbsoluteTime): string {
+ if (t.t_ms === "never") {
+ return "never";
+ }
+ return new Date(t.t_ms).toISOString();
}
- return { t_ms: Math.max(t1.t_ms, t2.t_ms) };
}
const SECONDS = 1000;
@@ -135,19 +274,6 @@ export function durationFromSpec(spec: {
return { d_ms };
}
-/**
- * Truncate a timestamp so that that it represents a multiple
- * of seconds. The timestamp is always rounded down.
- */
-export function timestampTruncateToSecond(t1: Timestamp): Timestamp {
- if (t1.t_ms === "never") {
- return { t_ms: "never" };
- }
- return {
- t_ms: Math.floor(t1.t_ms / 1000) * 1000,
- };
-}
-
export function durationMin(d1: Duration, d2: Duration): Duration {
if (d1.d_ms === "forever") {
return { d_ms: d2.d_ms };
@@ -182,111 +308,33 @@ export function durationAdd(d1: Duration, d2: Duration): Duration {
return { d_ms: d1.d_ms + d2.d_ms };
}
-export function timestampCmp(t1: Timestamp, t2: Timestamp): number {
- if (t1.t_ms === "never") {
- if (t2.t_ms === "never") {
- return 0;
- }
- return 1;
- }
- if (t2.t_ms === "never") {
- return -1;
- }
- if (t1.t_ms == t2.t_ms) {
- return 0;
- }
- if (t1.t_ms > t2.t_ms) {
- return 1;
- }
- return -1;
-}
-
-export function timestampAddDuration(t1: Timestamp, d: Duration): Timestamp {
- if (t1.t_ms === "never" || d.d_ms === "forever") {
- return { t_ms: "never" };
- }
- return { t_ms: t1.t_ms + d.d_ms };
-}
-
-export function timestampSubtractDuraction(
- t1: Timestamp,
- d: Duration,
-): Timestamp {
- if (t1.t_ms === "never") {
- return { t_ms: "never" };
- }
- if (d.d_ms === "forever") {
- return { t_ms: 0 };
- }
- return { t_ms: Math.max(0, t1.t_ms - d.d_ms) };
-}
-
-export function stringifyTimestamp(t: Timestamp): string {
- if (t.t_ms === "never") {
- return "never";
- }
- return new Date(t.t_ms).toISOString();
-}
-
-export function timestampDifference(t1: Timestamp, t2: Timestamp): Duration {
- if (t1.t_ms === "never") {
- return { d_ms: "forever" };
- }
- if (t2.t_ms === "never") {
- return { d_ms: "forever" };
- }
- return { d_ms: Math.abs(t1.t_ms - t2.t_ms) };
-}
-
-export function timestampToIsoString(t: Timestamp): string {
- if (t.t_ms === "never") {
- return "<never>";
- } else {
- return new Date(t.t_ms).toISOString();
- }
-}
-
-export function timestampIsBetween(
- t: Timestamp,
- start: Timestamp,
- end: Timestamp,
-): boolean {
- if (timestampCmp(t, start) < 0) {
- return false;
- }
- if (timestampCmp(t, end) > 0) {
- return false;
- }
- return true;
-}
-
-export const codecForTimestamp: Codec<Timestamp> = {
- decode(x: any, c?: Context): Timestamp {
- const t_ms = x.t_ms;
- if (typeof t_ms === "string") {
- if (t_ms === "never") {
- return { t_ms: "never" };
+export const codecForTimestamp: Codec<TalerProtocolTimestamp> = {
+ decode(x: any, c?: Context): TalerProtocolTimestamp {
+ const t_s = x.t_s;
+ if (typeof t_s === "string") {
+ if (t_s === "never") {
+ return { t_s: "never" };
}
throw Error(`expected timestamp at ${renderContext(c)}`);
}
- if (typeof t_ms === "number") {
- return { t_ms };
+ if (typeof t_s === "number") {
+ return { t_s };
}
throw Error(`expected timestamp at ${renderContext(c)}`);
},
};
-export const codecForDuration: Codec<Duration> = {
- decode(x: any, c?: Context): Duration {
- const d_ms = x.d_ms;
- if (typeof d_ms === "string") {
- if (d_ms === "forever") {
- return { d_ms: "forever" };
+export const codecForDuration: Codec<TalerProtocolDuration> = {
+ decode(x: any, c?: Context): TalerProtocolDuration {
+ const d_us = x.d_us;
+ if (typeof d_us === "string") {
+ if (d_us === "forever") {
+ return { d_us: "forever" };
}
throw Error(`expected duration at ${renderContext(c)}`);
}
- if (typeof d_ms === "number") {
- return { d_ms };
+ if (typeof d_us === "number") {
+ return { d_us };
}
throw Error(`expected duration at ${renderContext(c)}`);
},
diff --git a/packages/taler-util/src/transactionsTypes.ts b/packages/taler-util/src/transactionsTypes.ts
index e780ca411..bccbc7737 100644
--- a/packages/taler-util/src/transactionsTypes.ts
+++ b/packages/taler-util/src/transactionsTypes.ts
@@ -24,7 +24,7 @@
/**
* Imports.
*/
-import { Timestamp } from "./time.js";
+import { TalerProtocolTimestamp } from "./time.js";
import {
AmountString,
Product,
@@ -73,7 +73,7 @@ export interface TransactionCommon {
type: TransactionType;
// main timestamp of the transaction
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
// true if the transaction is still pending, false otherwise
// If a transaction is not longer pending, its timestamp will be updated,
diff --git a/packages/taler-util/src/types-test.ts b/packages/taler-util/src/types-test.ts
index 6998bb5fb..e8af13119 100644
--- a/packages/taler-util/src/types-test.ts
+++ b/packages/taler-util/src/types-test.ts
@@ -29,13 +29,13 @@ test("contract terms validation", (t) => {
merchant_pub: "12345",
merchant: { name: "Foo" },
order_id: "test_order",
- pay_deadline: { t_ms: 42 },
- wire_transfer_deadline: { t_ms: 42 },
+ pay_deadline: { t_s: 42 },
+ wire_transfer_deadline: { t_s: 42 },
merchant_base_url: "https://example.com/pay",
products: [],
- refund_deadline: { t_ms: 42 },
+ refund_deadline: { t_s: 42 },
summary: "hello",
- timestamp: { t_ms: 42 },
+ timestamp: { t_s: 42 },
wire_method: "test",
};
@@ -71,13 +71,13 @@ test("contract terms validation (locations)", (t) => {
},
},
order_id: "test_order",
- pay_deadline: { t_ms: 42 },
- wire_transfer_deadline: { t_ms: 42 },
+ pay_deadline: { t_s: 42 },
+ wire_transfer_deadline: { t_s: 42 },
merchant_base_url: "https://example.com/pay",
products: [],
- refund_deadline: { t_ms: 42 },
+ refund_deadline: { t_s: 42 },
summary: "hello",
- timestamp: { t_ms: 42 },
+ timestamp: { t_s: 42 },
wire_method: "test",
delivery_location: {
country: "FR",
diff --git a/packages/taler-util/src/walletTypes.ts b/packages/taler-util/src/walletTypes.ts
index 9a3f1f8f8..3c4fa96c7 100644
--- a/packages/taler-util/src/walletTypes.ts
+++ b/packages/taler-util/src/walletTypes.ts
@@ -32,7 +32,11 @@ import {
codecForAmountJson,
codecForAmountString,
} from "./amounts.js";
-import { Timestamp, codecForTimestamp } from "./time.js";
+import {
+ AbsoluteTime,
+ codecForTimestamp,
+ TalerProtocolTimestamp,
+} from "./time.js";
import {
buildCodecForObject,
codecForString,
@@ -299,7 +303,7 @@ export interface PrepareTipResult {
* Time when the tip will expire. After it expired, it can't be picked
* up anymore.
*/
- expirationTimestamp: Timestamp;
+ expirationTimestamp: TalerProtocolTimestamp;
}
export const codecForPrepareTipResult = (): Codec<PrepareTipResult> =>
@@ -460,7 +464,7 @@ export interface TalerErrorDetails {
/**
* Minimal information needed about a planchet for unblinding a signature.
- *
+ *
* Can be a withdrawal/tipping/refresh planchet.
*/
export interface PlanchetUnblindInfo {
@@ -527,8 +531,8 @@ export interface DepositInfo {
coinPub: string;
coinPriv: string;
spendAmount: AmountJson;
- timestamp: Timestamp;
- refundDeadline: Timestamp;
+ timestamp: TalerProtocolTimestamp;
+ refundDeadline: TalerProtocolTimestamp;
merchantPub: string;
feeDeposit: AmountJson;
wireInfoHash: string;
diff --git a/packages/taler-wallet-cli/src/harness/harness.ts b/packages/taler-wallet-cli/src/harness/harness.ts
index 1500d7743..63bb17fcc 100644
--- a/packages/taler-wallet-cli/src/harness/harness.ts
+++ b/packages/taler-wallet-cli/src/harness/harness.ts
@@ -478,7 +478,7 @@ class BankServiceBase {
protected globalTestState: GlobalTestState,
protected bankConfig: BankConfig,
protected configFile: string,
- ) { }
+ ) {}
}
/**
@@ -920,7 +920,7 @@ export class FakeBankService {
private globalTestState: GlobalTestState,
private bankConfig: FakeBankConfig,
private configFile: string,
- ) { }
+ ) {}
async start(): Promise<void> {
this.proc = this.globalTestState.spawnService(
@@ -1175,7 +1175,7 @@ export class ExchangeService implements ExchangeServiceInterface {
private exchangeConfig: ExchangeConfig,
private configFilename: string,
private keyPair: EddsaKeyPair,
- ) { }
+ ) {}
get name() {
return this.exchangeConfig.name;
@@ -1276,7 +1276,7 @@ export class ExchangeService implements ExchangeServiceInterface {
accTargetType,
`${this.exchangeConfig.currency}:0.01`,
`${this.exchangeConfig.currency}:0.01`,
- // `${this.exchangeConfig.currency}:0.01`,
+ `${this.exchangeConfig.currency}:0.01`,
"upload",
],
);
@@ -1398,7 +1398,7 @@ export class MerchantApiClient {
constructor(
private baseUrl: string,
public readonly auth: MerchantAuthConfiguration,
- ) { }
+ ) {}
async changeAuth(auth: MerchantAuthConfiguration): Promise<void> {
const url = new URL("private/auth", this.baseUrl);
@@ -1591,7 +1591,7 @@ export class MerchantService implements MerchantServiceInterface {
private globalState: GlobalTestState,
private merchantConfig: MerchantConfig,
private configFilename: string,
- ) { }
+ ) {}
private currentTimetravel: Duration | undefined;
@@ -1888,8 +1888,10 @@ export class WalletCli {
const resp = await sh(
self.globalTestState,
`wallet-${self.name}`,
- `taler-wallet-cli ${self.timetravelArg ?? ""
- } --no-throttle -LTRACE --wallet-db '${self.dbfile
+ `taler-wallet-cli ${
+ self.timetravelArg ?? ""
+ } --no-throttle -LTRACE --wallet-db '${
+ self.dbfile
}' api '${op}' ${shellWrap(JSON.stringify(payload))}`,
);
console.log("--- wallet core response ---");
diff --git a/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts b/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts
index a93a0ed25..dcb1a2b42 100644
--- a/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts
+++ b/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts
@@ -38,7 +38,7 @@ import {
codecForAny,
buildCodecForUnion,
AmountString,
- Timestamp,
+ AbsoluteTime,
CoinPublicKeyString,
EddsaPublicKeyString,
codecForAmountString,
@@ -195,7 +195,7 @@ export interface RefundDetails {
reason: string;
// when was the refund approved
- timestamp: Timestamp;
+ timestamp: AbsoluteTime;
// Total amount that was refunded (minus a refund fee).
amount: AmountString;
@@ -209,7 +209,7 @@ export interface TransactionWireTransfer {
wtid: string;
// execution time of the wire transfer
- execution_time: Timestamp;
+ execution_time: AbsoluteTime;
// Total amount that has been wire transferred
// to the merchant
@@ -247,10 +247,10 @@ export interface ReserveStatusEntry {
reserve_pub: string;
// Timestamp when it was established
- creation_time: Timestamp;
+ creation_time: AbsoluteTime;
// Timestamp when it expires
- expiration_time: Timestamp;
+ expiration_time: AbsoluteTime;
// Initial amount as per reserve creation call
merchant_initial_amount: AmountString;
@@ -281,7 +281,7 @@ export interface TipCreateConfirmation {
tip_status_url: string;
// when does the tip expire
- tip_expiration: Timestamp;
+ tip_expiration: AbsoluteTime;
}
export interface TipCreateRequest {
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
index 8e4109752..8a11b79c6 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
@@ -32,6 +32,7 @@ import {
BankApi,
BankAccessApi,
CreditDebitIndicator,
+ OperationFailedError,
} from "@gnu-taler/taler-wallet-core";
/**
@@ -106,8 +107,7 @@ export async function runBankApiTest(t: GlobalTestState) {
const e = await t.assertThrowsAsync(async () => {
await BankApi.registerAccount(bank, "user1", "pw1");
});
- t.assertAxiosError(e);
- t.assertTrue(e.response?.status === 409);
+ t.assertTrue(e.details.httpStatusCode === 409);
}
let balResp = await BankAccessApi.getAccountBalance(bank, bankUser);
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts b/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts
index ed07114eb..e2b81ee6a 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts
@@ -18,11 +18,11 @@
* Imports.
*/
import {
+ AbsoluteTime,
codecForExchangeKeysJson,
DenominationPubKey,
Duration,
durationFromSpec,
- stringifyTimestamp,
} from "@gnu-taler/taler-util";
import {
NodeHttpLib,
@@ -174,27 +174,37 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
const denomPubs1 = keys1.denoms.map((x) => {
return {
denomPub: x.denom_pub,
- expireDeposit: stringifyTimestamp(x.stamp_expire_deposit),
+ expireDeposit: AbsoluteTime.stringify(
+ AbsoluteTime.fromTimestamp(x.stamp_expire_deposit),
+ ),
};
});
const denomPubs2 = keys2.denoms.map((x) => {
return {
denomPub: x.denom_pub,
- expireDeposit: stringifyTimestamp(x.stamp_expire_deposit),
+ expireDeposit: AbsoluteTime.stringify(
+ AbsoluteTime.fromTimestamp(x.stamp_expire_deposit),
+ ),
};
});
const dps2 = new Set(denomPubs2.map((x) => x.denomPub));
console.log("=== KEYS RESPONSE 1 ===");
- console.log("list issue date", stringifyTimestamp(keys1.list_issue_date));
+ console.log(
+ "list issue date",
+ AbsoluteTime.stringify(AbsoluteTime.fromTimestamp(keys1.list_issue_date)),
+ );
console.log("num denoms", keys1.denoms.length);
console.log("denoms", JSON.stringify(denomPubs1, undefined, 2));
console.log("=== KEYS RESPONSE 2 ===");
- console.log("list issue date", stringifyTimestamp(keys2.list_issue_date));
+ console.log(
+ "list issue date",
+ AbsoluteTime.stringify(AbsoluteTime.fromTimestamp(keys2.list_issue_date)),
+ );
console.log("num denoms", keys2.denoms.length);
console.log("denoms", JSON.stringify(denomPubs2, undefined, 2));
@@ -214,8 +224,8 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
`denomination with public key ${da.denomPub} is not present in new /keys response`,
);
console.log(
- `the new /keys response was issued ${stringifyTimestamp(
- keys2.list_issue_date,
+ `the new /keys response was issued ${AbsoluteTime.stringify(
+ AbsoluteTime.fromTimestamp(keys2.list_issue_date),
)}`,
);
console.log(
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts
index 33aad80d2..8f7d77712 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts
@@ -18,9 +18,8 @@
* Imports.
*/
import {
+ AbsoluteTime,
ContractTerms,
- getTimestampNow,
- timestampTruncateToSecond,
} from "@gnu-taler/taler-util";
import {
WalletApiOperation,
@@ -277,7 +276,7 @@ export async function runLibeufinBasicTest(t: GlobalTestState) {
summary: "Buy me!",
amount: "EUR:5",
fulfillment_url: "taler://fulfillment-success/thx",
- wire_transfer_deadline: timestampTruncateToSecond(getTimestampNow()),
+ wire_transfer_deadline: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
};
await makeTestPayment(t, { wallet, merchant, order });
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts
index ef926c4af..2bef87b20 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts
@@ -25,7 +25,7 @@ import {
MerchantApiClient,
MerchantService,
setupDb,
- getPayto
+ getPayto,
} from "../harness/harness.js";
/**
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts b/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts
index 230fc942d..574177c8c 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts
@@ -18,7 +18,10 @@
* Imports.
*/
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment, withdrawViaBank } from "../harness/helpers.js";
+import {
+ createSimpleTestkudosEnvironment,
+ withdrawViaBank,
+} from "../harness/helpers.js";
import { durationFromSpec } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -28,12 +31,8 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runRefundAutoTest(t: GlobalTestState) {
// Set up test environment
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
+ const { wallet, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironment(t);
// Withdraw digital cash into the wallet.
@@ -46,7 +45,7 @@ export async function runRefundAutoTest(t: GlobalTestState) {
amount: "TESTKUDOS:5",
fulfillment_url: "taler://fulfillment-success/thx",
auto_refund: {
- d_ms: 3000,
+ d_us: 3000 * 1000,
},
},
refund_delay: durationFromSpec({ minutes: 5 }),
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts b/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts
index c6442a240..24600384b 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts
@@ -24,10 +24,8 @@ import {
applyTimeTravel,
} from "../harness/helpers.js";
import {
+ AbsoluteTime,
durationFromSpec,
- timestampAddDuration,
- getTimestampNow,
- timestampTruncateToSecond,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -55,9 +53,9 @@ export async function runRefundGoneTest(t: GlobalTestState) {
summary: "Buy me!",
amount: "TESTKUDOS:5",
fulfillment_url: "taler://fulfillment-success/thx",
- pay_deadline: timestampTruncateToSecond(
- timestampAddDuration(
- getTimestampNow(),
+ pay_deadline: AbsoluteTime.toTimestamp(
+ AbsoluteTime.addDuration(
+ AbsoluteTime.now(),
durationFromSpec({
minutes: 10,
}),
diff --git a/packages/taler-wallet-core/src/bank-api-client.ts b/packages/taler-wallet-core/src/bank-api-client.ts
index a61ea2eef..128e9a7a7 100644
--- a/packages/taler-wallet-core/src/bank-api-client.ts
+++ b/packages/taler-wallet-core/src/bank-api-client.ts
@@ -25,6 +25,7 @@ import {
AmountString,
buildCodecForObject,
Codec,
+ codecForAny,
codecForString,
encodeCrock,
getRandomBytes,
@@ -102,15 +103,16 @@ export namespace BankApi {
const resp = await bank.http.postJson(url.href, { username, password });
let paytoUri = `payto://x-taler-bank/localhost/${username}`;
if (resp.status !== 200 && resp.status !== 202) {
- logger.error(`${j2s(await resp.json())}`)
+ logger.error(`${j2s(await resp.json())}`);
throw new Error();
}
+ const respJson = await readSuccessResponseJsonOrThrow(resp, codecForAny());
+ // LibEuFin demobank returns payto URI in response
+ if (respJson.paytoUri) {
+ paytoUri = respJson.paytoUri;
+ }
try {
const respJson = await resp.json();
- // LibEuFin demobank returns payto URI in response
- if (respJson.paytoUri) {
- paytoUri = respJson.paytoUri;
- }
} catch (e) {}
return {
password,
diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts
index 957ba1ca1..d37bbe6eb 100644
--- a/packages/taler-wallet-core/src/common.ts
+++ b/packages/taler-wallet-core/src/common.ts
@@ -34,7 +34,8 @@ import {
BalancesResponse,
AmountJson,
DenominationPubKey,
- Timestamp,
+ AbsoluteTime,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { CryptoApi } from "./crypto/workers/cryptoApi.js";
import { ExchangeDetailsRecord, ExchangeRecord, WalletStoresV1 } from "./db.js";
@@ -165,22 +166,22 @@ export interface DenomInfo {
/**
* Validity start date of the denomination.
*/
- stampStart: Timestamp;
+ stampStart: TalerProtocolTimestamp;
/**
* Date after which the currency can't be withdrawn anymore.
*/
- stampExpireWithdraw: Timestamp;
+ stampExpireWithdraw: TalerProtocolTimestamp;
/**
* Date after the denomination officially doesn't exist anymore.
*/
- stampExpireLegal: Timestamp;
+ stampExpireLegal: TalerProtocolTimestamp;
/**
* Data after which coins of this denomination can't be deposited anymore.
*/
- stampExpireDeposit: Timestamp;
+ stampExpireDeposit: TalerProtocolTimestamp;
}
export type NotificationListener = (n: WalletNotification) => void;
diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoApi.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoApi.ts
index 820397346..d91aa08a2 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoApi.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoApi.ts
@@ -207,7 +207,7 @@ export class CryptoApi {
}
};
ws.terminationTimerHandle = timer.after(15 * 1000, destroy);
- ws.terminationTimerHandle.unref();
+ //ws.terminationTimerHandle.unref();
}
handleWorkerError(ws: WorkerState, e: any): void {
diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
index b51d499d5..b27067885 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
@@ -67,13 +67,11 @@ import {
setupWithdrawPlanchet,
stringToBytes,
TalerSignaturePurpose,
- Timestamp,
- timestampTruncateToSecond,
- typedArrayConcat,
+ AbsoluteTime,
BlindedDenominationSignature,
- RsaUnblindedSignature,
UnblindedSignature,
PlanchetUnblindInfo,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import bigint from "big-integer";
import { DenominationRecord, WireFee } from "../../db.js";
@@ -110,18 +108,16 @@ function amountToBuffer(amount: AmountJson): Uint8Array {
return u8buf;
}
-function timestampRoundedToBuffer(ts: Timestamp): Uint8Array {
+function timestampRoundedToBuffer(ts: TalerProtocolTimestamp): Uint8Array {
const b = new ArrayBuffer(8);
const v = new DataView(b);
- const tsRounded = timestampTruncateToSecond(ts);
+ // The buffer we sign over represents the timestamp in microseconds.
if (typeof v.setBigUint64 !== "undefined") {
- const s = BigInt(tsRounded.t_ms) * BigInt(1000);
+ const s = BigInt(ts.t_s) * BigInt(1000 * 1000);
v.setBigUint64(0, s);
} else {
const s =
- tsRounded.t_ms === "never"
- ? bigint.zero
- : bigint(tsRounded.t_ms).times(1000);
+ ts.t_s === "never" ? bigint.zero : bigint(ts.t_s).multiply(1000 * 1000);
const arr = s.toArray(2 ** 8).value;
let offset = 8 - arr.length;
for (let i = 0; i < arr.length; i++) {
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 2e76ab523..e9fe6a47b 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -36,9 +36,10 @@ import {
Product,
RefreshReason,
TalerErrorDetails,
- Timestamp,
UnblindedSignature,
CoinEnvelope,
+ TalerProtocolTimestamp,
+ TalerProtocolDuration,
} from "@gnu-taler/taler-util";
import { RetryInfo } from "./util/retries.js";
import { PayCoinSelection } from "./util/coinSelection.js";
@@ -152,7 +153,7 @@ export interface ReserveRecord {
/**
* Time when the reserve was created.
*/
- timestampCreated: Timestamp;
+ timestampCreated: TalerProtocolTimestamp;
/**
* Time when the information about this reserve was posted to the bank.
@@ -161,14 +162,14 @@ export interface ReserveRecord {
*
* Set to undefined if that hasn't happened yet.
*/
- timestampReserveInfoPosted: Timestamp | undefined;
+ timestampReserveInfoPosted: TalerProtocolTimestamp | undefined;
/**
* Time when the reserve was confirmed by the bank.
*
* Set to undefined if not confirmed yet.
*/
- timestampBankConfirmed: Timestamp | undefined;
+ timestampBankConfirmed: TalerProtocolTimestamp | undefined;
/**
* Wire information (as payto URI) for the bank account that
@@ -218,11 +219,6 @@ export interface ReserveRecord {
operationStatus: OperationStatus;
/**
- * Time of the last successful status query.
- */
- lastSuccessfulStatusQuery: Timestamp | undefined;
-
- /**
* Retry info, in case the reserve needs to be processed again
* later, either due to an error or because the wallet needs to
* wait for something.
@@ -350,22 +346,22 @@ export interface DenominationRecord {
/**
* Validity start date of the denomination.
*/
- stampStart: Timestamp;
+ stampStart: TalerProtocolTimestamp;
/**
* Date after which the currency can't be withdrawn anymore.
*/
- stampExpireWithdraw: Timestamp;
+ stampExpireWithdraw: TalerProtocolTimestamp;
/**
* Date after the denomination officially doesn't exist anymore.
*/
- stampExpireLegal: Timestamp;
+ stampExpireLegal: TalerProtocolTimestamp;
/**
* Data after which coins of this denomination can't be deposited anymore.
*/
- stampExpireDeposit: Timestamp;
+ stampExpireDeposit: TalerProtocolTimestamp;
/**
* Signature by the exchange's master key over the denomination
@@ -407,7 +403,7 @@ export interface DenominationRecord {
* Latest list issue date of the "/keys" response
* that includes this denomination.
*/
- listIssueDate: Timestamp;
+ listIssueDate: TalerProtocolTimestamp;
}
/**
@@ -441,7 +437,7 @@ export interface ExchangeDetailsRecord {
*/
protocolVersion: string;
- reserveClosingDelay: Duration;
+ reserveClosingDelay: TalerProtocolDuration;
/**
* Signing keys we got from the exchange, can also contain
@@ -478,7 +474,7 @@ export interface ExchangeDetailsRecord {
*
* Used during backup merging.
*/
- termsOfServiceAcceptedTimestamp: Timestamp | undefined;
+ termsOfServiceAcceptedTimestamp: TalerProtocolTimestamp | undefined;
wireInfo: WireInfo;
}
@@ -503,7 +499,7 @@ export interface ExchangeDetailsPointer {
* Timestamp when the (masterPublicKey, currency) pointer
* has been updated.
*/
- updateClock: Timestamp;
+ updateClock: TalerProtocolTimestamp;
}
/**
@@ -528,14 +524,14 @@ export interface ExchangeRecord {
/**
* Last time when the exchange was updated.
*/
- lastUpdate: Timestamp | undefined;
+ lastUpdate: TalerProtocolTimestamp | undefined;
/**
* Next scheduled update for the exchange.
*
* (This field must always be present, so we can index on the timestamp.)
*/
- nextUpdate: Timestamp;
+ nextUpdate: TalerProtocolTimestamp;
/**
* Next time that we should check if coins need to be refreshed.
@@ -543,7 +539,7 @@ export interface ExchangeRecord {
* Updated whenever the exchange's denominations are updated or when
* the refresh check has been done.
*/
- nextRefreshCheck: Timestamp;
+ nextRefreshCheck: TalerProtocolTimestamp;
/**
* Last error (if any) for fetching updated information about the
@@ -793,7 +789,7 @@ export interface ProposalRecord {
* Timestamp (in ms) of when the record
* was created.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
/**
* Private key for the nonce.
@@ -837,7 +833,7 @@ export interface TipRecord {
* Has the user accepted the tip? Only after the tip has been accepted coins
* withdrawn from the tip may be used.
*/
- acceptedTimestamp: Timestamp | undefined;
+ acceptedTimestamp: TalerProtocolTimestamp | undefined;
/**
* The tipped amount.
@@ -849,7 +845,7 @@ export interface TipRecord {
/**
* Timestamp, the tip can't be picked up anymore after this deadline.
*/
- tipExpiration: Timestamp;
+ tipExpiration: TalerProtocolTimestamp;
/**
* The exchange that will sign our coins, chosen by the merchant.
@@ -884,13 +880,13 @@ export interface TipRecord {
*/
merchantTipId: string;
- createdTimestamp: Timestamp;
+ createdTimestamp: TalerProtocolTimestamp;
/**
* Timestamp for when the wallet finished picking up the tip
* from the merchant.
*/
- pickedUpTimestamp: Timestamp | undefined;
+ pickedUpTimestamp: TalerProtocolTimestamp | undefined;
/**
* Retry info, even present when the operation isn't active to allow indexing
@@ -959,12 +955,12 @@ export interface RefreshGroupRecord {
*/
statusPerCoin: RefreshCoinStatus[];
- timestampCreated: Timestamp;
+ timestampCreated: TalerProtocolTimestamp;
/**
* Timestamp when the refresh session finished.
*/
- timestampFinished: Timestamp | undefined;
+ timestampFinished: TalerProtocolTimestamp | undefined;
/**
* No coins are pending, but at least one is frozen.
@@ -1025,12 +1021,12 @@ export interface WireFee {
/**
* Start date of the fee.
*/
- startStamp: Timestamp;
+ startStamp: TalerProtocolTimestamp;
/**
* End date of the fee.
*/
- endStamp: Timestamp;
+ endStamp: TalerProtocolTimestamp;
/**
* Signature made by the exchange master key.
@@ -1054,12 +1050,12 @@ export type WalletRefundItem =
export interface WalletRefundItemCommon {
// Execution time as claimed by the merchant
- executionTime: Timestamp;
+ executionTime: TalerProtocolTimestamp;
/**
* Time when the wallet became aware of the refund.
*/
- obtainedTime: Timestamp;
+ obtainedTime: TalerProtocolTimestamp;
refundAmount: AmountJson;
@@ -1141,14 +1137,14 @@ export interface WalletContractData {
orderId: string;
merchantBaseUrl: string;
summary: string;
- autoRefund: Duration | undefined;
+ autoRefund: TalerProtocolDuration | undefined;
maxWireFee: AmountJson;
wireFeeAmortization: number;
- payDeadline: Timestamp;
- refundDeadline: Timestamp;
+ payDeadline: TalerProtocolTimestamp;
+ refundDeadline: TalerProtocolTimestamp;
allowedAuditors: AllowedAuditorInfo[];
allowedExchanges: AllowedExchangeInfo[];
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
wireMethod: string;
wireInfoHash: string;
maxDepositFee: AmountJson;
@@ -1215,8 +1211,10 @@ export interface PurchaseRecord {
/**
* Timestamp of the first time that sending a payment to the merchant
* for this purchase was successful.
+ *
+ * FIXME: Does this need to be a timestamp, doensn't boolean suffice?
*/
- timestampFirstSuccessfulPay: Timestamp | undefined;
+ timestampFirstSuccessfulPay: TalerProtocolTimestamp | undefined;
merchantPaySig: string | undefined;
@@ -1224,7 +1222,7 @@ export interface PurchaseRecord {
* When was the purchase made?
* Refers to the time that the user accepted.
*/
- timestampAccept: Timestamp;
+ timestampAccept: TalerProtocolTimestamp;
/**
* Pending refunds for the purchase. A refund is pending
@@ -1236,7 +1234,7 @@ export interface PurchaseRecord {
* When was the last refund made?
* Set to 0 if no refund was made on the purchase.
*/
- timestampLastRefundStatus: Timestamp | undefined;
+ timestampLastRefundStatus: TalerProtocolTimestamp | undefined;
/**
* Last session signature that we submitted to /pay (if any).
@@ -1273,7 +1271,7 @@ export interface PurchaseRecord {
/**
* Continue querying the refund status until this deadline has expired.
*/
- autoRefundDeadline: Timestamp | undefined;
+ autoRefundDeadline: TalerProtocolTimestamp | undefined;
/**
* Is the payment frozen? I.e. did we encounter
@@ -1308,12 +1306,12 @@ export interface WalletBackupConfState {
/**
* Timestamp stored in the last backup.
*/
- lastBackupTimestamp?: Timestamp;
+ lastBackupTimestamp?: TalerProtocolTimestamp;
/**
* Last time we tried to do a backup.
*/
- lastBackupCheckTimestamp?: Timestamp;
+ lastBackupCheckTimestamp?: TalerProtocolTimestamp;
lastBackupNonce?: string;
}
@@ -1362,14 +1360,14 @@ export interface WithdrawalGroupRecord {
* When was the withdrawal operation started started?
* Timestamp in milliseconds.
*/
- timestampStart: Timestamp;
+ timestampStart: TalerProtocolTimestamp;
/**
* When was the withdrawal operation completed?
*
* FIXME: We should probably drop this and introduce an OperationStatus field.
*/
- timestampFinish?: Timestamp;
+ timestampFinish?: TalerProtocolTimestamp;
/**
* Operation status of the withdrawal group.
@@ -1429,9 +1427,9 @@ export interface RecoupGroupRecord {
*/
recoupGroupId: string;
- timestampStarted: Timestamp;
+ timestampStarted: TalerProtocolTimestamp;
- timestampFinished: Timestamp | undefined;
+ timestampFinished: TalerProtocolTimestamp | undefined;
/**
* Public keys that identify the coins being recouped
@@ -1482,7 +1480,7 @@ export type BackupProviderState =
}
| {
tag: BackupProviderStateTag.Ready;
- nextBackupTimestamp: Timestamp;
+ nextBackupTimestamp: TalerProtocolTimestamp;
}
| {
tag: BackupProviderStateTag.Retrying;
@@ -1529,7 +1527,7 @@ export interface BackupProviderRecord {
* Does NOT correspond to the timestamp of the backup,
* which only changes when the backup content changes.
*/
- lastBackupCycleTimestamp?: Timestamp;
+ lastBackupCycleTimestamp?: TalerProtocolTimestamp;
/**
* Proposal that we're currently trying to pay for.
@@ -1594,9 +1592,9 @@ export interface DepositGroupRecord {
depositedPerCoin: boolean[];
- timestampCreated: Timestamp;
+ timestampCreated: TalerProtocolTimestamp;
- timestampFinished: Timestamp | undefined;
+ timestampFinished: TalerProtocolTimestamp | undefined;
operationStatus: OperationStatus;
@@ -1618,14 +1616,14 @@ export interface GhostDepositGroupRecord {
* When multiple deposits for the same contract terms hash
* have a different timestamp, we choose the earliest one.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
contractTermsHash: string;
deposits: {
coinPub: string;
amount: AmountString;
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
depositFee: AmountString;
merchantPub: string;
coinSig: string;
diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts
index 169b6ae0a..854a3ea09 100644
--- a/packages/taler-wallet-core/src/dbless.ts
+++ b/packages/taler-wallet-core/src/dbless.ts
@@ -44,7 +44,7 @@ import {
hashWire,
Logger,
parsePaytoUri,
- Timestamp,
+ AbsoluteTime,
UnblindedSignature,
} from "@gnu-taler/taler-util";
import { DenominationRecord } from "./db.js";
@@ -222,10 +222,11 @@ export async function depositCoin(args: {
const depositPayto =
args.depositPayto ?? "payto://x-taler-bank/localhost/foo";
const wireSalt = encodeCrock(getRandomBytes(16));
+ const timestampNow = AbsoluteTime.toTimestamp(AbsoluteTime.now());
const contractTermsHash = encodeCrock(getRandomBytes(64));
- const depositTimestamp = Timestamp.truncateToSecond(Timestamp.now());
- const refundDeadline = Timestamp.truncateToSecond(Timestamp.now());
- const wireTransferDeadline = Timestamp.truncateToSecond(Timestamp.now());
+ const depositTimestamp = timestampNow;
+ const refundDeadline = timestampNow;
+ const wireTransferDeadline = timestampNow;
const merchantPub = encodeCrock(getRandomBytes(32));
const dp = await cryptoApi.signDepositPermission({
coinPriv: coin.coinPriv,
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts
index 12b309418..35306da63 100644
--- a/packages/taler-wallet-core/src/operations/backup/export.ts
+++ b/packages/taler-wallet-core/src/operations/backup/export.ts
@@ -49,14 +49,13 @@ import {
BackupWithdrawalGroup,
canonicalizeBaseUrl,
canonicalJson,
- getTimestampNow,
Logger,
- timestampToIsoString,
WalletBackupContentV1,
hash,
encodeCrock,
getRandomBytes,
stringToBytes,
+ AbsoluteTime,
} from "@gnu-taler/taler-util";
import { InternalWalletState } from "../../common.js";
import {
@@ -455,7 +454,7 @@ export async function exportBackup(
});
});
- const ts = getTimestampNow();
+ const ts = AbsoluteTime.toTimestamp(AbsoluteTime.now());
if (!bs.lastBackupTimestamp) {
bs.lastBackupTimestamp = ts;
@@ -496,9 +495,9 @@ export async function exportBackup(
);
bs.lastBackupNonce = encodeCrock(getRandomBytes(32));
logger.trace(
- `setting timestamp to ${timestampToIsoString(ts)} and nonce to ${
- bs.lastBackupNonce
- }`,
+ `setting timestamp to ${AbsoluteTime.toIsoString(
+ AbsoluteTime.fromTimestamp(ts),
+ )} and nonce to ${bs.lastBackupNonce}`,
);
await tx.config.put({
key: WALLET_BACKUP_STATE_KEY,
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts
index 35b62c2e4..4b17a5f33 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -20,7 +20,6 @@ import {
Amounts,
BackupDenomSel,
WalletBackupContentV1,
- getTimestampNow,
BackupCoinSourceType,
BackupProposalStatus,
codecForContractTerms,
@@ -28,6 +27,8 @@ import {
RefreshReason,
BackupRefreshReason,
DenomKeyType,
+ AbsoluteTime,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import {
WalletContractData,
@@ -277,8 +278,8 @@ export async function importBackup(
permanent: true,
retryInfo: initRetryInfo(),
lastUpdate: undefined,
- nextUpdate: getTimestampNow(),
- nextRefreshCheck: getTimestampNow(),
+ nextUpdate: TalerProtocolTimestamp.now(),
+ nextRefreshCheck: TalerProtocolTimestamp.now(),
});
}
@@ -465,7 +466,6 @@ export async function importBackup(
senderWire: backupReserve.sender_wire,
retryInfo: initRetryInfo(),
lastError: undefined,
- lastSuccessfulStatusQuery: { t_ms: "never" },
initialWithdrawalGroupId:
backupReserve.initial_withdrawal_group_id,
initialWithdrawalStarted:
@@ -752,7 +752,7 @@ export async function importBackup(
noncePub:
cryptoComp.proposalNoncePrivToPub[backupPurchase.nonce_priv],
lastPayError: undefined,
- autoRefundDeadline: { t_ms: "never" },
+ autoRefundDeadline: TalerProtocolTimestamp.never(),
refundStatusRetryInfo: initRetryInfo(),
lastRefundStatusError: undefined,
timestampAccept: backupPurchase.timestamp_accept,
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts
index 2a1a774f1..48eea56ad 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -40,21 +40,19 @@ import {
ConfirmPayResultType,
DenomKeyType,
durationFromSpec,
- getTimestampNow,
hashDenomPub,
HttpStatusCode,
j2s,
- LibtoolVersion,
Logger,
notEmpty,
PreparePayResultType,
RecoveryLoadRequest,
RecoveryMergeStrategy,
TalerErrorDetails,
- Timestamp,
- timestampAddDuration,
+ AbsoluteTime,
URL,
WalletBackupContentV1,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { gunzipSync, gzipSync } from "fflate";
import { InternalWalletState } from "../../common.js";
@@ -250,11 +248,13 @@ interface BackupForProviderArgs {
retryAfterPayment: boolean;
}
-function getNextBackupTimestamp(): Timestamp {
+function getNextBackupTimestamp(): TalerProtocolTimestamp {
// FIXME: Randomize!
- return timestampAddDuration(
- getTimestampNow(),
- durationFromSpec({ minutes: 5 }),
+ return AbsoluteTime.toTimestamp(
+ AbsoluteTime.addDuration(
+ AbsoluteTime.now(),
+ durationFromSpec({ minutes: 5 }),
+ ),
);
}
@@ -324,7 +324,7 @@ async function runBackupCycleForProvider(
if (!prov) {
return;
}
- prov.lastBackupCycleTimestamp = getTimestampNow();
+ prov.lastBackupCycleTimestamp = TalerProtocolTimestamp.now();
prov.state = {
tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: getNextBackupTimestamp(),
@@ -404,7 +404,7 @@ async function runBackupCycleForProvider(
return;
}
prov.lastBackupHash = encodeCrock(currentBackupHash);
- prov.lastBackupCycleTimestamp = getTimestampNow();
+ prov.lastBackupCycleTimestamp = TalerProtocolTimestamp.now();
prov.state = {
tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: getNextBackupTimestamp(),
@@ -641,7 +641,7 @@ export async function addBackupProvider(
if (req.activate) {
oldProv.state = {
tag: BackupProviderStateTag.Ready,
- nextBackupTimestamp: getTimestampNow(),
+ nextBackupTimestamp: TalerProtocolTimestamp.now(),
};
logger.info("setting existing backup provider to active");
await tx.backupProviders.put(oldProv);
@@ -662,7 +662,7 @@ export async function addBackupProvider(
if (req.activate) {
state = {
tag: BackupProviderStateTag.Ready,
- nextBackupTimestamp: getTimestampNow(),
+ nextBackupTimestamp: TalerProtocolTimestamp.now(),
};
} else {
state = {
@@ -701,8 +701,8 @@ export interface ProviderInfo {
* Last communication issue with the provider.
*/
lastError?: TalerErrorDetails;
- lastSuccessfulBackupTimestamp?: Timestamp;
- lastAttemptedBackupTimestamp?: Timestamp;
+ lastSuccessfulBackupTimestamp?: TalerProtocolTimestamp;
+ lastAttemptedBackupTimestamp?: TalerProtocolTimestamp;
paymentProposalIds: string[];
backupProblem?: BackupProblem;
paymentStatus: ProviderPaymentStatus;
@@ -724,7 +724,7 @@ export interface BackupConflictingDeviceProblem {
type: "backup-conflicting-device";
otherDeviceId: string;
myDeviceId: string;
- backupTimestamp: Timestamp;
+ backupTimestamp: AbsoluteTime;
}
export type ProviderPaymentStatus =
@@ -774,12 +774,12 @@ export interface ProviderPaymentPending {
export interface ProviderPaymentPaid {
type: ProviderPaymentType.Paid;
- paidUntil: Timestamp;
+ paidUntil: AbsoluteTime;
}
export interface ProviderPaymentTermsChanged {
type: ProviderPaymentType.TermsChanged;
- paidUntil: Timestamp;
+ paidUntil: AbsoluteTime;
oldTerms: BackupProviderTerms;
newTerms: BackupProviderTerms;
}
@@ -811,8 +811,8 @@ async function getProviderPaymentInfo(
if (status.paid) {
return {
type: ProviderPaymentType.Paid,
- paidUntil: timestampAddDuration(
- status.contractTerms.timestamp,
+ paidUntil: AbsoluteTime.addDuration(
+ AbsoluteTime.fromTimestamp(status.contractTerms.timestamp),
durationFromSpec({ years: 1 }),
),
};
@@ -915,7 +915,7 @@ async function backupRecoveryTheirs(
paymentProposalIds: [],
state: {
tag: BackupProviderStateTag.Ready,
- nextBackupTimestamp: getTimestampNow(),
+ nextBackupTimestamp: TalerProtocolTimestamp.now(),
},
uids: [encodeCrock(getRandomBytes(32))],
});
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index a5d6c93cf..4b976011b 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -15,6 +15,7 @@
*/
import {
+ AbsoluteTime,
AmountJson,
Amounts,
buildCodecForObject,
@@ -27,21 +28,16 @@ import {
ContractTerms,
CreateDepositGroupRequest,
CreateDepositGroupResponse,
- DenomKeyType,
durationFromSpec,
encodeCrock,
GetFeeForDepositRequest,
getRandomBytes,
- getTimestampNow,
hashWire,
Logger,
NotificationType,
parsePaytoUri,
TalerErrorDetails,
- Timestamp,
- timestampAddDuration,
- timestampIsBetween,
- timestampTruncateToSecond,
+ TalerProtocolTimestamp,
TrackDepositGroupRequest,
TrackDepositGroupResponse,
URL,
@@ -212,7 +208,7 @@ async function processDepositGroupImpl(
}
}
if (allDeposited) {
- dg.timestampFinished = getTimestampNow();
+ dg.timestampFinished = TalerProtocolTimestamp.now();
dg.operationStatus = OperationStatus.Finished;
delete dg.lastError;
delete dg.retryInfo;
@@ -310,13 +306,8 @@ export async function getFeeForDeposit(
}
});
- const timestamp = getTimestampNow();
- const timestampRound = timestampTruncateToSecond(timestamp);
- // const noncePair = await ws.cryptoApi.createEddsaKeypair();
- // const merchantPair = await ws.cryptoApi.createEddsaKeypair();
- // const wireSalt = encodeCrock(getRandomBytes(16));
- // const wireHash = hashWire(req.depositPaytoUri, wireSalt);
- // const wireHashLegacy = hashWireLegacy(req.depositPaytoUri, wireSalt);
+ const timestamp = AbsoluteTime.now();
+ const timestampRound = AbsoluteTime.toTimestamp(timestamp);
const contractTerms: ContractTerms = {
auditors: [],
exchanges: exchangeInfos,
@@ -331,15 +322,14 @@ export async function getFeeForDeposit(
wire_transfer_deadline: timestampRound,
order_id: "",
h_wire: "",
- pay_deadline: timestampAddDuration(
- timestampRound,
- durationFromSpec({ hours: 1 }),
+ pay_deadline: AbsoluteTime.toTimestamp(
+ AbsoluteTime.addDuration(timestamp, durationFromSpec({ hours: 1 })),
),
merchant: {
name: "",
},
merchant_pub: "",
- refund_deadline: { t_ms: 0 },
+ refund_deadline: TalerProtocolTimestamp.zero(),
};
const contractData = extractContractData(contractTerms, "", "");
@@ -399,8 +389,8 @@ export async function createDepositGroup(
}
});
- const timestamp = getTimestampNow();
- const timestampRound = timestampTruncateToSecond(timestamp);
+ const now = AbsoluteTime.now();
+ const nowRounded = AbsoluteTime.toTimestamp(now);
const noncePair = await ws.cryptoApi.createEddsaKeypair();
const merchantPair = await ws.cryptoApi.createEddsaKeypair();
const wireSalt = encodeCrock(getRandomBytes(16));
@@ -412,24 +402,23 @@ export async function createDepositGroup(
max_fee: Amounts.stringify(amount),
max_wire_fee: Amounts.stringify(amount),
wire_method: p.targetType,
- timestamp: timestampRound,
+ timestamp: nowRounded,
merchant_base_url: "",
summary: "",
nonce: noncePair.pub,
- wire_transfer_deadline: timestampRound,
+ wire_transfer_deadline: nowRounded,
order_id: "",
// This is always the v2 wire hash, as we're the "merchant" and support v2.
h_wire: wireHash,
// Required for older exchanges.
- pay_deadline: timestampAddDuration(
- timestampRound,
- durationFromSpec({ hours: 1 }),
+ pay_deadline: AbsoluteTime.toTimestamp(
+ AbsoluteTime.addDuration(now, durationFromSpec({ hours: 1 })),
),
merchant: {
name: "",
},
merchant_pub: merchantPair.pub,
- refund_deadline: { t_ms: 0 },
+ refund_deadline: TalerProtocolTimestamp.zero(),
};
const contractTermsHash = await ws.cryptoApi.hashString(
@@ -482,7 +471,7 @@ export async function createDepositGroup(
depositGroupId,
noncePriv: noncePair.priv,
noncePub: noncePair.pub,
- timestampCreated: timestamp,
+ timestampCreated: AbsoluteTime.toTimestamp(now),
timestampFinished: undefined,
payCoinSelection: payCoinSel,
payCoinSelectionUid: encodeCrock(getRandomBytes(32)),
@@ -570,10 +559,10 @@ export async function getEffectiveDepositAmount(
// about "find method not found on undefined" when the wireType
// is not supported by the Exchange.
const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => {
- return timestampIsBetween(
- getTimestampNow(),
- x.startStamp,
- x.endStamp,
+ return AbsoluteTime.isBetween(
+ AbsoluteTime.now(),
+ AbsoluteTime.fromTimestamp(x.startStamp),
+ AbsoluteTime.fromTimestamp(x.endStamp),
);
})?.wireFee;
if (fee) {
@@ -656,10 +645,10 @@ export async function getTotalFeeForDepositAmount(
// about "find method not found on undefined" when the wireType
// is not supported by the Exchange.
const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => {
- return timestampIsBetween(
- getTimestampNow(),
- x.startStamp,
- x.endStamp,
+ return AbsoluteTime.isBetween(
+ AbsoluteTime.now(),
+ AbsoluteTime.fromTimestamp(x.startStamp),
+ AbsoluteTime.fromTimestamp(x.endStamp),
);
})?.wireFee;
if (fee) {
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 536d4e3bf..df7eee76d 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -28,8 +28,6 @@ import {
durationFromSpec,
ExchangeSignKeyJson,
ExchangeWireJson,
- getTimestampNow,
- isTimestampExpired,
Logger,
NotificationType,
parsePaytoUri,
@@ -37,13 +35,15 @@ import {
TalerErrorCode,
URL,
TalerErrorDetails,
- Timestamp,
+ AbsoluteTime,
hashDenomPub,
LibtoolVersion,
codecForAny,
DenominationPubKey,
DenomKeyType,
ExchangeKeysJson,
+ TalerProtocolTimestamp,
+ TalerProtocolDuration,
} from "@gnu-taler/taler-util";
import { decodeCrock, encodeCrock, hash } from "@gnu-taler/taler-util";
import { CryptoApi } from "../crypto/workers/cryptoApi.js";
@@ -57,7 +57,7 @@ import {
WireInfo,
} from "../db.js";
import {
- getExpiryTimestamp,
+ getExpiry,
HttpRequestLibrary,
readSuccessResponseJsonOrThrow,
readSuccessResponseTextOrThrow,
@@ -80,7 +80,7 @@ const logger = new Logger("exchanges.ts");
function denominationRecordFromKeys(
exchangeBaseUrl: string,
exchangeMasterPub: string,
- listIssueDate: Timestamp,
+ listIssueDate: TalerProtocolTimestamp,
denomIn: ExchangeDenomination,
): DenominationRecord {
let denomPub: DenominationPubKey;
@@ -132,7 +132,9 @@ async function handleExchangeUpdateError(
}
export function getExchangeRequestTimeout(): Duration {
- return { d_ms: 5000 };
+ return Duration.fromSpec({
+ seconds: 5,
+ });
}
export interface ExchangeTosDownloadResult {
@@ -362,12 +364,11 @@ export async function updateExchangeFromUrl(
async function provideExchangeRecord(
ws: InternalWalletState,
baseUrl: string,
- now: Timestamp,
+ now: AbsoluteTime,
): Promise<{
exchange: ExchangeRecord;
exchangeDetails: ExchangeDetailsRecord | undefined;
}> {
-
return await ws.db
.mktx((x) => ({
exchanges: x.exchanges,
@@ -376,14 +377,14 @@ async function provideExchangeRecord(
.runReadWrite(async (tx) => {
let exchange = await tx.exchanges.get(baseUrl);
if (!exchange) {
- const r = {
+ const r: ExchangeRecord = {
permanent: true,
baseUrl: baseUrl,
retryInfo: initRetryInfo(),
detailsPointer: undefined,
lastUpdate: undefined,
- nextUpdate: now,
- nextRefreshCheck: now,
+ nextUpdate: AbsoluteTime.toTimestamp(now),
+ nextRefreshCheck: AbsoluteTime.toTimestamp(now),
};
await tx.exchanges.put(r);
exchange = r;
@@ -400,10 +401,10 @@ interface ExchangeKeysDownloadResult {
currentDenominations: DenominationRecord[];
protocolVersion: string;
signingKeys: ExchangeSignKeyJson[];
- reserveClosingDelay: Duration;
- expiry: Timestamp;
+ reserveClosingDelay: TalerProtocolDuration;
+ expiry: TalerProtocolTimestamp;
recoup: Recoup[];
- listIssueDate: Timestamp;
+ listIssueDate: TalerProtocolTimestamp;
}
/**
@@ -475,9 +476,11 @@ async function downloadExchangeKeysInfo(
protocolVersion: exchangeKeysJsonUnchecked.version,
signingKeys: exchangeKeysJsonUnchecked.signkeys,
reserveClosingDelay: exchangeKeysJsonUnchecked.reserve_closing_delay,
- expiry: getExpiryTimestamp(resp, {
- minDuration: durationFromSpec({ hours: 1 }),
- }),
+ expiry: AbsoluteTime.toTimestamp(
+ getExpiry(resp, {
+ minDuration: durationFromSpec({ hours: 1 }),
+ }),
+ ),
recoup: exchangeKeysJsonUnchecked.recoup ?? [],
listIssueDate: exchangeKeysJsonUnchecked.list_issue_date,
};
@@ -529,12 +532,20 @@ async function updateExchangeFromUrlImpl(
exchangeDetails: ExchangeDetailsRecord;
}> {
logger.info(`updating exchange info for ${baseUrl}, forced: ${forceNow}`);
- const now = getTimestampNow();
+ const now = AbsoluteTime.now();
baseUrl = canonicalizeBaseUrl(baseUrl);
- const { exchange, exchangeDetails } = await provideExchangeRecord(ws, baseUrl, now);
+ const { exchange, exchangeDetails } = await provideExchangeRecord(
+ ws,
+ baseUrl,
+ now,
+ );
- if (!forceNow && exchangeDetails !== undefined && !isTimestampExpired(exchange.nextUpdate)) {
+ if (
+ !forceNow &&
+ exchangeDetails !== undefined &&
+ !AbsoluteTime.isExpired(AbsoluteTime.fromTimestamp(exchange.nextUpdate))
+ ) {
logger.info("using existing exchange info");
return { exchange, exchangeDetails };
}
@@ -575,7 +586,8 @@ async function updateExchangeFromUrlImpl(
timeout,
acceptedFormat,
);
- const tosHasBeenAccepted = exchangeDetails?.termsOfServiceAcceptedEtag === tosDownload.tosEtag
+ const tosHasBeenAccepted =
+ exchangeDetails?.termsOfServiceAcceptedEtag === tosDownload.tosEtag;
let recoupGroupId: string | undefined;
@@ -611,23 +623,25 @@ async function updateExchangeFromUrlImpl(
exchangeBaseUrl: r.baseUrl,
wireInfo,
termsOfServiceText: tosDownload.tosText,
- termsOfServiceAcceptedEtag: tosHasBeenAccepted ? tosDownload.tosEtag : undefined,
+ termsOfServiceAcceptedEtag: tosHasBeenAccepted
+ ? tosDownload.tosEtag
+ : undefined,
termsOfServiceContentType: tosDownload.tosContentType,
termsOfServiceLastEtag: tosDownload.tosEtag,
- termsOfServiceAcceptedTimestamp: getTimestampNow(),
+ termsOfServiceAcceptedTimestamp: TalerProtocolTimestamp.now(),
};
// FIXME: only update if pointer got updated
r.lastError = undefined;
r.retryInfo = initRetryInfo();
- r.lastUpdate = getTimestampNow();
+ r.lastUpdate = TalerProtocolTimestamp.now();
r.nextUpdate = keysInfo.expiry;
// New denominations might be available.
- r.nextRefreshCheck = getTimestampNow();
+ r.nextRefreshCheck = TalerProtocolTimestamp.now();
r.detailsPointer = {
currency: details.currency,
masterPublicKey: details.masterPublicKey,
// FIXME: only change if pointer really changed
- updateClock: getTimestampNow(),
+ updateClock: TalerProtocolTimestamp.now(),
protocolVersionRange: keysInfo.protocolVersion,
};
await tx.exchanges.put(r);
diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts
index 9844dc52e..9521d544f 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -27,7 +27,6 @@
import {
AmountJson,
Amounts,
- CheckPaymentResponse,
codecForContractTerms,
codecForMerchantPayResponse,
codecForProposal,
@@ -41,11 +40,8 @@ import {
durationMin,
durationMul,
encodeCrock,
- getDurationRemaining,
getRandomBytes,
- getTimestampNow,
HttpStatusCode,
- isTimestampExpired,
j2s,
kdf,
Logger,
@@ -57,9 +53,9 @@ import {
stringToBytes,
TalerErrorCode,
TalerErrorDetails,
- Timestamp,
- timestampAddDuration,
+ AbsoluteTime,
URL,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { EXCHANGE_COINS_LOCK, InternalWalletState } from "../common.js";
import {
@@ -172,7 +168,9 @@ function isSpendableCoin(coin: CoinRecord, denom: DenominationRecord): boolean {
if (coin.status !== CoinStatus.Fresh) {
return false;
}
- if (isTimestampExpired(denom.stampExpireDeposit)) {
+ if (
+ AbsoluteTime.isExpired(AbsoluteTime.fromTimestamp(denom.stampExpireDeposit))
+ ) {
return false;
}
return true;
@@ -187,7 +185,7 @@ export interface CoinSelectionRequest {
/**
* Timestamp of the contract.
*/
- timestamp: Timestamp;
+ timestamp: TalerProtocolTimestamp;
wireMethod: string;
@@ -422,7 +420,7 @@ async function recordConfirmPay(
payCoinSelectionUid: encodeCrock(getRandomBytes(32)),
totalPayCost: payCostInfo,
coinDepositPermissions,
- timestampAccept: getTimestampNow(),
+ timestampAccept: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
timestampLastRefundStatus: undefined,
proposalId: proposal.proposalId,
lastPayError: undefined,
@@ -784,7 +782,7 @@ async function processDownloadProposalImpl(
} catch (e) {
const err = makeErrorDetails(
TalerErrorCode.WALLET_CONTRACT_TERMS_MALFORMED,
- "schema validation failed",
+ `schema validation failed: ${e}`,
{},
);
await failProposalPermanently(ws, proposalId, err);
@@ -921,7 +919,7 @@ async function startDownloadProposal(
noncePriv: priv,
noncePub: pub,
claimToken,
- timestamp: getTimestampNow(),
+ timestamp: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
merchantBaseUrl,
orderId,
proposalId: proposalId,
@@ -956,7 +954,7 @@ async function storeFirstPaySuccess(
sessionId: string | undefined,
paySig: string,
): Promise<void> {
- const now = getTimestampNow();
+ const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
await ws.db
.mktx((x) => ({ purchases: x.purchases }))
.runReadWrite(async (tx) => {
@@ -978,13 +976,16 @@ async function storeFirstPaySuccess(
purchase.payRetryInfo = initRetryInfo();
purchase.merchantPaySig = paySig;
if (isFirst) {
- const ar = purchase.download.contractData.autoRefund;
- if (ar) {
+ const protoAr = purchase.download.contractData.autoRefund;
+ if (protoAr) {
+ const ar = Duration.fromTalerProtocolDuration(protoAr);
logger.info("auto_refund present");
purchase.refundQueryRequested = true;
purchase.refundStatusRetryInfo = initRetryInfo();
purchase.lastRefundStatusError = undefined;
- purchase.autoRefundDeadline = timestampAddDuration(now, ar);
+ purchase.autoRefundDeadline = AbsoluteTime.toTimestamp(
+ AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
+ );
}
}
await tx.purchases.put(purchase);
@@ -1150,7 +1151,7 @@ async function unblockBackup(
if (bp.state.tag === BackupProviderStateTag.Retrying) {
bp.state = {
tag: BackupProviderStateTag.Ready,
- nextBackupTimestamp: getTimestampNow(),
+ nextBackupTimestamp: TalerProtocolTimestamp.now(),
};
}
});
diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts
index 6d686fb3a..fc76eeb19 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -35,7 +35,7 @@ import {
PendingTaskType,
ReserveType,
} from "../pending-types.js";
-import { getTimestampNow, Timestamp } from "@gnu-taler/taler-util";
+import { AbsoluteTime } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../common.js";
import { GetReadOnlyAccess } from "../util/query.js";
@@ -44,21 +44,25 @@ async function gatherExchangePending(
exchanges: typeof WalletStoresV1.exchanges;
exchangeDetails: typeof WalletStoresV1.exchangeDetails;
}>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
await tx.exchanges.iter().forEachAsync(async (e) => {
resp.pendingOperations.push({
type: PendingTaskType.ExchangeUpdate,
givesLifeness: false,
- timestampDue: e.lastError ? e.retryInfo.nextRetry : e.nextUpdate,
+ timestampDue: e.lastError
+ ? e.retryInfo.nextRetry
+ : AbsoluteTime.fromTimestamp(e.nextUpdate),
exchangeBaseUrl: e.baseUrl,
lastError: e.lastError,
});
resp.pendingOperations.push({
type: PendingTaskType.ExchangeCheckRefresh,
- timestampDue: e.lastError ? e.retryInfo.nextRetry : e.nextRefreshCheck,
+ timestampDue: e.lastError
+ ? e.retryInfo.nextRetry
+ : AbsoluteTime.fromTimestamp(e.nextRefreshCheck),
givesLifeness: false,
exchangeBaseUrl: e.baseUrl,
});
@@ -67,7 +71,7 @@ async function gatherExchangePending(
async function gatherReservePending(
tx: GetReadOnlyAccess<{ reserves: typeof WalletStoresV1.reserves }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
const reserves = await tx.reserves.indexes.byStatus.getAll(
@@ -87,7 +91,7 @@ async function gatherReservePending(
resp.pendingOperations.push({
type: PendingTaskType.Reserve,
givesLifeness: true,
- timestampDue: reserve.retryInfo?.nextRetry ?? Timestamp.now(),
+ timestampDue: reserve.retryInfo?.nextRetry ?? AbsoluteTime.now(),
stage: reserve.reserveStatus,
timestampCreated: reserve.timestampCreated,
reserveType,
@@ -105,7 +109,7 @@ async function gatherReservePending(
async function gatherRefreshPending(
tx: GetReadOnlyAccess<{ refreshGroups: typeof WalletStoresV1.refreshGroups }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
const refreshGroups = await tx.refreshGroups.indexes.byStatus.getAll(
@@ -136,7 +140,7 @@ async function gatherWithdrawalPending(
withdrawalGroups: typeof WalletStoresV1.withdrawalGroups;
planchets: typeof WalletStoresV1.planchets;
}>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
const wsrs = await tx.withdrawalGroups.indexes.byStatus.getAll(
@@ -169,14 +173,14 @@ async function gatherWithdrawalPending(
async function gatherProposalPending(
tx: GetReadOnlyAccess<{ proposals: typeof WalletStoresV1.proposals }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
await tx.proposals.iter().forEach((proposal) => {
if (proposal.proposalStatus == ProposalStatus.Proposed) {
// Nothing to do, user needs to choose.
} else if (proposal.proposalStatus == ProposalStatus.Downloading) {
- const timestampDue = proposal.retryInfo?.nextRetry ?? getTimestampNow();
+ const timestampDue = proposal.retryInfo?.nextRetry ?? AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.ProposalDownload,
givesLifeness: true,
@@ -194,7 +198,7 @@ async function gatherProposalPending(
async function gatherDepositPending(
tx: GetReadOnlyAccess<{ depositGroups: typeof WalletStoresV1.depositGroups }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
const dgs = await tx.depositGroups.indexes.byStatus.getAll(
@@ -204,7 +208,7 @@ async function gatherDepositPending(
if (dg.timestampFinished) {
return;
}
- const timestampDue = dg.retryInfo?.nextRetry ?? getTimestampNow();
+ const timestampDue = dg.retryInfo?.nextRetry ?? AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Deposit,
givesLifeness: true,
@@ -218,7 +222,7 @@ async function gatherDepositPending(
async function gatherTipPending(
tx: GetReadOnlyAccess<{ tips: typeof WalletStoresV1.tips }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
await tx.tips.iter().forEach((tip) => {
@@ -240,7 +244,7 @@ async function gatherTipPending(
async function gatherPurchasePending(
tx: GetReadOnlyAccess<{ purchases: typeof WalletStoresV1.purchases }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
await tx.purchases.iter().forEach((pr) => {
@@ -249,7 +253,7 @@ async function gatherPurchasePending(
pr.abortStatus === AbortStatus.None &&
!pr.payFrozen
) {
- const timestampDue = pr.payRetryInfo?.nextRetry ?? getTimestampNow();
+ const timestampDue = pr.payRetryInfo?.nextRetry ?? AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Pay,
givesLifeness: true,
@@ -275,7 +279,7 @@ async function gatherPurchasePending(
async function gatherRecoupPending(
tx: GetReadOnlyAccess<{ recoupGroups: typeof WalletStoresV1.recoupGroups }>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
await tx.recoupGroups.iter().forEach((rg) => {
@@ -297,7 +301,7 @@ async function gatherBackupPending(
tx: GetReadOnlyAccess<{
backupProviders: typeof WalletStoresV1.backupProviders;
}>,
- now: Timestamp,
+ now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
await tx.backupProviders.iter().forEach((bp) => {
@@ -305,7 +309,7 @@ async function gatherBackupPending(
resp.pendingOperations.push({
type: PendingTaskType.Backup,
givesLifeness: false,
- timestampDue: bp.state.nextBackupTimestamp,
+ timestampDue: AbsoluteTime.fromTimestamp(bp.state.nextBackupTimestamp),
backupProviderBaseUrl: bp.baseUrl,
lastError: undefined,
});
@@ -325,7 +329,7 @@ async function gatherBackupPending(
export async function getPendingOperations(
ws: InternalWalletState,
): Promise<PendingOperationsResponse> {
- const now = getTimestampNow();
+ const now = AbsoluteTime.now();
return await ws.db
.mktx((x) => ({
backupProviders: x.backupProviders,
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts
index 23d14f212..84a27966d 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -27,11 +27,11 @@
import {
Amounts,
codecForRecoupConfirmation,
- getTimestampNow,
j2s,
NotificationType,
RefreshReason,
TalerErrorDetails,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
import {
@@ -110,7 +110,7 @@ async function putGroupAsFinished(
}
if (allFinished) {
logger.info("all recoups of recoup group are finished");
- recoupGroup.timestampFinished = getTimestampNow();
+ recoupGroup.timestampFinished = TalerProtocolTimestamp.now();
recoupGroup.retryInfo = initRetryInfo();
recoupGroup.lastError = undefined;
if (recoupGroup.scheduleRefreshCoins.length > 0) {
@@ -467,7 +467,7 @@ export async function createRecoupGroup(
coinPubs: coinPubs,
lastError: undefined,
timestampFinished: undefined,
- timestampStarted: getTimestampNow(),
+ timestampStarted: TalerProtocolTimestamp.now(),
retryInfo: initRetryInfo(),
recoupFinishedPerCoin: coinPubs.map(() => false),
// Will be populated later
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index 8b6d8b2e4..11f0f6c51 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -23,7 +23,7 @@ import {
ExchangeRefreshRevealRequest,
getRandomBytes,
HttpStatusCode,
- j2s,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import {
CoinRecord,
@@ -42,11 +42,8 @@ import {
fnutil,
NotificationType,
RefreshGroupId,
- RefreshPlanchetInfo,
RefreshReason,
- stringifyTimestamp,
TalerErrorDetails,
- timestampToIsoString,
} from "@gnu-taler/taler-util";
import { AmountJson, Amounts } from "@gnu-taler/taler-util";
import { amountToPretty } from "@gnu-taler/taler-util";
@@ -61,12 +58,7 @@ import {
Duration,
durationFromSpec,
durationMul,
- getTimestampNow,
- isTimestampExpired,
- Timestamp,
- timestampAddDuration,
- timestampDifference,
- timestampMin,
+ AbsoluteTime,
URL,
} from "@gnu-taler/taler-util";
import { guardOperationException } from "../errors.js";
@@ -139,7 +131,7 @@ function updateGroupStatus(rg: RefreshGroupRecord): void {
rg.frozen = true;
rg.retryInfo = initRetryInfo();
} else {
- rg.timestampFinished = getTimestampNow();
+ rg.timestampFinished = AbsoluteTime.toTimestamp(AbsoluteTime.now());
rg.operationStatus = OperationStatus.Finished;
rg.retryInfo = initRetryInfo();
}
@@ -234,19 +226,6 @@ async function refreshCreateSession(
availableDenoms,
);
- if (logger.shouldLogTrace()) {
- logger.trace(`printing selected denominations for refresh`);
- logger.trace(`current time: ${stringifyTimestamp(getTimestampNow())}`);
- for (const denom of newCoinDenoms.selectedDenoms) {
- logger.trace(`denom ${denom.denom}, count ${denom.count}`);
- logger.trace(
- `withdrawal expiration ${stringifyTimestamp(
- denom.denom.stampExpireWithdraw,
- )}`,
- );
- }
- }
-
if (newCoinDenoms.selectedDenoms.length === 0) {
logger.trace(
`not refreshing, available amount ${amountToPretty(
@@ -306,7 +285,9 @@ async function refreshCreateSession(
}
function getRefreshRequestTimeout(rg: RefreshGroupRecord): Duration {
- return { d_ms: 5000 };
+ return Duration.fromSpec({
+ seconds: 5,
+ });
}
async function refreshMelt(
@@ -949,12 +930,12 @@ export async function createRefreshGroup(
retryInfo: initRetryInfo(),
inputPerCoin,
estimatedOutputPerCoin,
- timestampCreated: getTimestampNow(),
+ timestampCreated: TalerProtocolTimestamp.now(),
};
if (oldCoinPubs.length == 0) {
logger.warn("created refresh group with zero coins");
- refreshGroup.timestampFinished = getTimestampNow();
+ refreshGroup.timestampFinished = TalerProtocolTimestamp.now();
refreshGroup.operationStatus = OperationStatus.Finished;
}
@@ -974,25 +955,23 @@ export async function createRefreshGroup(
/**
* Timestamp after which the wallet would do the next check for an auto-refresh.
*/
-function getAutoRefreshCheckThreshold(d: DenominationRecord): Timestamp {
- const delta = timestampDifference(
- d.stampExpireWithdraw,
- d.stampExpireDeposit,
- );
+function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
+ const expireWithdraw = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw);
+ const expireDeposit = AbsoluteTime.fromTimestamp(d.stampExpireDeposit);
+ const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.75);
- return timestampAddDuration(d.stampExpireWithdraw, deltaDiv);
+ return AbsoluteTime.addDuration(expireWithdraw, deltaDiv);
}
/**
* Timestamp after which the wallet would do an auto-refresh.
*/
-function getAutoRefreshExecuteThreshold(d: DenominationRecord): Timestamp {
- const delta = timestampDifference(
- d.stampExpireWithdraw,
- d.stampExpireDeposit,
- );
+function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
+ const expireWithdraw = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw);
+ const expireDeposit = AbsoluteTime.fromTimestamp(d.stampExpireDeposit);
+ const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.5);
- return timestampAddDuration(d.stampExpireWithdraw, deltaDiv);
+ return AbsoluteTime.addDuration(expireWithdraw, deltaDiv);
}
export async function autoRefresh(
@@ -1001,8 +980,8 @@ export async function autoRefresh(
): Promise<void> {
logger.info(`doing auto-refresh check for '${exchangeBaseUrl}'`);
await updateExchangeFromUrl(ws, exchangeBaseUrl, undefined, true);
- let minCheckThreshold = timestampAddDuration(
- getTimestampNow(),
+ let minCheckThreshold = AbsoluteTime.addDuration(
+ AbsoluteTime.now(),
durationFromSpec({ days: 1 }),
);
await ws.db
@@ -1037,11 +1016,14 @@ export async function autoRefresh(
continue;
}
const executeThreshold = getAutoRefreshExecuteThreshold(denom);
- if (isTimestampExpired(executeThreshold)) {
+ if (AbsoluteTime.isExpired(executeThreshold)) {
refreshCoins.push(coin);
} else {
const checkThreshold = getAutoRefreshCheckThreshold(denom);
- minCheckThreshold = timestampMin(minCheckThreshold, checkThreshold);
+ minCheckThreshold = AbsoluteTime.min(
+ minCheckThreshold,
+ checkThreshold,
+ );
}
}
if (refreshCoins.length > 0) {
@@ -1056,12 +1038,12 @@ export async function autoRefresh(
);
}
logger.info(
- `current wallet time: ${timestampToIsoString(getTimestampNow())}`,
+ `current wallet time: ${AbsoluteTime.toIsoString(AbsoluteTime.now())}`,
);
logger.info(
- `next refresh check at ${timestampToIsoString(minCheckThreshold)}`,
+ `next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
);
- exchange.nextRefreshCheck = minCheckThreshold;
+ exchange.nextRefreshCheck = AbsoluteTime.toTimestamp(minCheckThreshold);
await tx.exchanges.put(exchange);
});
}
diff --git a/packages/taler-wallet-core/src/operations/refund.ts b/packages/taler-wallet-core/src/operations/refund.ts
index 106c79365..686d545df 100644
--- a/packages/taler-wallet-core/src/operations/refund.ts
+++ b/packages/taler-wallet-core/src/operations/refund.ts
@@ -32,7 +32,6 @@ import {
codecForAbortResponse,
codecForMerchantOrderRefundPickupResponse,
CoinPublicKey,
- getTimestampNow,
Logger,
MerchantCoinRefundFailureStatus,
MerchantCoinRefundStatus,
@@ -43,9 +42,10 @@ import {
TalerErrorCode,
TalerErrorDetails,
URL,
- timestampAddDuration,
codecForMerchantOrderStatusPaid,
- isTimestampExpired,
+ AbsoluteTime,
+ TalerProtocolTimestamp,
+ Duration,
} from "@gnu-taler/taler-util";
import {
AbortStatus,
@@ -170,7 +170,7 @@ async function applySuccessfulRefund(
p.refunds[refundKey] = {
type: RefundState.Applied,
- obtainedTime: getTimestampNow(),
+ obtainedTime: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
executionTime: r.execution_time,
refundAmount: Amounts.parseOrThrow(r.refund_amount),
refundFee: denom.feeRefund,
@@ -222,7 +222,7 @@ async function storePendingRefund(
p.refunds[refundKey] = {
type: RefundState.Pending,
- obtainedTime: getTimestampNow(),
+ obtainedTime: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
executionTime: r.execution_time,
refundAmount: Amounts.parseOrThrow(r.refund_amount),
refundFee: denom.feeRefund,
@@ -275,7 +275,7 @@ async function storeFailedRefund(
p.refunds[refundKey] = {
type: RefundState.Failed,
- obtainedTime: getTimestampNow(),
+ obtainedTime: TalerProtocolTimestamp.now(),
executionTime: r.execution_time,
refundAmount: Amounts.parseOrThrow(r.refund_amount),
refundFee: denom.feeRefund,
@@ -327,7 +327,7 @@ async function acceptRefunds(
reason: RefundReason,
): Promise<void> {
logger.trace("handling refunds", refunds);
- const now = getTimestampNow();
+ const now = TalerProtocolTimestamp.now();
await ws.db
.mktx((x) => ({
@@ -401,7 +401,10 @@ async function acceptRefunds(
if (
p.timestampFirstSuccessfulPay &&
p.autoRefundDeadline &&
- p.autoRefundDeadline.t_ms > now.t_ms
+ AbsoluteTime.cmp(
+ AbsoluteTime.fromTimestamp(p.autoRefundDeadline),
+ AbsoluteTime.fromTimestamp(now),
+ ) > 0
) {
queryDone = false;
}
@@ -556,8 +559,10 @@ export async function applyRefund(
).amount,
).amount;
} else {
- amountRefundGone = Amounts.add(amountRefundGone, refund.refundAmount)
- .amount;
+ amountRefundGone = Amounts.add(
+ amountRefundGone,
+ refund.refundAmount,
+ ).amount;
}
});
@@ -623,7 +628,9 @@ async function processPurchaseQueryRefundImpl(
if (
waitForAutoRefund &&
purchase.autoRefundDeadline &&
- !isTimestampExpired(purchase.autoRefundDeadline)
+ !AbsoluteTime.isExpired(
+ AbsoluteTime.fromTimestamp(purchase.autoRefundDeadline),
+ )
) {
const requestUrl = new URL(
`orders/${purchase.download.contractData.orderId}`,
@@ -731,11 +738,13 @@ async function processPurchaseQueryRefundImpl(
purchase.payCoinSelection.coinContributions[i],
),
rtransaction_id: 0,
- execution_time: timestampAddDuration(
- purchase.download.contractData.timestamp,
- {
- d_ms: 1000,
- },
+ execution_time: AbsoluteTime.toTimestamp(
+ AbsoluteTime.addDuration(
+ AbsoluteTime.fromTimestamp(
+ purchase.download.contractData.timestamp,
+ ),
+ Duration.fromSpec({ seconds: 1 }),
+ ),
),
});
}
diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts
index d91ce89f1..ac9483631 100644
--- a/packages/taler-wallet-core/src/operations/reserves.ts
+++ b/packages/taler-wallet-core/src/operations/reserves.ts
@@ -29,15 +29,13 @@ import {
durationMin,
encodeCrock,
getRandomBytes,
- getTimestampNow,
j2s,
Logger,
NotificationType,
randomBytes,
- ReserveTransactionType,
TalerErrorCode,
TalerErrorDetails,
- Timestamp,
+ AbsoluteTime,
URL,
} from "@gnu-taler/taler-util";
import { InternalWalletState } from "../common.js";
@@ -172,7 +170,7 @@ export async function createReserve(
req: CreateReserveRequest,
): Promise<CreateReserveResponse> {
const keypair = await ws.cryptoApi.createEddsaKeypair();
- const now = getTimestampNow();
+ const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
const canonExchange = canonicalizeBaseUrl(req.exchange);
let reserveStatus;
@@ -217,7 +215,6 @@ export async function createReserve(
timestampReserveInfoPosted: undefined,
bankInfo,
reserveStatus,
- lastSuccessfulStatusQuery: undefined,
retryInfo: initRetryInfo(),
lastError: undefined,
currency: req.amount.currency,
@@ -403,7 +400,9 @@ async function registerReserveWithBank(
default:
return;
}
- r.timestampReserveInfoPosted = getTimestampNow();
+ r.timestampReserveInfoPosted = AbsoluteTime.toTimestamp(
+ AbsoluteTime.now(),
+ );
r.reserveStatus = ReserveRecordStatus.WaitConfirmBank;
r.operationStatus = OperationStatus.Pending;
if (!r.bankInfo) {
@@ -472,7 +471,7 @@ async function processReserveBankStatus(
default:
return;
}
- const now = getTimestampNow();
+ const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
r.timestampBankConfirmed = now;
r.reserveStatus = ReserveRecordStatus.BankAborted;
r.operationStatus = OperationStatus.Finished;
@@ -509,7 +508,7 @@ async function processReserveBankStatus(
default:
return;
}
- const now = getTimestampNow();
+ const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
r.timestampBankConfirmed = now;
r.reserveStatus = ReserveRecordStatus.QueryingStatus;
r.operationStatus = OperationStatus.Pending;
@@ -683,7 +682,7 @@ async function updateReserve(
exchangeBaseUrl: reserve.exchangeBaseUrl,
reservePub: reserve.reservePub,
rawWithdrawalAmount: remainingAmount,
- timestampStart: getTimestampNow(),
+ timestampStart: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
retryInfo: initRetryInfo(),
lastError: undefined,
denomsSel: denomSelectionInfoToState(denomSelInfo),
@@ -736,7 +735,7 @@ async function processReserveImpl(
await resetReserveRetry(ws, reservePub);
} else if (
reserve.retryInfo &&
- !Timestamp.isExpired(reserve.retryInfo.nextRetry)
+ !AbsoluteTime.isExpired(reserve.retryInfo.nextRetry)
) {
logger.trace("processReserve retry not due yet");
return;
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
index 93f48fb83..23fee56c1 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -229,8 +229,8 @@ async function createOrder(
amount,
summary,
fulfillment_url: fulfillmentUrl,
- refund_deadline: { t_ms: t * 1000 },
- wire_transfer_deadline: { t_ms: t * 1000 },
+ refund_deadline: { t_s: t },
+ wire_transfer_deadline: { t_s: t },
},
};
const resp = await http.postJson(reqUrl, orderReq, {
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index a2a4e6f49..765120294 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -22,7 +22,6 @@ import {
parseTipUri,
codecForTipPickupGetResponse,
Amounts,
- getTimestampNow,
TalerErrorDetails,
NotificationType,
TipPlanchetDetail,
@@ -32,6 +31,7 @@ import {
DenomKeyType,
BlindedDenominationSignature,
codecForMerchantTipResponseV2,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { DerivedTipPlanchet } from "../crypto/cryptoTypes.js";
import {
@@ -39,6 +39,7 @@ import {
CoinRecord,
CoinSourceType,
CoinStatus,
+ TipRecord,
} from "../db.js";
import { j2s } from "@gnu-taler/taler-util";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
@@ -115,14 +116,14 @@ export async function prepareTip(
const secretSeed = encodeCrock(getRandomBytes(64));
const denomSelUid = encodeCrock(getRandomBytes(32));
- const newTipRecord = {
+ const newTipRecord: TipRecord = {
walletTipId: walletTipId,
acceptedTimestamp: undefined,
tipAmountRaw: amount,
tipExpiration: tipPickupStatus.expiration,
exchangeBaseUrl: tipPickupStatus.exchange_url,
merchantBaseUrl: res.merchantBaseUrl,
- createdTimestamp: getTimestampNow(),
+ createdTimestamp: TalerProtocolTimestamp.now(),
merchantTipId: res.merchantTipId,
tipAmountEffective: Amounts.sub(
amount,
@@ -397,7 +398,7 @@ async function processTipImpl(
if (tr.pickedUpTimestamp) {
return;
}
- tr.pickedUpTimestamp = getTimestampNow();
+ tr.pickedUpTimestamp = TalerProtocolTimestamp.now();
tr.lastError = undefined;
tr.retryInfo = initRetryInfo();
await tx.tips.put(tr);
@@ -421,7 +422,7 @@ export async function acceptTip(
logger.error("tip not found");
return false;
}
- tipRecord.acceptedTimestamp = getTimestampNow();
+ tipRecord.acceptedTimestamp = TalerProtocolTimestamp.now();
await tx.tips.put(tipRecord);
return true;
});
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index 23ab39052..bc466f5a0 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -18,12 +18,12 @@
* Imports.
*/
import {
+ AbsoluteTime,
AmountJson,
Amounts,
Logger,
OrderShortInfo,
PaymentStatus,
- timestampCmp,
Transaction,
TransactionsRequest,
TransactionsResponse,
@@ -309,7 +309,7 @@ export async function getTransactions(
for (const rk of Object.keys(pr.refunds)) {
const refund = pr.refunds[rk];
- const groupKey = `${refund.executionTime.t_ms}`;
+ const groupKey = `${refund.executionTime.t_s}`;
refundGroupKeys.add(groupKey);
}
@@ -333,7 +333,7 @@ export async function getTransactions(
let amountEffective = Amounts.getZero(contractData.amount.currency);
for (const rk of Object.keys(pr.refunds)) {
const refund = pr.refunds[rk];
- const myGroupKey = `${refund.executionTime.t_ms}`;
+ const myGroupKey = `${refund.executionTime.t_s}`;
if (myGroupKey !== groupKey) {
continue;
}
@@ -403,8 +403,18 @@ export async function getTransactions(
const txPending = transactions.filter((x) => x.pending);
const txNotPending = transactions.filter((x) => !x.pending);
- txPending.sort((h1, h2) => timestampCmp(h1.timestamp, h2.timestamp));
- txNotPending.sort((h1, h2) => timestampCmp(h1.timestamp, h2.timestamp));
+ txPending.sort((h1, h2) =>
+ AbsoluteTime.cmp(
+ AbsoluteTime.fromTimestamp(h1.timestamp),
+ AbsoluteTime.fromTimestamp(h2.timestamp),
+ ),
+ );
+ txNotPending.sort((h1, h2) =>
+ AbsoluteTime.cmp(
+ AbsoluteTime.fromTimestamp(h1.timestamp),
+ AbsoluteTime.fromTimestamp(h2.timestamp),
+ ),
+ );
return { transactions: [...txNotPending, ...txPending] };
}
@@ -485,11 +495,10 @@ export async function deleteTransaction(
});
return;
}
- const reserveRecord:
- | ReserveRecord
- | undefined = await tx.reserves.indexes.byInitialWithdrawalGroupId.get(
- withdrawalGroupId,
- );
+ const reserveRecord: ReserveRecord | undefined =
+ await tx.reserves.indexes.byInitialWithdrawalGroupId.get(
+ withdrawalGroupId,
+ );
if (reserveRecord && !reserveRecord.initialWithdrawalStarted) {
const reservePub = reserveRecord.reservePub;
await tx.reserves.delete(reservePub);
diff --git a/packages/taler-wallet-core/src/operations/withdraw.test.ts b/packages/taler-wallet-core/src/operations/withdraw.test.ts
index 02540848a..e5894a3e7 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.test.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.test.ts
@@ -62,16 +62,16 @@ test("withdrawal selection bug repro", (t) => {
masterSig:
"4F0P456CNNTTWK8BFJHGM3JTD6FVVNZY8EP077GYAHDJ5Y81S5RQ3SMS925NXMDVG9A88JAAP0E2GDZBC21PP5NHFFVWHAW3AVT8J3R",
stampExpireDeposit: {
- t_ms: 1742909388000,
+ t_s: 1742909388,
},
stampExpireLegal: {
- t_ms: 1900589388000,
+ t_s: 1900589388,
},
stampExpireWithdraw: {
- t_ms: 1679837388000,
+ t_s: 1679837388,
},
stampStart: {
- t_ms: 1585229388000,
+ t_s: 1585229388,
},
verificationStatus: DenominationVerificationStatus.Unverified,
value: {
@@ -79,7 +79,7 @@ test("withdrawal selection bug repro", (t) => {
fraction: 0,
value: 1000,
},
- listIssueDate: { t_ms: 0 },
+ listIssueDate: { t_s: 0 },
},
{
denomPub: {
@@ -117,16 +117,16 @@ test("withdrawal selection bug repro", (t) => {
masterSig:
"P99AW82W46MZ0AKW7Z58VQPXFNTJQM9DVTYPBDF6KVYF38PPVDAZTV7JQ8TY7HGEC7JJJAY4E7AY7J3W1WV10DAZZQHHKTAVTSRAC20",
stampExpireDeposit: {
- t_ms: 1742909388000,
+ t_s: 1742909388,
},
stampExpireLegal: {
- t_ms: 1900589388000,
+ t_s: 1900589388,
},
stampExpireWithdraw: {
- t_ms: 1679837388000,
+ t_s: 1679837388,
},
stampStart: {
- t_ms: 1585229388000,
+ t_s: 1585229388,
},
verificationStatus: DenominationVerificationStatus.Unverified,
value: {
@@ -134,7 +134,7 @@ test("withdrawal selection bug repro", (t) => {
fraction: 0,
value: 10,
},
- listIssueDate: { t_ms: 0 },
+ listIssueDate: { t_s: 0 },
},
{
denomPub: {
@@ -171,16 +171,16 @@ test("withdrawal selection bug repro", (t) => {
masterSig:
"8S4VZGHE5WE0N5ZVCHYW9KZZR4YAKK15S46MV1HR1QB9AAMH3NWPW4DCR4NYGJK33Q8YNFY80SWNS6XKAP5DEVK933TM894FJ2VGE3G",
stampExpireDeposit: {
- t_ms: 1742909388000,
+ t_s: 1742909388,
},
stampExpireLegal: {
- t_ms: 1900589388000,
+ t_s: 1900589388,
},
stampExpireWithdraw: {
- t_ms: 1679837388000,
+ t_s: 1679837388,
},
stampStart: {
- t_ms: 1585229388000,
+ t_s: 1585229388,
},
verificationStatus: DenominationVerificationStatus.Unverified,
value: {
@@ -188,7 +188,7 @@ test("withdrawal selection bug repro", (t) => {
fraction: 0,
value: 5,
},
- listIssueDate: { t_ms: 0 },
+ listIssueDate: { t_s: 0 },
},
{
denomPub: {
@@ -226,16 +226,16 @@ test("withdrawal selection bug repro", (t) => {
masterSig:
"E3AWGAG8VB42P3KXM8B04Z6M483SX59R3Y4T53C3NXCA2NPB6C7HVCMVX05DC6S58E9X40NGEBQNYXKYMYCF3ASY2C4WP1WCZ4ME610",
stampExpireDeposit: {
- t_ms: 1742909388000,
+ t_s: 1742909388,
},
stampExpireLegal: {
- t_ms: 1900589388000,
+ t_s: 1900589388,
},
stampExpireWithdraw: {
- t_ms: 1679837388000,
+ t_s: 1679837388,
},
stampStart: {
- t_ms: 1585229388000,
+ t_s: 1585229388,
},
verificationStatus: DenominationVerificationStatus.Unverified,
value: {
@@ -243,7 +243,7 @@ test("withdrawal selection bug repro", (t) => {
fraction: 0,
value: 1,
},
- listIssueDate: { t_ms: 0 },
+ listIssueDate: { t_s: 0 },
},
{
denomPub: {
@@ -280,16 +280,16 @@ test("withdrawal selection bug repro", (t) => {
masterSig:
"0ES1RKV002XB4YP21SN0QB7RSDHGYT0XAE65JYN8AVJAA6H7JZFN7JADXT521DJS89XMGPZGR8GCXF1516Y0Q9QDV00E6NMFA6CF838",
stampExpireDeposit: {
- t_ms: 1742909388000,
+ t_s: 1742909388,
},
stampExpireLegal: {
- t_ms: 1900589388000,
+ t_s: 1900589388,
},
stampExpireWithdraw: {
- t_ms: 1679837388000,
+ t_s: 1679837388,
},
stampStart: {
- t_ms: 1585229388000,
+ t_s: 1585229388,
},
verificationStatus: DenominationVerificationStatus.Unverified,
value: {
@@ -297,7 +297,7 @@ test("withdrawal selection bug repro", (t) => {
fraction: 10000000,
value: 0,
},
- listIssueDate: { t_ms: 0 },
+ listIssueDate: { t_s: 0 },
},
{
denomPub: {
@@ -334,16 +334,16 @@ test("withdrawal selection bug repro", (t) => {
masterSig:
"58QEB6C6N7602E572E3JYANVVJ9BRW0V9E2ZFDW940N47YVQDK9SAFPWBN5YGT3G1742AFKQ0CYR4DM2VWV0Z0T1XMEKWN6X2EZ9M0R",
stampExpireDeposit: {
- t_ms: 1742909388000,
+ t_s: 1742909388,
},
stampExpireLegal: {
- t_ms: 1900589388000,
+ t_s: 1900589388,
},
stampExpireWithdraw: {
- t_ms: 1679837388000,
+ t_s: 1679837388,
},
stampStart: {
- t_ms: 1585229388000,
+ t_s: 1585229388,
},
verificationStatus: DenominationVerificationStatus.Unverified,
value: {
@@ -351,7 +351,7 @@ test("withdrawal selection bug repro", (t) => {
fraction: 0,
value: 2,
},
- listIssueDate: { t_ms: 0 },
+ listIssueDate: { t_s: 0 },
},
];
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 392cecf0b..e4c6f2a6a 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -26,16 +26,12 @@ import {
codecForWithdrawResponse,
durationFromSpec,
ExchangeListItem,
- getDurationRemaining,
- getTimestampNow,
Logger,
NotificationType,
parseWithdrawUri,
TalerErrorCode,
TalerErrorDetails,
- Timestamp,
- timestampCmp,
- timestampSubtractDuraction,
+ AbsoluteTime,
WithdrawResponse,
URL,
WithdrawUriInfoResponse,
@@ -44,6 +40,8 @@ import {
LibtoolVersion,
UnblindedSignature,
ExchangeWithdrawRequest,
+ Duration,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import {
CoinRecord,
@@ -147,7 +145,7 @@ export interface ExchangeWithdrawDetails {
/**
* The earliest deposit expiration of the selected coins.
*/
- earliestDepositExpiration: Timestamp;
+ earliestDepositExpiration: TalerProtocolTimestamp;
/**
* Number of currently offered denominations.
@@ -184,18 +182,20 @@ export interface ExchangeWithdrawDetails {
* revocation and offered state.
*/
export function isWithdrawableDenom(d: DenominationRecord): boolean {
- const now = getTimestampNow();
- const started = timestampCmp(now, d.stampStart) >= 0;
- let lastPossibleWithdraw: Timestamp;
+ const now = AbsoluteTime.now();
+ const start = AbsoluteTime.fromTimestamp(d.stampStart);
+ const withdrawExpire = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw);
+ const started = AbsoluteTime.cmp(now, start) >= 0;
+ let lastPossibleWithdraw: AbsoluteTime;
if (walletCoreDebugFlags.denomselAllowLate) {
- lastPossibleWithdraw = d.stampExpireWithdraw;
+ lastPossibleWithdraw = start;
} else {
- lastPossibleWithdraw = timestampSubtractDuraction(
- d.stampExpireWithdraw,
+ lastPossibleWithdraw = AbsoluteTime.subtractDuraction(
+ withdrawExpire,
durationFromSpec({ minutes: 5 }),
);
}
- const remaining = getDurationRemaining(lastPossibleWithdraw, now);
+ const remaining = Duration.getRemaining(lastPossibleWithdraw, now);
const stillOkay = remaining.d_ms !== 0;
return started && stillOkay && !d.isRevoked && d.isOffered;
}
@@ -274,7 +274,7 @@ export function selectWithdrawalDenominations(
/**
* Get information about a withdrawal from
* a taler://withdraw URI by asking the bank.
- *
+ *
* FIXME: Move into bank client.
*/
export async function getBankWithdrawalInfo(
@@ -947,7 +947,7 @@ async function processWithdrawGroupImpl(
logger.trace(`now withdrawn ${numFinished} of ${numTotalCoins} coins`);
if (wg.timestampFinish === undefined && numFinished === numTotalCoins) {
finishedForFirstTime = true;
- wg.timestampFinish = getTimestampNow();
+ wg.timestampFinish = TalerProtocolTimestamp.now();
wg.operationStatus = OperationStatus.Finished;
delete wg.lastError;
wg.retryInfo = initRetryInfo();
@@ -999,7 +999,12 @@ export async function getExchangeWithdrawalInfo(
for (let i = 1; i < selectedDenoms.selectedDenoms.length; i++) {
const expireDeposit =
selectedDenoms.selectedDenoms[i].denom.stampExpireDeposit;
- if (expireDeposit.t_ms < earliestDepositExpiration.t_ms) {
+ if (
+ AbsoluteTime.cmp(
+ AbsoluteTime.fromTimestamp(expireDeposit),
+ AbsoluteTime.fromTimestamp(earliestDepositExpiration),
+ ) < 0
+ ) {
earliestDepositExpiration = expireDeposit;
}
}
diff --git a/packages/taler-wallet-core/src/pending-types.ts b/packages/taler-wallet-core/src/pending-types.ts
index 911d0d8bd..4b1434bb5 100644
--- a/packages/taler-wallet-core/src/pending-types.ts
+++ b/packages/taler-wallet-core/src/pending-types.ts
@@ -27,7 +27,8 @@
import {
TalerErrorDetails,
BalancesResponse,
- Timestamp,
+ AbsoluteTime,
+ TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { ReserveRecordStatus } from "./db.js";
import { RetryInfo } from "./util/retries.js";
@@ -112,7 +113,7 @@ export interface PendingReserveTask {
type: PendingTaskType.Reserve;
retryInfo: RetryInfo | undefined;
stage: ReserveRecordStatus;
- timestampCreated: Timestamp;
+ timestampCreated: TalerProtocolTimestamp;
reserveType: ReserveType;
reservePub: string;
bankWithdrawConfirmUrl?: string;
@@ -135,7 +136,7 @@ export interface PendingRefreshTask {
export interface PendingProposalDownloadTask {
type: PendingTaskType.ProposalDownload;
merchantBaseUrl: string;
- proposalTimestamp: Timestamp;
+ proposalTimestamp: TalerProtocolTimestamp;
proposalId: string;
orderId: string;
lastError?: TalerErrorDetails;
@@ -149,7 +150,7 @@ export interface PendingProposalDownloadTask {
export interface PendingProposalChoiceOperation {
type: PendingTaskType.ProposalChoice;
merchantBaseUrl: string;
- proposalTimestamp: Timestamp;
+ proposalTimestamp: AbsoluteTime;
proposalId: string;
}
@@ -231,7 +232,7 @@ export interface PendingTaskInfoCommon {
/**
* Timestamp when the pending operation should be executed next.
*/
- timestampDue: Timestamp;
+ timestampDue: AbsoluteTime;
/**
* Retry info. Currently used to stop the wallet after any operation
diff --git a/packages/taler-wallet-core/src/util/http.ts b/packages/taler-wallet-core/src/util/http.ts
index 43fe29bba..79afd5707 100644
--- a/packages/taler-wallet-core/src/util/http.ts
+++ b/packages/taler-wallet-core/src/util/http.ts
@@ -28,10 +28,7 @@ import { OperationFailedError, makeErrorDetails } from "../errors.js";
import {
Logger,
Duration,
- Timestamp,
- getTimestampNow,
- timestampAddDuration,
- timestampMax,
+ AbsoluteTime,
TalerErrorDetails,
Codec,
j2s,
@@ -314,24 +311,24 @@ export async function readSuccessResponseTextOrThrow<T>(
/**
* Get the timestamp at which the response's content is considered expired.
*/
-export function getExpiryTimestamp(
+export function getExpiry(
httpResponse: HttpResponse,
opt: { minDuration?: Duration },
-): Timestamp {
+): AbsoluteTime {
const expiryDateMs = new Date(
httpResponse.headers.get("expiry") ?? "",
).getTime();
- let t: Timestamp;
+ let t: AbsoluteTime;
if (Number.isNaN(expiryDateMs)) {
- t = getTimestampNow();
+ t = AbsoluteTime.now();
} else {
t = {
t_ms: expiryDateMs,
};
}
if (opt.minDuration) {
- const t2 = timestampAddDuration(getTimestampNow(), opt.minDuration);
- return timestampMax(t, t2);
+ const t2 = AbsoluteTime.addDuration(AbsoluteTime.now(), opt.minDuration);
+ return AbsoluteTime.max(t, t2);
}
return t;
}
diff --git a/packages/taler-wallet-core/src/util/retries.ts b/packages/taler-wallet-core/src/util/retries.ts
index 8dec22bed..4b78d38ef 100644
--- a/packages/taler-wallet-core/src/util/retries.ts
+++ b/packages/taler-wallet-core/src/util/retries.ts
@@ -21,11 +21,11 @@
/**
* Imports.
*/
-import { Timestamp, Duration, getTimestampNow } from "@gnu-taler/taler-util";
+import { AbsoluteTime, Duration } from "@gnu-taler/taler-util";
export interface RetryInfo {
- firstTry: Timestamp;
- nextRetry: Timestamp;
+ firstTry: AbsoluteTime;
+ nextRetry: AbsoluteTime;
retryCounter: number;
}
@@ -45,7 +45,7 @@ export function updateRetryInfoTimeout(
r: RetryInfo,
p: RetryPolicy = defaultRetryPolicy,
): void {
- const now = getTimestampNow();
+ const now = AbsoluteTime.now();
if (now.t_ms === "never") {
throw Error("assertion failed");
}
@@ -54,10 +54,14 @@ export function updateRetryInfoTimeout(
return;
}
- const nextIncrement = p.backoffDelta.d_ms * Math.pow(p.backoffBase, r.retryCounter)
+ const nextIncrement =
+ p.backoffDelta.d_ms * Math.pow(p.backoffBase, r.retryCounter);
const t =
- now.t_ms + (p.maxTimeout.d_ms === "forever" ? nextIncrement : Math.min(p.maxTimeout.d_ms, nextIncrement));
+ now.t_ms +
+ (p.maxTimeout.d_ms === "forever"
+ ? nextIncrement
+ : Math.min(p.maxTimeout.d_ms, nextIncrement));
r.nextRetry = { t_ms: t };
}
@@ -73,13 +77,13 @@ export function getRetryDuration(
return { d_ms: "forever" };
}
const t = p.backoffDelta.d_ms * Math.pow(p.backoffBase, r.retryCounter);
- return { d_ms: p.maxTimeout.d_ms === "forever" ? t : Math.min(p.maxTimeout.d_ms, t) };
+ return {
+ d_ms: p.maxTimeout.d_ms === "forever" ? t : Math.min(p.maxTimeout.d_ms, t),
+ };
}
-export function initRetryInfo(
- p: RetryPolicy = defaultRetryPolicy,
-): RetryInfo {
- const now = getTimestampNow();
+export function initRetryInfo(p: RetryPolicy = defaultRetryPolicy): RetryInfo {
+ const now = AbsoluteTime.now();
const info = {
firstTry: now,
nextRetry: now,
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 329417562..bbff465a8 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -64,9 +64,7 @@ import {
durationMin,
ExchangeListItem,
ExchangesListRespose,
- getDurationRemaining,
GetExchangeTosResult,
- isTimestampExpired,
j2s,
KnownBankAccounts,
Logger,
@@ -76,11 +74,12 @@ import {
PaytoUri,
RefreshReason,
TalerErrorCode,
- Timestamp,
- timestampMin,
+ AbsoluteTime,
URL,
WalletNotification,
+ Duration,
} from "@gnu-taler/taler-util";
+import { timeStamp } from "console";
import {
DenomInfo,
ExchangeOperations,
@@ -292,7 +291,7 @@ export async function runPending(
): Promise<void> {
const pendingOpsResponse = await getPendingOperations(ws);
for (const p of pendingOpsResponse.pendingOperations) {
- if (!forceNow && !isTimestampExpired(p.timestampDue)) {
+ if (!forceNow && !AbsoluteTime.isExpired(p.timestampDue)) {
continue;
}
try {
@@ -340,10 +339,10 @@ async function runTaskLoop(
logger.trace(`pending operations: ${j2s(pending)}`);
let numGivingLiveness = 0;
let numDue = 0;
- let minDue: Timestamp = { t_ms: "never" };
+ let minDue: AbsoluteTime = AbsoluteTime.never();
for (const p of pending.pendingOperations) {
- minDue = timestampMin(minDue, p.timestampDue);
- if (isTimestampExpired(p.timestampDue)) {
+ minDue = AbsoluteTime.min(minDue, p.timestampDue);
+ if (AbsoluteTime.isExpired(p.timestampDue)) {
numDue++;
}
if (p.givesLifeness) {
@@ -377,7 +376,7 @@ async function runTaskLoop(
durationFromSpec({
seconds: 5,
}),
- getDurationRemaining(minDue),
+ Duration.getRemaining(minDue),
);
logger.trace(`waiting for at most ${dt.d_ms} ms`);
const timeout = ws.timerGroup.resolveAfter(dt);
@@ -394,7 +393,7 @@ async function runTaskLoop(
`running ${pending.pendingOperations.length} pending operations`,
);
for (const p of pending.pendingOperations) {
- if (!isTimestampExpired(p.timestampDue)) {
+ if (!AbsoluteTime.isExpired(p.timestampDue)) {
continue;
}
try {
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx
index 658a41aa8..ea29d4a78 100644
--- a/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx
@@ -22,7 +22,11 @@
import { PendingTransactionsView as TestedComponent } from "./PendingTransactions";
import { Fragment, h, VNode } from "preact";
import { createExample } from "../test-utils";
-import { Transaction, TransactionType } from "@gnu-taler/taler-util";
+import {
+ TalerProtocolTimestamp,
+ Transaction,
+ TransactionType,
+} from "@gnu-taler/taler-util";
export default {
title: "component/PendingTransactions",
@@ -34,9 +38,7 @@ export const OnePendingTransaction = createExample(TestedComponent, {
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
],
});
@@ -46,23 +48,17 @@ export const ThreePendingTransactions = createExample(TestedComponent, {
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
],
});
@@ -72,72 +68,52 @@ export const TenPendingTransactions = createExample(TestedComponent, {
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1)
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
{
amountEffective: "USD:10",
type: TransactionType.Withdrawal,
- timestamp: {
- t_ms: 1,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(1),
} as Transaction,
],
});
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
index eed31beb4..7923eb6ad 100644
--- a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
+++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
@@ -1,4 +1,9 @@
-import { Amounts, NotificationType, Transaction } from "@gnu-taler/taler-util";
+import {
+ AbsoluteTime,
+ Amounts,
+ NotificationType,
+ Transaction,
+} from "@gnu-taler/taler-util";
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, JSX } from "preact";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
@@ -70,7 +75,11 @@ export function PendingTransactionsView({
<b>
{amount.currency} {Amounts.stringifyValue(amount)}
</b>{" "}
- - <Time timestamp={t.timestamp} format="dd MMMM yyyy" />
+ -{" "}
+ <Time
+ timestamp={AbsoluteTime.fromTimestamp(t.timestamp)}
+ format="dd MMMM yyyy"
+ />
</Typography>
),
};
diff --git a/packages/taler-wallet-webextension/src/components/Time.tsx b/packages/taler-wallet-webextension/src/components/Time.tsx
index 452b08334..902187aa3 100644
--- a/packages/taler-wallet-webextension/src/components/Time.tsx
+++ b/packages/taler-wallet-webextension/src/components/Time.tsx
@@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Timestamp } from "@gnu-taler/taler-util";
+import { AbsoluteTime } from "@gnu-taler/taler-util";
import { formatISO, format } from "date-fns";
import { h, VNode } from "preact";
@@ -22,7 +22,7 @@ export function Time({
timestamp,
format: formatString,
}: {
- timestamp: Timestamp | undefined;
+ timestamp: AbsoluteTime | undefined;
format: string;
}): VNode {
return (
diff --git a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
index 12ed4139b..d7eae7bb6 100644
--- a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
+++ b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
@@ -18,7 +18,7 @@ import {
AmountJson,
Amounts,
AmountString,
- Timestamp,
+ AbsoluteTime,
Transaction,
TransactionType,
} from "@gnu-taler/taler-util";
@@ -46,7 +46,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective}
debitCreditIndicator={"credit"}
title={new URL(tx.exchangeBaseUrl).hostname}
- timestamp={tx.timestamp}
+ timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
iconPath={"W"}
pending={tx.pending}
/>
@@ -59,7 +59,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
debitCreditIndicator={"debit"}
title={tx.info.merchant.name}
subtitle={tx.info.summary}
- timestamp={tx.timestamp}
+ timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
iconPath={"P"}
pending={tx.pending}
/>
@@ -72,7 +72,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
debitCreditIndicator={"credit"}
subtitle={tx.info.summary}
title={tx.info.merchant.name}
- timestamp={tx.timestamp}
+ timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
iconPath={"R"}
pending={tx.pending}
/>
@@ -84,7 +84,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective}
debitCreditIndicator={"credit"}
title={new URL(tx.merchantBaseUrl).hostname}
- timestamp={tx.timestamp}
+ timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
iconPath={"T"}
pending={tx.pending}
/>
@@ -96,7 +96,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective}
debitCreditIndicator={"credit"}
title={new URL(tx.exchangeBaseUrl).hostname}
- timestamp={tx.timestamp}
+ timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
iconPath={"R"}
pending={tx.pending}
/>
@@ -108,7 +108,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective}
debitCreditIndicator={"debit"}
title={tx.targetPaytoUri}
- timestamp={tx.timestamp}
+ timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
iconPath={"D"}
pending={tx.pending}
/>
@@ -165,7 +165,7 @@ function TransactionLayout(props: TransactionLayoutProps): VNode {
interface TransactionLayoutProps {
debitCreditIndicator: "debit" | "credit" | "unknown";
amount: AmountString | "unknown";
- timestamp: Timestamp;
+ timestamp: AbsoluteTime;
title: string;
subtitle?: string;
id: string;
diff --git a/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
index 8da599513..e475a9610 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
@@ -19,6 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { AbsoluteTime, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
import { createExample } from "../test-utils";
import { View as TestedComponent } from "./Tip";
@@ -33,9 +34,7 @@ export const Accepted = createExample(TestedComponent, {
accepted: true,
merchantBaseUrl: "",
exchangeBaseUrl: "",
- expirationTimestamp: {
- t_ms: 0,
- },
+ expirationTimestamp: TalerProtocolTimestamp.fromSeconds(1),
tipAmountEffective: "USD:10",
tipAmountRaw: "USD:5",
walletTipId: "id",
@@ -47,9 +46,7 @@ export const NotYetAccepted = createExample(TestedComponent, {
accepted: false,
merchantBaseUrl: "http://merchant.url/",
exchangeBaseUrl: "http://exchange.url/",
- expirationTimestamp: {
- t_ms: 0,
- },
+ expirationTimestamp: TalerProtocolTimestamp.fromSeconds(1),
tipAmountEffective: "USD:10",
tipAmountRaw: "USD:5",
walletTipId: "id",
diff --git a/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx b/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx
index 738ece2f1..3deea032d 100644
--- a/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx
@@ -20,7 +20,7 @@ import {
CoinDumpJson,
ExchangeListItem,
NotificationType,
- Timestamp,
+ AbsoluteTime,
Translate,
} from "@gnu-taler/taler-util";
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
diff --git a/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx
index b2771bc2a..92536db85 100644
--- a/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx
@@ -23,6 +23,7 @@ import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
import { addDays } from "date-fns";
import { BackupView as TestedComponent } from "./BackupPage";
import { createExample } from "../test-utils";
+import { TalerProtocolTimestamp } from "@gnu-taler/taler-util";
export default {
title: "wallet/backup/list",
@@ -40,9 +41,8 @@ export const LotOfProviders = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
@@ -62,9 +62,8 @@ export const LotOfProviders = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
@@ -172,9 +171,8 @@ export const OneProvider = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
diff --git a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
index e1d34748b..8c12201b9 100644
--- a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
@@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Timestamp, Translate } from "@gnu-taler/taler-util";
+import { AbsoluteTime, Translate } from "@gnu-taler/taler-util";
import {
ProviderInfo,
ProviderPaymentPaid,
@@ -104,7 +104,13 @@ export function BackupView({
<BackupLayout
key={idx}
status={provider.paymentStatus}
- timestamp={provider.lastSuccessfulBackupTimestamp}
+ timestamp={
+ provider.lastSuccessfulBackupTimestamp
+ ? AbsoluteTime.fromTimestamp(
+ provider.lastSuccessfulBackupTimestamp,
+ )
+ : undefined
+ }
id={provider.syncProviderBaseUrl}
active={provider.active}
title={provider.name}
@@ -144,7 +150,7 @@ export function BackupView({
interface TransactionLayoutProps {
status: ProviderPaymentStatus;
- timestamp?: Timestamp;
+ timestamp?: AbsoluteTime;
title: string;
id: string;
active: boolean;
@@ -192,7 +198,7 @@ function BackupLayout(props: TransactionLayoutProps): VNode {
);
}
-function ExpirationText({ until }: { until: Timestamp }): VNode {
+function ExpirationText({ until }: { until: AbsoluteTime }): VNode {
const { i18n } = useTranslationContext();
return (
<Fragment>
@@ -207,13 +213,13 @@ function ExpirationText({ until }: { until: Timestamp }): VNode {
);
}
-function colorByTimeToExpire(d: Timestamp): string {
+function colorByTimeToExpire(d: AbsoluteTime): string {
if (d.t_ms === "never") return "rgb(28, 184, 65)";
const months = differenceInMonths(d.t_ms, new Date());
return months > 1 ? "rgb(28, 184, 65)" : "rgb(223, 117, 20)";
}
-function daysUntil(d: Timestamp): string {
+function daysUntil(d: AbsoluteTime): string {
if (d.t_ms === "never") return "";
const duration = intervalToDuration({
start: d.t_ms,
diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
index bd52995d9..8138e63dd 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
@@ -21,6 +21,7 @@
import {
PaymentStatus,
+ TalerProtocolTimestamp,
TransactionCommon,
TransactionDeposit,
TransactionPayment,
@@ -45,9 +46,9 @@ const commonTransaction = () =>
amountRaw: "USD:10",
amountEffective: "USD:9",
pending: false,
- timestamp: {
- t_ms: new Date().getTime() - count++ * 1000 * 60 * 60 * 7,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(
+ new Date().getTime() - count++ * 60 * 60 * 7,
+ ),
transactionId: "12",
} as TransactionCommon);
diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx b/packages/taler-wallet-webextension/src/wallet/History.tsx
index 02fc0a76c..5d00e2e01 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.tsx
@@ -126,7 +126,7 @@ export function HistoryView({
.filter((t) => t.amountRaw.split(":")[0] === selectedCurrency)
.reduce((rv, x) => {
const theDate =
- x.timestamp.t_ms === "never" ? 0 : normalizeToDay(x.timestamp.t_ms);
+ x.timestamp.t_s === "never" ? 0 : normalizeToDay(x.timestamp.t_s * 1000);
if (theDate) {
(rv[theDate] = rv[theDate] || []).push(x);
}
diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx
index a170620a3..c4c070fa8 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx
@@ -19,6 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { TalerProtocolTimestamp } from "@gnu-taler/taler-util";
import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
import { createExample } from "../test-utils";
import { ProviderView as TestedComponent } from "./ProviderDetailPage";
@@ -38,9 +39,8 @@ export const Active = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
@@ -63,12 +63,10 @@ export const ActiveErrorSync = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
- lastAttemptedBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925),
+ lastAttemptedBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925078),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
@@ -97,9 +95,8 @@ export const ActiveBackupProblemUnreadable = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
@@ -125,9 +122,8 @@ export const ActiveBackupProblemDevice = createExample(TestedComponent, {
active: true,
name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/",
- lastSuccessfulBackupTimestamp: {
- t_ms: 1625063925078,
- },
+ lastSuccessfulBackupTimestamp:
+ TalerProtocolTimestamp.fromSeconds(1625063925078),
paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
index 765f34a02..afd9612ee 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
@@ -15,6 +15,7 @@
*/
import * as utils from "@gnu-taler/taler-util";
+import { AbsoluteTime } from "@gnu-taler/taler-util";
import {
ProviderInfo,
ProviderPaymentStatus,
@@ -122,7 +123,9 @@ export function ProviderView({
</Fragment>
);
}
- const lb = info.lastSuccessfulBackupTimestamp;
+ const lb = info.lastSuccessfulBackupTimestamp
+ ? AbsoluteTime.fromTimestamp(info.lastSuccessfulBackupTimestamp)
+ : undefined;
const isPaid =
info.paymentStatus.type === ProviderPaymentType.Paid ||
info.paymentStatus.type === ProviderPaymentType.TermsChanged;
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
index 7b6ac1fdc..f02938420 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
@@ -21,6 +21,7 @@
import {
PaymentStatus,
+ TalerProtocolTimestamp,
TransactionCommon,
TransactionDeposit,
TransactionPayment,
@@ -53,9 +54,7 @@ const commonTransaction = {
amountRaw: "KUDOS:11",
amountEffective: "KUDOS:9.2",
pending: false,
- timestamp: {
- t_ms: new Date().getTime(),
- },
+ timestamp: TalerProtocolTimestamp.now(),
transactionId: "12",
} as TransactionCommon;
@@ -144,18 +143,14 @@ export const Withdraw = createExample(TestedComponent, {
export const WithdrawOneMinuteAgo = createExample(TestedComponent, {
transaction: {
...exampleData.withdraw,
- timestamp: {
- t_ms: new Date().getTime() - 60 * 1000,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(new Date().getTime() - 60),
},
});
export const WithdrawOneMinuteAgoAndPending = createExample(TestedComponent, {
transaction: {
...exampleData.withdraw,
- timestamp: {
- t_ms: new Date().getTime() - 60 * 1000,
- },
+ timestamp: TalerProtocolTimestamp.fromSeconds(new Date().getTime() - 60),
pending: true,
},
});
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index b367416fa..0e58aaf61 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -15,6 +15,7 @@
*/
import {
+ AbsoluteTime,
AmountLike,
Amounts,
NotificationType,
@@ -137,9 +138,9 @@ export function TransactionView({
}): VNode {
const showRetry =
transaction.error !== undefined ||
- transaction.timestamp.t_ms === "never" ||
+ transaction.timestamp.t_s === "never" ||
(transaction.pending &&
- differenceInSeconds(new Date(), transaction.timestamp.t_ms) > 10);
+ differenceInSeconds(new Date(), transaction.timestamp.t_s * 1000) > 10);
return (
<Fragment>
@@ -218,7 +219,7 @@ export function TransactionView({
<h2>
<i18n.Translate>Withdrawal</i18n.Translate>
</h2>
- <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
+ <Time timestamp={AbsoluteTime.fromTimestamp(transaction.timestamp)} format="dd MMMM yyyy, HH:mm" />
{transaction.pending ? (
transaction.withdrawalDetails.type ===
WithdrawalType.ManualTransfer ? (
@@ -342,7 +343,7 @@ export function TransactionView({
<h2>
<i18n.Translate>Payment</i18n.Translate>
</h2>
- <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
+ <Time timestamp={AbsoluteTime.fromTimestamp(transaction.timestamp)} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
@@ -425,7 +426,7 @@ export function TransactionView({
<h2>
<i18n.Translate>Deposit</i18n.Translate>
</h2>
- <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
+ <Time timestamp={AbsoluteTime.fromTimestamp(transaction.timestamp)} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
@@ -459,7 +460,7 @@ export function TransactionView({
<h2>
<i18n.Translate>Refresh</i18n.Translate>
</h2>
- <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
+ <Time timestamp={AbsoluteTime.fromTimestamp(transaction.timestamp)} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
@@ -493,7 +494,7 @@ export function TransactionView({
<h2>
<i18n.Translate>Tip</i18n.Translate>
</h2>
- <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
+ <Time timestamp={AbsoluteTime.fromTimestamp(transaction.timestamp)} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
@@ -527,7 +528,10 @@ export function TransactionView({
<h2>
<i18n.Translate>Refund</i18n.Translate>
</h2>
- <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
+ <Time
+ timestamp={AbsoluteTime.fromTimestamp(transaction.timestamp)}
+ format="dd MMMM yyyy, HH:mm"
+ />
<br />
<Part
big