gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet transaction detail


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet transaction detail
Date: Thu, 03 Jun 2021 06:07:43 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new aa0edbdd wallet transaction detail
aa0edbdd is described below

commit aa0edbdd6875113976ec2b27efe2d82625ed2fde
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Thu Jun 3 01:07:29 2021 -0300

    wallet transaction detail
---
 packages/taler-util/src/transactionsTypes.ts       |  10 +-
 packages/taler-wallet-webextension/package.json    |   3 +-
 .../taler-wallet-webextension/src/Application.tsx  |   2 +-
 .../src/pages/popup.stories.tsx                    | 191 +++++++++++++++++
 .../taler-wallet-webextension/src/pages/popup.tsx  | 231 ++++++++++++++++++++-
 packages/taler-wallet-webextension/src/wxApi.ts    |  10 +
 .../static/style/popup.css                         |  22 ++
 pnpm-lock.yaml                                     |   7 +
 8 files changed, 467 insertions(+), 9 deletions(-)

diff --git a/packages/taler-util/src/transactionsTypes.ts 
b/packages/taler-util/src/transactionsTypes.ts
index b3cc274a..e29a5549 100644
--- a/packages/taler-util/src/transactionsTypes.ts
+++ b/packages/taler-util/src/transactionsTypes.ts
@@ -145,7 +145,7 @@ interface WithdrawalDetailsForTalerBankIntegrationApi {
 
 // This should only be used for actual withdrawals
 // and not for tips that have their own transactions type.
-interface TransactionWithdrawal extends TransactionCommon {
+export interface TransactionWithdrawal extends TransactionCommon {
   type: TransactionType.Withdrawal;
 
   /**
@@ -266,7 +266,7 @@ export interface OrderShortInfo {
   fulfillmentMessage_i18n?: InternationalizedString;
 }
 
-interface TransactionRefund extends TransactionCommon {
+export interface TransactionRefund extends TransactionCommon {
   type: TransactionType.Refund;
 
   // ID for the transaction that is refunded
@@ -282,7 +282,7 @@ interface TransactionRefund extends TransactionCommon {
   amountEffective: AmountString;
 }
 
-interface TransactionTip extends TransactionCommon {
+export interface TransactionTip extends TransactionCommon {
   type: TransactionType.Tip;
 
   // Raw amount of the tip, without extra fees that apply
@@ -297,7 +297,7 @@ interface TransactionTip extends TransactionCommon {
 // A transaction shown for refreshes that are not associated to other 
transactions
 // such as a refresh necessary before coin expiration.
 // It should only be returned by the API if the effective amount is different 
from zero.
-interface TransactionRefresh extends TransactionCommon {
+export interface TransactionRefresh extends TransactionCommon {
   type: TransactionType.Refresh;
 
   // Exchange that the coins are refreshed with
@@ -314,7 +314,7 @@ interface TransactionRefresh extends TransactionCommon {
  * Deposit transaction, which effectively sends
  * money from this wallet somewhere else.
  */
-interface TransactionDeposit extends TransactionCommon {
+export interface TransactionDeposit extends TransactionCommon {
   type: TransactionType.Deposit;
 
   depositGroupId: string;
diff --git a/packages/taler-wallet-webextension/package.json 
b/packages/taler-wallet-webextension/package.json
index 5a6775b2..60a2ea5d 100644
--- a/packages/taler-wallet-webextension/package.json
+++ b/packages/taler-wallet-webextension/package.json
@@ -12,12 +12,13 @@
     "test": "jest ./tests",
     "compile": "tsc && rollup -c",
     "build-storybook": "build-storybook",
-    "storybook": "start-storybook -p 6006",
+    "storybook": "start-storybook -s static -p 6006",
     "watch": "tsc --watch & rollup -w -c"
   },
   "dependencies": {
     "@gnu-taler/taler-util": "workspace:*",
     "@gnu-taler/taler-wallet-core": "workspace:*",
+    "date-fns": "^2.22.1",
     "preact": "^10.5.13",
     "preact-router": "^3.2.1",
     "tslib": "^2.1.0"
diff --git a/packages/taler-wallet-webextension/src/Application.tsx 
b/packages/taler-wallet-webextension/src/Application.tsx
index 096f6a09..6e10786d 100644
--- a/packages/taler-wallet-webextension/src/Application.tsx
+++ b/packages/taler-wallet-webextension/src/Application.tsx
@@ -19,7 +19,7 @@ export enum Pages {
   return_coins = '/return-coins',
   tips = '/tips',
   withdraw = '/withdraw',
-  popup = '/popup/:rest',
+  popup = '/popup/:rest*',
 }
 
 export function Application() {
diff --git a/packages/taler-wallet-webextension/src/pages/popup.stories.tsx 
b/packages/taler-wallet-webextension/src/pages/popup.stories.tsx
new file mode 100644
index 00000000..e9202fbe
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/pages/popup.stories.tsx
@@ -0,0 +1,191 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { PaymentStatus, TransactionPayment, TransactionType, 
TransactionWithdrawal, TransactionDeposit, TransactionRefresh, TransactionTip, 
TransactionRefund, WithdrawalType, TransactionCommon } from 
'@gnu-taler/taler-util';
+import { Fragment, h } from 'preact';
+import { WalletTransactionView as Component } from './popup';
+
+export default {
+  title: 'popup/transaction details',
+  component: Component,
+  decorators: [
+    (Story: any) => <div>
+      <link key="1" rel="stylesheet" type="text/css" href="/style/pure.css" />
+      <link key="2" rel="stylesheet" type="text/css" href="/style/popup.css" />
+      <link key="3" rel="stylesheet" type="text/css" href="/style/wallet.css" 
/>
+      <div style={{ margin: "1em", width: 400 }}>
+        <Story />
+      </div>
+    </div>
+  ],
+};
+
+const commonTransaction = {
+  amountRaw: 'USD:10',
+  amountEffective: 'USD:9',
+  pending: false,
+  timestamp: {
+    t_ms: new Date().getTime()
+  },
+  transactionId: '12',
+} as TransactionCommon
+
+const exampleData = {
+  withdraw: {
+    ...commonTransaction,
+    type: TransactionType.Withdrawal,
+    exchangeBaseUrl: 'http://exchange.taler',
+    withdrawalDetails: {
+      confirmed: false,
+      exchangePaytoUris: ['payto://x-taler-bank/bank/account'],
+      type: WithdrawalType.ManualTransfer,
+    }
+  } as TransactionWithdrawal,
+  payment: {
+    ...commonTransaction,
+    type: TransactionType.Payment,
+    info: {
+      contractTermsHash: 'ASDZXCASD',
+      merchant: {
+        name: 'the merchant',
+      },
+      orderId: '#12345',
+      products: [],
+      summary: 'the summary',
+      fulfillmentMessage: '',
+    },
+    proposalId: '#proposalId',
+    status: PaymentStatus.Accepted,
+  } as TransactionPayment,
+  deposit: {
+    ...commonTransaction,
+    type: TransactionType.Deposit,
+    depositGroupId: '#groupId',
+    targetPaytoUri: 'payto://x-taler-bank/bank/account',
+  } as TransactionDeposit,
+  refresh: {
+    ...commonTransaction,
+    type: TransactionType.Refresh,
+    exchangeBaseUrl: 'http://exchange.taler',
+  } as TransactionRefresh,
+  tip: {
+    ...commonTransaction,
+    type: TransactionType.Tip,
+    merchantBaseUrl: 'http://merchant.taler',
+  } as TransactionTip,
+  refund: {
+    ...commonTransaction,
+    type: TransactionType.Refund,
+    refundedTransactionId: '#refundId',
+    info: {
+      contractTermsHash: 'ASDZXCASD',
+      merchant: {
+        name: 'the merchant',
+      },
+      orderId: '#12345',
+      products: [],
+      summary: 'the summary',
+      fulfillmentMessage: '',
+    },
+  } as TransactionRefund,
+}
+
+function dynamic<T>(props: any) {
+  const r = (args: any) => <Component {...args} />
+  r.args = props
+  return r
+}
+
+export const NotYetLoaded = dynamic({});
+
+export const Withdraw = dynamic({
+  transaction: exampleData.withdraw
+});
+
+export const WithdrawPending = dynamic({
+  transaction: { ...exampleData.withdraw, pending: true },
+});
+
+
+export const Payment = dynamic({
+  transaction: exampleData.payment
+});
+
+export const PaymentPending = dynamic({
+  transaction: { ...exampleData.payment, pending: true },
+});
+
+export const PaymentWithProducts = dynamic({
+  transaction: {
+    ...exampleData.payment,
+    info: {
+      ...exampleData.payment.info,
+      products: [{
+        description: 't-shirt',
+      }, {
+        description: 'beer',
+      }]
+    }
+  } as TransactionPayment,
+});
+
+
+export const Deposit = dynamic({
+  transaction: exampleData.deposit
+});
+
+export const DepositPending = dynamic({
+  transaction: { ...exampleData.deposit, pending: true }
+});
+
+export const Refresh = dynamic({
+  transaction: exampleData.refresh
+});
+
+export const Tip = dynamic({
+  transaction: exampleData.tip
+});
+
+export const TipPending = dynamic({
+  transaction: { ...exampleData.tip, pending: true }
+});
+
+export const Refund = dynamic({
+  transaction: exampleData.refund
+});
+
+export const RefundPending = dynamic({
+  transaction: { ...exampleData.refund , pending: true }
+});
+
+export const RefundWithProducts = dynamic({
+  transaction: {
+    ...exampleData.refund,
+    info: {
+      ...exampleData.refund.info,
+      products: [{
+        description: 't-shirt',
+      }, {
+        description: 'beer',
+      }]
+    }
+  } as TransactionRefund,
+});
diff --git a/packages/taler-wallet-webextension/src/pages/popup.tsx 
b/packages/taler-wallet-webextension/src/pages/popup.tsx
index c361f4d9..4693c94c 100644
--- a/packages/taler-wallet-webextension/src/pages/popup.tsx
+++ b/packages/taler-wallet-webextension/src/pages/popup.tsx
@@ -38,7 +38,8 @@ import {
   Timestamp,
   amountFractionalBase,
 } from "@gnu-taler/taler-util";
-import { Component, ComponentChildren, JSX } from "preact";
+import { format } from "date-fns";
+import { Component, ComponentChildren, Fragment, JSX } from "preact";
 import { route, Route, Router } from 'preact-router';
 import { Match } from 'preact-router/match';
 import { useEffect, useState } from "preact/hooks";
@@ -268,6 +269,7 @@ interface TransactionLayoutProps {
   amount: AmountString | "unknown";
   timestamp: Timestamp;
   title: string;
+  id: string;
   subtitle: string;
   iconPath: string;
   pending: boolean;
@@ -297,7 +299,7 @@ function TransactionLayout(props: TransactionLayoutProps): 
JSX.Element {
       >
         <div style={{ fontSize: "small", color: "gray" }}>{dateStr}</div>
         <div style={{ fontVariant: "small-caps", fontSize: "x-large" }}>
-          <span>{props.title}</span>
+          <a href={Pages.transaction.replace(':tid', 
props.id)}><span>{props.title}</span></a>
           {props.pending ? (
             <span style={{ color: "darkblue" }}> (Pending)</span>
           ) : null}
@@ -320,6 +322,7 @@ function TransactionItem(props: { tx: Transaction }): 
JSX.Element {
     case TransactionType.Withdrawal:
       return (
         <TransactionLayout
+          id={tx.transactionId}
           amount={tx.amountEffective}
           debitCreditIndicator={"credit"}
           title="Withdrawal"
@@ -332,6 +335,7 @@ function TransactionItem(props: { tx: Transaction }): 
JSX.Element {
     case TransactionType.Payment:
       return (
         <TransactionLayout
+          id={tx.transactionId}
           amount={tx.amountEffective}
           debitCreditIndicator={"debit"}
           title="Payment"
@@ -344,6 +348,7 @@ function TransactionItem(props: { tx: Transaction }): 
JSX.Element {
     case TransactionType.Refund:
       return (
         <TransactionLayout
+          id={tx.transactionId}
           amount={tx.amountEffective}
           debitCreditIndicator={"credit"}
           title="Refund"
@@ -356,6 +361,7 @@ function TransactionItem(props: { tx: Transaction }): 
JSX.Element {
     case TransactionType.Tip:
       return (
         <TransactionLayout
+          id={tx.transactionId}
           amount={tx.amountEffective}
           debitCreditIndicator={"credit"}
           title="Tip"
@@ -368,6 +374,7 @@ function TransactionItem(props: { tx: Transaction }): 
JSX.Element {
     case TransactionType.Refresh:
       return (
         <TransactionLayout
+          id={tx.transactionId}
           amount={tx.amountEffective}
           debitCreditIndicator={"credit"}
           title="Refresh"
@@ -380,6 +387,7 @@ function TransactionItem(props: { tx: Transaction }): 
JSX.Element {
     case TransactionType.Deposit:
       return (
         <TransactionLayout
+          id={tx.transactionId}
           amount={tx.amountEffective}
           debitCreditIndicator={"debit"}
           title="Refresh"
@@ -420,6 +428,223 @@ function WalletHistory(props: any): JSX.Element {
   );
 }
 
+interface WalletTransactionProps {
+  transaction?: Transaction,
+  onDelete: () => void,
+  onBack: () => void,
+}
+
+export function WalletTransactionView({ transaction, onDelete, onBack }: 
WalletTransactionProps) {
+  if (!transaction) {
+    return <div>Loading ...</div>;
+  }
+
+  function Footer() {
+    return <footer style={{ marginTop: 'auto', display: 'flex' }}>
+      <button onClick={onBack}>back</button>
+      <div style={{ width: '100%', flexDirection: 'row', justifyContent: 
'flex-end', display: 'flex' }}>
+        <button onClick={onDelete}>remove</button>
+
+      </div>
+
+    </footer>
+  }
+
+  function Pending() {
+    if (!transaction?.pending) return null
+    return <span style={{fontWeight:'normal', fontSize:16, color: 
'gray'}}>(pending...)</span>
+  }
+
+  function CommonFields() {
+    if (!transaction) return null;
+    return <Fragment>
+      <tr>
+        <td>Amount deduce</td>
+        <td>{transaction.amountRaw}</td>
+      </tr>
+      <tr>
+        <td>Amount received</td>
+        <td>{transaction.amountEffective}</td>
+      </tr>
+      <tr>
+        <td>Exchange fee</td>
+        <td>{Amounts.stringify(
+          Amounts.sub(
+            Amounts.parseOrThrow(transaction.amountRaw),
+            Amounts.parseOrThrow(transaction.amountEffective),
+          ).amount
+        )}</td>
+      </tr>
+      <tr>
+        <td>When</td>
+        <td>{transaction.timestamp.t_ms === "never" ? "never" : 
format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}</td>
+      </tr>
+    </Fragment>
+  }
+
+  if (transaction.type === TransactionType.Withdrawal) {
+    return (
+      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, 
minHeight: '20rem' }} >
+        <section>
+          <h1>Withdrawal <Pending /></h1>
+          <p>
+            From <b>{transaction.exchangeBaseUrl}</b>
+          </p>
+          <table class={transaction.pending ? "detailsTable pending" : 
"detailsTable"}>
+            <CommonFields />
+          </table>
+        </section>
+        <Footer />
+      </div>
+    );
+  }
+
+  if (transaction.type === TransactionType.Payment) {
+    return (
+      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, 
minHeight: '20rem' }} >
+        <section>
+          <h1>Payment ({transaction.proposalId}) <Pending /></h1>
+          <p>
+            To <b>{transaction.info.merchant.name}</b>
+          </p>
+          <table class={transaction.pending ? "detailsTable pending" : 
"detailsTable"}>
+            <tr>
+              <td>Order id</td>
+              <td>{transaction.info.orderId}</td>
+            </tr>
+            <tr>
+              <td>Summary</td>
+              <td>{transaction.info.summary}</td>
+            </tr>
+            {transaction.info.products && transaction.info.products.length > 0 
&&
+              <tr>
+                <td>Products</td>
+                <td><ol style={{margin:0, textAlign:'left'}}>
+                  {transaction.info.products.map(p =>
+                    <li>{p.description}</li>
+                  )}</ol></td>
+              </tr>
+            }
+            <CommonFields />
+          </table>
+        </section>
+        <Footer />
+      </div>
+    );
+  }
+
+  if (transaction.type === TransactionType.Deposit) {
+    return (
+      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, 
minHeight: '20rem' }} >
+        <section>
+          <h1>Deposit ({transaction.depositGroupId}) <Pending /></h1>
+          <p>
+            To <b>{transaction.targetPaytoUri}</b>
+          </p>
+          <table class={transaction.pending ? "detailsTable pending" : 
"detailsTable"}>
+            <CommonFields />
+          </table>
+        </section>
+        <Footer />
+      </div>
+    );
+  }
+
+  if (transaction.type === TransactionType.Refresh) {
+    return (
+      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, 
minHeight: '20rem' }} >
+        <section>
+          <h1>Refresh <Pending /></h1>
+          <p>
+            From <b>{transaction.exchangeBaseUrl}</b>
+          </p>
+          <table class={transaction.pending ? "detailsTable pending" : 
"detailsTable"}>
+            <CommonFields />
+          </table>
+        </section>
+        <Footer />
+      </div>
+    );
+  }
+
+  if (transaction.type === TransactionType.Tip) {
+    return (
+      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, 
minHeight: '20rem' }} >
+        <section>
+          <h1>Tip <Pending /></h1>
+          <p>
+            From <b>{transaction.merchantBaseUrl}</b>
+          </p>
+          <table class={transaction.pending ? "detailsTable pending" : 
"detailsTable"}>
+            <CommonFields />
+          </table>
+        </section>
+        <Footer />
+      </div>
+    );
+  }
+
+  if (transaction.type === TransactionType.Refund) {
+    return (
+      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, 
minHeight: '20rem' }} >
+        <section>
+          <h1>Refund ({transaction.refundedTransactionId}) <Pending /></h1>
+          <p>
+            From <b>{transaction.info.merchant.name}</b>
+          </p>
+          <table class={transaction.pending ? "detailsTable pending" : 
"detailsTable"}>
+            <tr>
+              <td>Order id</td>
+              <td>{transaction.info.orderId}</td>
+            </tr>
+            <tr>
+              <td>Summary</td>
+              <td>{transaction.info.summary}</td>
+            </tr>
+            {transaction.info.products && transaction.info.products.length > 0 
&&
+              <tr>
+                <td>Products</td>
+                <td><ol>
+                  {transaction.info.products.map(p =>
+                    <li>{p.description}</li>
+                  )}</ol></td>
+              </tr>
+            }
+            <CommonFields />
+          </table>
+        </section>
+        <Footer />
+      </div>
+    );
+  }
+
+
+  return <div></div>
+}
+
+function WalletTransaction({ tid }: { tid: string }): JSX.Element {
+  const [transaction, setTransaction] = useState<
+    Transaction | undefined
+  >(undefined);
+
+  useEffect(() => {
+    const fetchData = async (): Promise<void> => {
+      const res = await wxApi.getTransactions();
+      const ts = res.transactions.filter(t => t.transactionId === tid)
+      if (ts.length === 1) {
+        setTransaction(ts[0]);
+      }
+    };
+    fetchData();
+  }, []);
+
+  return <WalletTransactionView
+    transaction={transaction}
+    onDelete={() => wxApi.deleteTransaction(tid)}
+    onBack={() => { history.go(-1) }}
+  />
+}
+
 class WalletSettings extends Component<any, any> {
   render(): JSX.Element {
     return (
@@ -597,6 +822,7 @@ export function WalletPopup(): JSX.Element {
           <Route path={Pages.settings} component={WalletSettings} />
           <Route path={Pages.debug} component={WalletDebug} />
           <Route path={Pages.history} component={WalletHistory} />
+          <Route path={Pages.transaction} component={WalletTransaction} />
         </Router>
       </div>
     </div>
@@ -605,6 +831,7 @@ export function WalletPopup(): JSX.Element {
 
 enum Pages {
   balance = '/popup/balance',
+  transaction = '/popup/transaction/:tid',
   settings = '/popup/settings',
   debug = '/popup/debug',
   history = '/popup/history',
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index cbebfb21..3340f27c 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -35,6 +35,7 @@ import {
   PrepareTipRequest,
   PrepareTipResult,
   AcceptTipRequest,
+  DeleteTransactionRequest,
 } from "@gnu-taler/taler-util";
 import { OperationFailedError } from "@gnu-taler/taler-wallet-core";
 
@@ -130,6 +131,15 @@ export function getTransactions(): 
Promise<TransactionsResponse> {
   return callBackend("getTransactions", {});
 }
 
+/**
+ * Get balances for all currencies/exchanges.
+ */
+export function deleteTransaction(transactionId: string): Promise<void> {
+  return callBackend("deleteTransaction", {
+    transactionId
+  } as DeleteTransactionRequest);
+}
+
 /**
  * Download a refund and accept it.
  */
diff --git a/packages/taler-wallet-webextension/static/style/popup.css 
b/packages/taler-wallet-webextension/static/style/popup.css
index c0201e58..a234f2a2 100644
--- a/packages/taler-wallet-webextension/static/style/popup.css
+++ b/packages/taler-wallet-webextension/static/style/popup.css
@@ -238,3 +238,25 @@ button.accept:disabled {
   font-weight: bold;
   background: #00fa9a;
 }
+
+table.detailsTable td {
+  text-align: right;
+  border: 0px;
+  border-bottom: 1px;
+}
+
+table.detailsTable td {
+  border-bottom: 1px solid black;
+}
+
+table.detailsTable tr:last-child td {
+  border-bottom: 0px;
+}
+
+table.detailsTable {
+  border: 0px;
+}
+
+table.detailsTable.pending {
+  color: gray;
+}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ea20e183..1cf013b8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -224,6 +224,7 @@ importers:
       '@types/node': ^14.14.22
       ava: 3.15.0
       babel-plugin-transform-react-jsx: ^6.24.1
+      date-fns: ^2.22.1
       enzyme: ^3.11.0
       enzyme-adapter-preact-pure: ^3.1.0
       history: 4.10.1
@@ -243,6 +244,7 @@ importers:
     dependencies:
       '@gnu-taler/taler-util': link:../taler-util
       '@gnu-taler/taler-wallet-core': link:../taler-wallet-core
+      date-fns: 2.22.1
       preact: 10.5.13
       preact-router: 3.2.1_preact@10.5.13
       tslib: 2.1.0
@@ -8087,6 +8089,11 @@ packages:
       whatwg-url: 8.5.0
     dev: true
 
+  /date-fns/2.22.1:
+    resolution: {integrity: 
sha512-yUFPQjrxEmIsMqlHhAhmxkuH769baF21Kk+nZwZGyrMoyLA+LugaQtC0+Tqf9CBUUULWwUJt6Q5ySI3LJDDCGg==}
+    engines: {node: '>=0.11'}
+    dev: false
+
   /date-time/3.1.0:
     resolution: {integrity: 
sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==}
     engines: {node: '>=6'}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]