gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: helpers for auditor integrati


From: gnunet
Subject: [taler-wallet-core] branch master updated: helpers for auditor integration test
Date: Tue, 24 Mar 2020 10:55:10 +0100

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 01e83df4 helpers for auditor integration test
01e83df4 is described below

commit 01e83df471802d3253953b00672af0bc879403fe
Author: Florian Dold <address@hidden>
AuthorDate: Tue Mar 24 15:25:04 2020 +0530

    helpers for auditor integration test
---
 src/headless/taler-wallet-cli.ts | 136 ++++++++++++++++++++++++++++-----------
 src/operations/pay.ts            |   4 --
 src/operations/refresh.ts        |   3 +-
 src/operations/withdraw.ts       |   1 +
 src/types/dbTypes.ts             |   6 +-
 src/types/talerTypes.ts          |  14 ++++
 src/util/logging.ts              |   6 ++
 src/wallet.ts                    | 103 +++++++++++++++++++++++------
 8 files changed, 206 insertions(+), 67 deletions(-)

diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts
index 9a21d2a1..17495391 100644
--- a/src/headless/taler-wallet-cli.ts
+++ b/src/headless/taler-wallet-cli.ts
@@ -32,6 +32,7 @@ import { classifyTalerUri, TalerUriType } from 
"../util/taleruri";
 import util = require("util");
 import { Configuration } from "../util/talerconfig";
 import { setDangerousTimetravel } from "../util/time";
+import { makeCodecForList, codecForString } from "../util/codec";
 
 // Backwards compatibility with nodejs<0.11, where TextEncoder and TextDecoder
 // are not globals yet.
@@ -118,7 +119,7 @@ const walletCli = clk
     help: "Command line interface for the GNU Taler wallet.",
   })
   .maybeOption("walletDbFile", ["--wallet-db"], clk.STRING, {
-    help: "location of the wallet database file"
+    help: "location of the wallet database file",
   })
   .maybeOption("timetravel", ["--timetravel"], clk.INT, {
     help: "modify system time by given offset in microseconds",
@@ -172,8 +173,8 @@ walletCli
   .flag("json", ["--json"], {
     help: "Show raw JSON.",
   })
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const balance = await wallet.getBalances();
       if (args.balance.json) {
         console.log(JSON.stringify(balance, undefined, 2));
@@ -195,8 +196,8 @@ walletCli
   .maybeOption("to", ["--to"], clk.STRING)
   .maybeOption("limit", ["--limit"], clk.STRING)
   .maybeOption("contEvt", ["--continue-with"], clk.STRING)
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const history = await wallet.getHistory();
       if (args.history.json) {
         console.log(JSON.stringify(history, undefined, 2));
@@ -216,8 +217,8 @@ walletCli
 
 walletCli
   .subcommand("", "pending", { help: "Show pending operations." })
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const pending = await wallet.getPendingOperations();
       console.log(JSON.stringify(pending, undefined, 2));
     });
@@ -234,8 +235,8 @@ walletCli
     help: "Run pending operations.",
   })
   .flag("forceNow", ["-f", "--force-now"])
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       await wallet.runPending(args.runPendingOpt.forceNow);
     });
   });
@@ -246,8 +247,8 @@ walletCli
   })
   .requiredArgument("uri", clk.STRING)
   .flag("autoYes", ["-y", "--yes"])
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const uri: string = args.handleUri.uri;
       const uriType = classifyTalerUri(uri);
       switch (uriType) {
@@ -294,9 +295,9 @@ exchangesCli
   .subcommand("exchangesListCmd", "list", {
     help: "List known exchanges.",
   })
-  .action(async args => {
+  .action(async (args) => {
     console.log("Listing exchanges ...");
-    await withWallet(args, async wallet => {
+    await withWallet(args, async (wallet) => {
       const exchanges = await wallet.getExchanges();
       console.log("exchanges", exchanges);
     });
@@ -310,8 +311,8 @@ exchangesCli
     help: "Base URL of the exchange.",
   })
   .flag("force", ["-f", "--force"])
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const res = await wallet.updateExchangeFromUrl(
         args.exchangesUpdateCmd.url,
         args.exchangesUpdateCmd.force,
@@ -328,7 +329,7 @@ advancedCli
   .subcommand("decode", "decode", {
     help: "Decode base32-crockford.",
   })
-  .action(args => {
+  .action((args) => {
     const enc = fs.readFileSync(0, "utf8");
     fs.writeFileSync(1, decodeCrock(enc.trim()));
   });
@@ -338,8 +339,8 @@ advancedCli
     help: "Claim an order but don't pay yet.",
   })
   .requiredArgument("url", clk.STRING)
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const res = await wallet.preparePayForUri(args.payPrepare.url);
       switch (res.status) {
         case "error":
@@ -365,18 +366,75 @@ advancedCli
     help: "Force a refresh on a coin.",
   })
   .requiredArgument("coinPub", clk.STRING)
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       await wallet.refresh(args.refresh.coinPub);
     });
   });
 
+advancedCli
+  .subcommand("dumpCoins", "dump-coins", {
+    help: "Dump coins in an easy-to-process format.",
+  })
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
+      const coinDump = await wallet.dumpCoins();
+      console.log(JSON.stringify(coinDump, undefined, 2));
+    });
+  });
+
+  const coinPubListCodec = makeCodecForList(codecForString);
+
+advancedCli
+  .subcommand("suspendCoins", "suspend-coins", {
+    help: "Mark a coin as suspended, will not be used for payments.",
+  })
+  .requiredArgument("coinPubSpec", clk.STRING)
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
+      let coinPubList: string[];
+      try {
+        coinPubList = coinPubListCodec.decode(
+          JSON.parse(args.suspendCoins.coinPubSpec),
+        );
+      } catch (e) {
+        console.log("could not parse coin list:", e.message);
+        process.exit(1);
+      }
+      for (const c of coinPubList) {
+        await wallet.setCoinSuspended(c, true);
+      }
+    });
+  });
+
+advancedCli
+  .subcommand("unsuspendCoins", "unsuspend-coins", {
+    help: "Mark a coin as suspended, will not be used for payments.",
+  })
+  .requiredArgument("coinPubSpec", clk.STRING)
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
+      let coinPubList: string[];
+      try {
+        coinPubList = coinPubListCodec.decode(
+          JSON.parse(args.unsuspendCoins.coinPubSpec),
+        );
+      } catch (e) {
+        console.log("could not parse coin list:", e.message);
+        process.exit(1);
+      }
+      for (const c of coinPubList) {
+        await wallet.setCoinSuspended(c, false);
+      }
+    });
+  });
+
 advancedCli
   .subcommand("coins", "list-coins", {
     help: "List coins.",
   })
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const coins = await wallet.getCoins();
       for (const coin of coins) {
         console.log(`coin ${coin.coinPub}`);
@@ -395,8 +453,8 @@ advancedCli
     help: "Update reserve status.",
   })
   .requiredArgument("reservePub", clk.STRING)
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const r = await wallet.updateReserve(args.updateReserve.reservePub);
       console.log("updated reserve:", JSON.stringify(r, undefined, 2));
     });
@@ -407,8 +465,8 @@ advancedCli
     help: "Show the current reserve status.",
   })
   .requiredArgument("reservePub", clk.STRING)
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       const r = await wallet.getReserve(args.updateReserve.reservePub);
       console.log("updated reserve:", JSON.stringify(r, undefined, 2));
     });
@@ -421,7 +479,7 @@ const testCli = walletCli.subcommand("testingArgs", 
"testing", {
 testCli
   .subcommand("integrationtestBasic", "integrationtest-basic")
   .requiredArgument("cfgfile", clk.STRING)
-  .action(async args => {
+  .action(async (args) => {
     const cfgStr = fs.readFileSync(args.integrationtestBasic.cfgfile, "utf8");
     const cfg = new Configuration();
     cfg.loadFromString(cfgStr);
@@ -429,7 +487,7 @@ testCli
       await runIntegrationTestBasic(cfg);
     } catch (e) {
       console.log("integration test failed");
-      console.log(e)
+      console.log(e);
       process.exit(1);
     }
     process.exit(0);
@@ -441,7 +499,7 @@ testCli
   .requiredOption("summary", ["-s", "--summary"], clk.STRING, {
     default: "Test Payment",
   })
-  .action(async args => {
+  .action(async (args) => {
     const cmdArgs = args.testPayCmd;
     console.log("creating order");
     const merchantBackend = new MerchantBackendConnection(
@@ -462,7 +520,7 @@ testCli
       return;
     }
     console.log("taler pay URI:", talerPayUri);
-    await withWallet(args, async wallet => {
+    await withWallet(args, async (wallet) => {
       await doPay(wallet, talerPayUri, { alwaysYes: true });
     });
   });
@@ -489,7 +547,7 @@ testCli
   .requiredOption("spendAmount", ["-s", "--spend-amount"], clk.STRING, {
     default: "TESTKUDOS:4",
   })
-  .action(async args => {
+  .action(async (args) => {
     applyVerbose(args.wallet.verbose);
     let cmdObj = args.integrationtestCmd;
 
@@ -501,7 +559,7 @@ testCli
         exchangeBaseUrl: cmdObj.exchange,
         merchantApiKey: cmdObj.merchantApiKey,
         merchantBaseUrl: cmdObj.merchant,
-      }).catch(err => {
+      }).catch((err) => {
         console.error("Integration test failed with exception:");
         console.error(err);
         process.exit(1);
@@ -520,7 +578,7 @@ testCli
   .requiredOption("amount", ["-a", "--amount"], clk.STRING, {
     default: "TESTKUDOS:10",
   })
-  .action(async args => {
+  .action(async (args) => {
     const merchantBackend = new MerchantBackendConnection(
       "https://backend.test.taler.net/";,
       "sandbox",
@@ -539,7 +597,7 @@ testCli
   .requiredOption("bank", ["-b", "--bank"], clk.STRING, {
     default: "https://bank.test.taler.net/";,
   })
-  .action(async args => {
+  .action(async (args) => {
     const b = new Bank(args.genWithdrawUri.bank);
     const user = await b.registerRandomUser();
     const url = await b.generateWithdrawUri(user, args.genWithdrawUri.amount);
@@ -559,7 +617,7 @@ testCli
   .requiredOption("summary", ["-s", "--summary"], clk.STRING, {
     default: "Test Payment (for refund)",
   })
-  .action(async args => {
+  .action(async (args) => {
     const cmdArgs = args.genRefundUri;
     const merchantBackend = new MerchantBackendConnection(
       "https://backend.test.taler.net/";,
@@ -578,7 +636,7 @@ testCli
       process.exit(1);
       return;
     }
-    await withWallet(args, async wallet => {
+    await withWallet(args, async (wallet) => {
       await doPay(wallet, talerPayUri, { alwaysYes: true });
     });
     const refundUri = await merchantBackend.refund(
@@ -611,7 +669,7 @@ testCli
   .requiredOption("merchantApiKey", ["-k", "--merchant-api-key"], clk.STRING, {
     default: "sandbox",
   })
-  .action(async args => {
+  .action(async (args) => {
     const cmdArgs = args.genPayUri;
     console.log("creating order");
     const merchantBackend = new MerchantBackendConnection(
@@ -669,8 +727,8 @@ testCli
     default: "https://bank.test.taler.net/";,
     help: "Bank base URL",
   })
-  .action(async args => {
-    await withWallet(args, async wallet => {
+  .action(async (args) => {
+    await withWallet(args, async (wallet) => {
       await withdrawTestBalance(
         wallet,
         args.withdrawArgs.amount,
diff --git a/src/operations/pay.ts b/src/operations/pay.ts
index b8a63cb1..9a8017e4 100644
--- a/src/operations/pay.ts
+++ b/src/operations/pay.ts
@@ -318,10 +318,6 @@ async function getCoinsForPayment(
       .iterIndex(Stores.coins.exchangeBaseUrlIndex, exchange.baseUrl)
       .toArray();
 
-    const denoms = await ws.db
-      .iterIndex(Stores.denominations.exchangeBaseUrlIndex, exchange.baseUrl)
-      .toArray();
-
     if (!coins || coins.length === 0) {
       continue;
     }
diff --git a/src/operations/refresh.ts b/src/operations/refresh.ts
index 092d9f15..c04b7927 100644
--- a/src/operations/refresh.ts
+++ b/src/operations/refresh.ts
@@ -412,7 +412,8 @@ async function refreshReveal(
       coinSource: {
         type: CoinSourceType.Refresh,
         oldCoinPub: refreshSession.meltCoinPub,
-      }
+      },
+      suspended: false,
     };
 
     coins.push(coin);
diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts
index 09d912bc..37993023 100644
--- a/src/operations/withdraw.ts
+++ b/src/operations/withdraw.ts
@@ -240,6 +240,7 @@ async function processPlanchet(
       reservePub: planchet.reservePub,
       withdrawSessionId: withdrawalSessionId,
     },
+    suspended: false,
   };
 
   let withdrawSessionFinished = false;
diff --git a/src/types/dbTypes.ts b/src/types/dbTypes.ts
index f28426ac..5a5ac7c3 100644
--- a/src/types/dbTypes.ts
+++ b/src/types/dbTypes.ts
@@ -674,11 +674,9 @@ export interface CoinRecord {
   exchangeBaseUrl: string;
 
   /**
-   * We have withdrawn the coin, but it's not accepted by the exchange anymore.
-   * We have to tell an auditor and wait for compensation or for the exchange
-   * to fix it.
+   * The coin is currently suspended, and will not be used for payments.
    */
-  suspended?: boolean;
+  suspended: boolean;
 
   /**
    * Blinding key used when withdrawing the coin.
diff --git a/src/types/talerTypes.ts b/src/types/talerTypes.ts
index 569b9312..e5be32ab 100644
--- a/src/types/talerTypes.ts
+++ b/src/types/talerTypes.ts
@@ -759,6 +759,20 @@ export class WithdrawResponse {
   ev_sig: string;
 }
 
+export interface CoinDumpJson {
+  coins: Array<{
+    denom_pub: string;
+    denom_pub_hash: string;
+    denom_value: string;
+    coin_pub: string;
+    exchange_base_url: string;
+    remaining_value: string;
+    refresh_parent_coin_pub: string | undefined;
+    withdrawal_reserve_pub: string | undefined;
+    coin_suspended: boolean;
+  }>;
+}
+
 export type AmountString = string;
 export type Base32String = string;
 export type EddsaSignatureString = string;
diff --git a/src/util/logging.ts b/src/util/logging.ts
index 309d1593..4560105f 100644
--- a/src/util/logging.ts
+++ b/src/util/logging.ts
@@ -19,6 +19,12 @@ export class Logger {
   info(message: string, ...args: any[]) {
     console.log(`${new Date().toISOString()} ${this.tag} INFO ` + message, 
...args);
   }
+  warn(message: string, ...args: any[]) {
+    console.log(`${new Date().toISOString()} ${this.tag} WARN ` + message, 
...args);
+  }
+  error(message: string, ...args: any[]) {
+    console.log(`${new Date().toISOString()} ${this.tag} ERROR ` + message, 
...args);
+  }
   trace(message: any, ...args: any[]) {
     console.log(`${new Date().toISOString()} ${this.tag} TRACE ` + message, 
...args)
   }
diff --git a/src/wallet.ts b/src/wallet.ts
index 6245941a..df83eec8 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -53,8 +53,9 @@ import {
   ReserveRecord,
   Stores,
   ReserveRecordStatus,
+  CoinSourceType,
 } from "./types/dbTypes";
-import { MerchantRefundPermission } from "./types/talerTypes";
+import { MerchantRefundPermission, CoinDumpJson } from "./types/talerTypes";
 import {
   BenchmarkResult,
   ConfirmPayResult,
@@ -238,7 +239,10 @@ export class Wallet {
         await this.processOnePendingOperation(p, forceNow);
       } catch (e) {
         if (e instanceof OperationFailedAndReportedError) {
-          console.error("Operation failed:", JSON.stringify(e.operationError, 
undefined, 2));
+          console.error(
+            "Operation failed:",
+            JSON.stringify(e.operationError, undefined, 2),
+          );
         } else {
           console.error(e);
         }
@@ -254,7 +258,7 @@ export class Wallet {
   public async runUntilDone(): Promise<void> {
     const p = new Promise((resolve, reject) => {
       // Run this asynchronously
-      this.addNotificationListener(n => {
+      this.addNotificationListener((n) => {
         if (
           n.type === NotificationType.WaitingForRetry &&
           n.numGivingLiveness == 0
@@ -263,7 +267,7 @@ export class Wallet {
           resolve();
         }
       });
-      this.runRetryLoop().catch(e => {
+      this.runRetryLoop().catch((e) => {
         console.log("exception in wallet retry loop");
         reject(e);
       });
@@ -279,7 +283,7 @@ export class Wallet {
   public async runUntilDoneAndStop(): Promise<void> {
     const p = new Promise((resolve, reject) => {
       // Run this asynchronously
-      this.addNotificationListener(n => {
+      this.addNotificationListener((n) => {
         if (
           n.type === NotificationType.WaitingForRetry &&
           n.numGivingLiveness == 0
@@ -288,7 +292,7 @@ export class Wallet {
           this.stop();
         }
       });
-      this.runRetryLoop().catch(e => {
+      this.runRetryLoop().catch((e) => {
         console.log("exception in wallet retry loop");
         reject(e);
       });
@@ -371,9 +375,9 @@ export class Wallet {
   async fillDefaults() {
     await this.db.runWithWriteTransaction(
       [Stores.config, Stores.currencies],
-      async tx => {
+      async (tx) => {
         let applied = false;
-        await tx.iter(Stores.config).forEach(x => {
+        await tx.iter(Stores.config).forEach((x) => {
           if (x.key == "currencyDefaultsApplied" && x.value == true) {
             applied = true;
           }
@@ -506,7 +510,7 @@ export class Wallet {
     try {
       const refreshGroupId = await this.db.runWithWriteTransaction(
         [Stores.refreshGroups],
-        async tx => {
+        async (tx) => {
           return await createRefreshGroup(
             tx,
             [{ coinPub: oldCoinPub }],
@@ -573,13 +577,13 @@ export class Wallet {
   async getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> {
     return await this.db
       .iter(Stores.reserves)
-      .filter(r => r.exchangeBaseUrl === exchangeBaseUrl);
+      .filter((r) => r.exchangeBaseUrl === exchangeBaseUrl);
   }
 
   async getCoinsForExchange(exchangeBaseUrl: string): Promise<CoinRecord[]> {
     return await this.db
       .iter(Stores.coins)
-      .filter(c => c.exchangeBaseUrl === exchangeBaseUrl);
+      .filter((c) => c.exchangeBaseUrl === exchangeBaseUrl);
   }
 
   async getCoins(): Promise<CoinRecord[]> {
@@ -598,22 +602,22 @@ export class Wallet {
   async getSenderWireInfos(): Promise<SenderWireInfos> {
     const m: { [url: string]: Set<string> } = {};
 
-    await this.db.iter(Stores.exchanges).forEach(x => {
+    await this.db.iter(Stores.exchanges).forEach((x) => {
       const wi = x.wireInfo;
       if (!wi) {
         return;
       }
       const s = (m[x.baseUrl] = m[x.baseUrl] || new Set());
-      Object.keys(wi.feesForType).map(k => s.add(k));
+      Object.keys(wi.feesForType).map((k) => s.add(k));
     });
 
     const exchangeWireTypes: { [url: string]: string[] } = {};
-    Object.keys(m).map(e => {
+    Object.keys(m).map((e) => {
       exchangeWireTypes[e] = Array.from(m[e]);
     });
 
     const senderWiresSet: Set<string> = new Set();
-    await this.db.iter(Stores.senderWires).forEach(x => {
+    await this.db.iter(Stores.senderWires).forEach((x) => {
       senderWiresSet.add(x.paytoUri);
     });
 
@@ -735,20 +739,20 @@ export class Wallet {
     }
     const refundsDoneAmounts = Object.values(
       purchase.refundState.refundsDone,
-    ).map(x => Amounts.parseOrThrow(x.perm.refund_amount));
+    ).map((x) => Amounts.parseOrThrow(x.perm.refund_amount));
     const refundsPendingAmounts = Object.values(
       purchase.refundState.refundsPending,
-    ).map(x => Amounts.parseOrThrow(x.perm.refund_amount));
+    ).map((x) => Amounts.parseOrThrow(x.perm.refund_amount));
     const totalRefundAmount = Amounts.sum([
       ...refundsDoneAmounts,
       ...refundsPendingAmounts,
     ]).amount;
     const refundsDoneFees = Object.values(
       purchase.refundState.refundsDone,
-    ).map(x => Amounts.parseOrThrow(x.perm.refund_amount));
+    ).map((x) => Amounts.parseOrThrow(x.perm.refund_amount));
     const refundsPendingFees = Object.values(
       purchase.refundState.refundsPending,
-    ).map(x => Amounts.parseOrThrow(x.perm.refund_amount));
+    ).map((x) => Amounts.parseOrThrow(x.perm.refund_amount));
     const totalRefundFees = Amounts.sum([
       ...refundsDoneFees,
       ...refundsPendingFees,
@@ -765,4 +769,65 @@ export class Wallet {
   benchmarkCrypto(repetitions: number): Promise<BenchmarkResult> {
     return this.ws.cryptoApi.benchmark(repetitions);
   }
+
+  async setCoinSuspended(coinPub: string, suspended: boolean): Promise<void> {
+    await this.db.runWithWriteTransaction([Stores.coins], async (tx) => {
+      const c = await tx.get(Stores.coins, coinPub);
+      if (!c) {
+        logger.warn(`coin ${coinPub} not found, won't suspend`);
+        return;
+      }
+      c.suspended = suspended;
+      await tx.put(Stores.coins, c);
+    });
+  }
+
+  /**
+   * Dump the public information of coins we have in an easy-to-process format.
+   */
+  async dumpCoins(): Promise<CoinDumpJson> {
+    const coins = await this.db.iter(Stores.coins).toArray();
+    const coinsJson: CoinDumpJson = { coins: [] };
+    for (const c of coins) {
+      const denom = await this.db.get(Stores.denominations, [
+        c.exchangeBaseUrl,
+        c.denomPub,
+      ]);
+      if (!denom) {
+        console.error("no denom session found for coin");
+        continue;
+      }
+      const cs = c.coinSource;
+      let refreshParentCoinPub: string | undefined;
+      if (cs.type == CoinSourceType.Refresh) {
+        refreshParentCoinPub = cs.oldCoinPub;
+      }
+      let withdrawalReservePub: string | undefined;
+      if (cs.type == CoinSourceType.Withdraw) {
+        const ws = await this.db.get(
+          Stores.withdrawalSession,
+          cs.withdrawSessionId,
+        );
+        if (!ws) {
+          console.error("no withdrawal session found for coin");
+          continue;
+        }
+        if (ws.source.type == "reserve") {
+          withdrawalReservePub = ws.source.reservePub;
+        }
+      }
+      coinsJson.coins.push({
+        coin_pub: c.coinPub,
+        denom_pub: c.denomPub,
+        denom_pub_hash: c.denomPubHash,
+        denom_value: Amounts.toString(denom.value),
+        exchange_base_url: c.exchangeBaseUrl,
+        refresh_parent_coin_pub: refreshParentCoinPub,
+        remaining_value: Amounts.toString(c.currentAmount),
+        withdrawal_reserve_pub: withdrawalReservePub,
+        coin_suspended: c.suspended,
+      });
+    }
+    return coinsJson;
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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