gnunet-svn
[Top][All Lists]
Advanced

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

[taler-depolymerization] branch master updated (2ad5eb9 -> fb88a48)


From: gnunet
Subject: [taler-depolymerization] branch master updated (2ad5eb9 -> fb88a48)
Date: Wed, 02 Feb 2022 20:41:02 +0100

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

antoine pushed a change to branch master
in repository depolymerization.

    from 2ad5eb9  eth-wire: wire draft
     new 3429547  Cleanup
     new fb88a48  presentation: progress

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 btc-wire/src/bin/btc-test.rs                       | 398 ---------------------
 btc-wire/src/bin/btc-wire-cli.rs                   |   6 +-
 btc-wire/src/bin/btc-wire-utils.rs                 |  10 +-
 btc-wire/src/lib.rs                                |   4 +-
 btc-wire/src/loops.rs                              |   2 +-
 btc-wire/src/loops/worker.rs                       |  35 +-
 btc-wire/src/main.rs                               |   6 +-
 btc-wire/src/{info.rs => metadata.rs}              |  98 ++---
 btc-wire/src/reconnect.rs                          |  10 +-
 btc-wire/src/rpc.rs                                |   4 +-
 btc-wire/src/rpc_utils.rs                          |   4 +-
 docs/presentation.tex                              | 102 +++---
 eth-wire/src/bin/eth-test.rs                       | 140 --------
 taler-common/src/lib.rs => eth-wire/src/loops.rs   |  19 +-
 .../src/lib.rs => eth-wire/src/loops/watcher.rs    |  24 +-
 eth-wire/src/loops/worker.rs                       | 150 ++++++++
 eth-wire/src/main.rs                               | 184 +---------
 eth-wire/src/rpc.rs                                |   2 +-
 {btc-wire => eth-wire}/src/sql.rs                  |  36 +-
 eth-wire/src/taler_util.rs                         |  15 +
 taler-common/src/config.rs                         |   2 +-
 21 files changed, 335 insertions(+), 916 deletions(-)
 delete mode 100644 btc-wire/src/bin/btc-test.rs
 rename btc-wire/src/{info.rs => metadata.rs} (51%)
 delete mode 100644 eth-wire/src/bin/eth-test.rs
 copy taler-common/src/lib.rs => eth-wire/src/loops.rs (66%)
 copy taler-common/src/lib.rs => eth-wire/src/loops/watcher.rs (66%)
 create mode 100644 eth-wire/src/loops/worker.rs
 copy {btc-wire => eth-wire}/src/sql.rs (51%)

diff --git a/btc-wire/src/bin/btc-test.rs b/btc-wire/src/bin/btc-test.rs
deleted file mode 100644
index eb150e5..0000000
--- a/btc-wire/src/bin/btc-test.rs
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2022 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU Affero General Public License as published by the Free 
Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  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 Affero General Public License for more 
details.
-
-  You should have received a copy of the GNU Affero General Public License 
along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-use core::panic;
-use std::{collections::HashSet, iter::repeat_with, panic::AssertUnwindSafe};
-
-use bitcoin::{Address, Amount, Network, Txid};
-use btc_wire::{
-    config::BitcoinConfig,
-    rpc::{self, BtcRpc, Category},
-    rpc_utils::{default_data_dir, CLIENT, WIRE},
-};
-use taler_common::rand_slice;
-
-const RESERVE: &str = "reserve";
-
-/// Instrumentation test
-pub fn main() {
-    let test_amount = Amount::from_sat(1500);
-    let data_dir = default_data_dir();
-    let config = BitcoinConfig::load(&data_dir).unwrap();
-    // Network check
-    match config.network {
-        Network::Bitcoin => {
-            panic!("Do not run tests on the mainnet, you are going to loose 
money")
-        }
-        Network::Testnet | Network::Signet => {
-            println!("Running on testnet, slow network mining")
-        }
-        Network::Regtest => println!("Running on regtest, fast manual mining"),
-    }
-
-    // Wallet check
-    {
-        let existing_wallets: HashSet<String> = 
std::fs::read_dir(config.dir.join("wallets"))
-            .unwrap()
-            .filter_map(|it| it.ok())
-            .map(|it| it.file_name().to_string_lossy().to_string())
-            .collect();
-
-        let wallets = [CLIENT, WIRE, RESERVE];
-
-        let mut rpc = BtcRpc::common(&config).unwrap();
-        if !existing_wallets.contains(CLIENT)
-            || !existing_wallets.contains(WIRE)
-            || !existing_wallets.contains(RESERVE)
-        {
-            println!("Generate tests wallets");
-            // Create wallets
-            for wallet in &wallets {
-                rpc.create_wallet(wallet).unwrap();
-            }
-        }
-
-        // Load wallets
-        for wallet in &wallets {
-            if let Err(e) = rpc.load_wallet(wallet) {
-                match e {
-                    rpc::Error::RPC { code, .. }
-                        if code == rpc::ErrorCode::RpcWalletAlreadyLoaded => {}
-                    e => Err(e).unwrap(),
-                }
-            }
-        }
-    }
-
-    // Client initialization
-    let mut client_rpc = BtcRpc::wallet(&config, CLIENT).unwrap();
-    let mut wire_rpc = BtcRpc::wallet(&config, WIRE).unwrap();
-    let mut reserve_rpc = BtcRpc::wallet(&config, RESERVE).unwrap();
-    let client_addr = client_rpc.get_new_address().unwrap();
-    let wire_addr = wire_rpc.get_new_address().unwrap();
-    let reserve_addr = reserve_rpc.get_new_address().unwrap();
-
-    let next_block = |reserve_rpc: &mut BtcRpc| {
-        match config.network {
-            Network::Regtest => {
-                // Manually mine a block
-                reserve_rpc.generate(1, &reserve_addr).unwrap();
-            }
-            _ => {
-                // Wait for next network block
-                reserve_rpc.wait_for_new_block(0).ok();
-            }
-        }
-    };
-
-    let wait_for_tx = |rpc: &mut BtcRpc, reserve_rpc: &mut BtcRpc, txs: 
&[Txid]| {
-        let mut count = 0;
-        while txs
-            .iter()
-            .any(|id| rpc.get_tx(id).unwrap().confirmations <= 0)
-        {
-            next_block(reserve_rpc);
-            if count > 3 {
-                panic!("Transaction no sended after 4 blocks");
-            }
-            count += 1;
-        }
-    };
-
-    // Balance check
-
-    {
-        // Transfer all wire money to client
-        let wire_balance = wire_rpc.get_balance().unwrap();
-        wire_rpc.send(&client_addr, &wire_balance, true).ok();
-        // Transfer all wire money to client
-        let reserve_balance = reserve_rpc.get_balance().unwrap();
-        reserve_rpc.send(&client_addr, &reserve_balance, true).ok();
-        next_block(&mut reserve_rpc);
-
-        let balance = client_rpc.get_balance().unwrap();
-        let min_balance = test_amount * 3;
-        if balance < min_balance {
-            println!(
-                "Client wallet have only {}, {} are required to perform the 
test",
-                balance, min_balance
-            );
-            match config.network {
-                Network::Bitcoin | Network::Testnet | Network::Signet => {
-                    if config.network == Network::Bitcoin {
-                        println!("Send coins to this address: {}", 
client_addr);
-                    } else {
-                        println!("Request coins from a faucet such as 
https://bitcoinfaucet.uo1.net/send.php to this address: {}", client_addr);
-                    }
-                    println!("Waiting for the transaction...");
-                    while client_rpc.get_balance().unwrap() < min_balance {
-                        client_rpc.wait_for_new_block(0).ok();
-                    }
-                }
-                Network::Regtest => {
-                    println!("Add 50B to client wallet");
-                    client_rpc
-                        .generate(101 /* Need 100 blocks to validate */, 
&reserve_addr)
-                        .unwrap();
-                    reserve_rpc
-                        .send(&client_addr, &Amount::from_sat(5_000_000_000), 
true)
-                        .unwrap();
-                    next_block(&mut reserve_rpc);
-                }
-            }
-        }
-
-        println!(
-            "Initial state:\n{} {}\n{} {}",
-            WIRE,
-            wire_rpc.get_balance().unwrap(),
-            CLIENT,
-            client_rpc.get_balance().unwrap()
-        );
-    }
-
-    let mut runner = TestRunner::new();
-
-    runner.test("OpReturn metadata", || {
-        // Send metadata
-        let msg = "J'aime le chocolat".as_bytes();
-        let id = client_rpc
-            .send_op_return(&wire_addr, &test_amount, msg, false, false)
-            .unwrap();
-        // Check in mempool
-        assert!(
-            tx_exist(&mut client_rpc, &id, 0, Category::Send).unwrap(),
-            "Not in mempool"
-        );
-        // Check mined
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[id]);
-        assert!(
-            tx_exist(&mut wire_rpc, &id, 1, Category::Receive).unwrap(),
-            "Not mined"
-        );
-        // Check extract
-        let (_, extracted) = wire_rpc.get_tx_op_return(&id).unwrap();
-        assert_eq!(msg, extracted, "Corrupted metadata");
-    });
-    runner.test("SegWit metadata", || {
-        // Send metadata
-        let key = rand_slice();
-        let id = client_rpc
-            .send_segwit_key(&wire_addr, &test_amount, &key)
-            .unwrap();
-        // Check in mempool
-        assert!(
-            tx_exist(&mut client_rpc, &id, 0, Category::Send).unwrap(),
-            "Not in mempool"
-        );
-        // Check mined
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[id]);
-        assert!(
-            tx_exist(&mut wire_rpc, &id, 1, Category::Receive).unwrap(),
-            "Not mined"
-        );
-        // Check extract
-        let (_, extracted) = wire_rpc.get_tx_segwit_key(&id).unwrap();
-        assert_eq!(key, extracted, "Corrupted metadata");
-    });
-
-    let bounce_fee = Amount::from_sat(300);
-    runner.test("Bounce simple", || {
-        let before = client_rpc.get_balance().unwrap();
-        let send_id = client_rpc.send(&wire_addr, &test_amount, 
false).unwrap();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[send_id]);
-        let bounce_id = wire_rpc.bounce(&send_id, &bounce_fee, &[]).unwrap();
-        wait_for_tx(&mut wire_rpc, &mut reserve_rpc, &[bounce_id]);
-        let bounce_tx_fee = wire_rpc.get_tx(&bounce_id).unwrap().details[0]
-            .fee
-            .unwrap()
-            .abs()
-            .to_unsigned()
-            .unwrap();
-        let send_tx_fee = client_rpc.get_tx(&send_id).unwrap().details[0]
-            .fee
-            .unwrap()
-            .abs()
-            .to_unsigned()
-            .unwrap();
-        let after = client_rpc.get_balance().unwrap();
-        assert!(before >= after);
-        assert_eq!(before - after, bounce_tx_fee + bounce_fee + send_tx_fee);
-    });
-    runner.test("Bounce minimal amount", || {
-        let send_id = client_rpc
-            .send(&wire_addr, &Amount::from_sat(294), false)
-            .unwrap();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[send_id]);
-        assert!(matches!(
-            wire_rpc.bounce(&send_id, &bounce_fee, &[]),
-            Err(rpc::Error::RPC {
-                code: rpc::ErrorCode::RpcWalletInsufficientFunds,
-                ..
-            })
-        ));
-    });
-    runner.test("Bounce simple with metadata", || {
-        let before = client_rpc.get_balance().unwrap();
-        let send_id = client_rpc.send(&wire_addr, &test_amount, 
false).unwrap();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[send_id]);
-        let bounce_id = wire_rpc
-            .bounce(&send_id, &bounce_fee, &[12, 34, 56, 78])
-            .unwrap();
-        wait_for_tx(&mut wire_rpc, &mut reserve_rpc, &[bounce_id]);
-        let bounce_tx_fee = wire_rpc.get_tx(&bounce_id).unwrap().details[0]
-            .fee
-            .unwrap()
-            .abs()
-            .to_unsigned()
-            .unwrap();
-        let send_tx_fee = client_rpc.get_tx(&send_id).unwrap().details[0]
-            .fee
-            .unwrap()
-            .abs()
-            .to_unsigned()
-            .unwrap();
-        wire_rpc.get_tx_op_return(&bounce_id).unwrap();
-        let after = client_rpc.get_balance().unwrap();
-        assert!(before >= after);
-        assert_eq!(before - after, bounce_tx_fee + bounce_fee + send_tx_fee);
-    });
-    runner.test("Bounce minimal amount with metadata", || {
-        let send_id = client_rpc
-            .send(&wire_addr, &Amount::from_sat(294), false)
-            .unwrap();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[send_id]);
-        assert!(matches!(
-            wire_rpc.bounce(&send_id, &bounce_fee, &[12, 34, 56]),
-            Err(rpc::Error::RPC {
-                code: rpc::ErrorCode::RpcWalletError,
-                ..
-            })
-        ));
-    });
-    runner.test("Bounce too small amount", || {
-        let send_id = client_rpc
-            .send(&wire_addr, &(Amount::from_sat(294) + bounce_fee), false)
-            .unwrap();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[send_id]);
-        assert!(matches!(
-            wire_rpc.bounce(&send_id, &bounce_fee, &[]),
-            Err(rpc::Error::RPC {
-                code: rpc::ErrorCode::RpcWalletInsufficientFunds,
-                ..
-            })
-        ));
-    });
-    runner.test("Bounce complex", || {
-        // Generate 6 new addresses
-        let addresses: Vec<Address> = repeat_with(|| 
client_rpc.get_new_address().unwrap())
-            .take(6)
-            .collect();
-        // Send transaction to self with 1, 2 and 3 outputs
-        let txs: Vec<Txid> = [&addresses[0..1], &addresses[1..3], 
&addresses[3..]]
-            .into_iter()
-            .map(|addresses| {
-                client_rpc
-                    .send_custom(
-                        &[],
-                        addresses.iter().map(|addr| (addr, &test_amount)),
-                        None,
-                        false,
-                        false,
-                    )
-                    .unwrap()
-            })
-            .collect();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, txs.as_slice());
-        let before = client_rpc.get_balance().unwrap();
-        // Send a transaction with multiple input from multiple transaction of 
different outputs len
-        let send_id = client_rpc
-            .send_custom(&txs, [(&wire_addr, &(test_amount * 3))], None, 
false, false)
-            .unwrap();
-        wait_for_tx(&mut client_rpc, &mut reserve_rpc, &[send_id]);
-        let bounce_id = wire_rpc.bounce(&send_id, &bounce_fee, &[]).unwrap();
-        wait_for_tx(&mut wire_rpc, &mut reserve_rpc, &[bounce_id]);
-        let after = client_rpc.get_balance().unwrap();
-        let bounce_tx_fee = wire_rpc.get_tx(&bounce_id).unwrap().details[0]
-            .fee
-            .unwrap()
-            .abs()
-            .to_unsigned()
-            .unwrap();
-        let send_tx_fee = client_rpc.get_tx(&send_id).unwrap().details[0]
-            .fee
-            .unwrap()
-            .abs()
-            .to_unsigned()
-            .unwrap();
-        assert!(before >= after);
-        assert_eq!(before - after, bounce_tx_fee + bounce_fee + send_tx_fee);
-    });
-
-    runner.conclude();
-}
-
-/// Check a specific transaction exist in a wallet historic
-fn tx_exist(
-    rpc: &mut BtcRpc,
-    id: &Txid,
-    min_confirmation: i32,
-    detail: Category,
-) -> rpc::Result<bool> {
-    let result = rpc.list_since_block(None, 1, false).unwrap();
-    let found = result
-        .transactions
-        .into_iter()
-        .any(|tx| tx.category == detail && tx.confirmations >= 
min_confirmation && tx.txid == *id);
-    Ok(found)
-}
-
-/// Run test track success and errors
-struct TestRunner {
-    nb_ok: usize,
-    nb_err: usize,
-}
-
-impl TestRunner {
-    fn new() -> Self {
-        Self {
-            nb_err: 0,
-            nb_ok: 0,
-        }
-    }
-
-    fn test(&mut self, name: &str, test: impl FnOnce()) {
-        println!("{}", name);
-
-        let result = std::panic::catch_unwind(AssertUnwindSafe(test));
-        if result.is_ok() {
-            println!("OK");
-            self.nb_ok += 1;
-        } else {
-            println!("ERR");
-            self.nb_err += 1;
-        }
-    }
-
-    /// Wait for tests completion and print results
-    fn conclude(self) {
-        println!(
-            "Result for {} tests: {} ok and {} err",
-            self.nb_ok + self.nb_err,
-            self.nb_ok,
-            self.nb_err
-        );
-    }
-}
diff --git a/btc-wire/src/bin/btc-wire-cli.rs b/btc-wire/src/bin/btc-wire-cli.rs
index 8bba7e7..47f3096 100644
--- a/btc-wire/src/bin/btc-wire-cli.rs
+++ b/btc-wire/src/bin/btc-wire-cli.rs
@@ -15,7 +15,7 @@
 */
 use btc_wire::{
     config::{BitcoinConfig, WIRE_WALLET_NAME},
-    rpc::{BtcRpc, Error, ErrorCode},
+    rpc::{Rpc, Error, ErrorCode},
     rpc_utils::default_data_dir,
 };
 use taler_common::{
@@ -52,7 +52,7 @@ fn main() {
                     .expect("Failed to load bitcoin configuration");
             // Connect to bitcoin node
             let mut rpc =
-                BtcRpc::common(&btc_conf).expect("Failed to connect to bitcoin 
RPC server");
+                Rpc::common(&btc_conf).expect("Failed to connect to bitcoin 
RPC server");
 
             // Skip previous blocks
             let info = rpc
@@ -85,7 +85,7 @@ fn main() {
                 String::from_utf8(row.get(0)).expect("Stored address is not a 
valid string")
             } else {
                 // Or generate a new one
-                let new = BtcRpc::wallet(&btc_conf, WIRE_WALLET_NAME)
+                let new = Rpc::wallet(&btc_conf, WIRE_WALLET_NAME)
                     .expect("Failed to connect to wallet bitcoin RPC server")
                     .get_new_address()
                     .expect("Failed to generate new address")
diff --git a/btc-wire/src/bin/btc-wire-utils.rs 
b/btc-wire/src/bin/btc-wire-utils.rs
index e5ecf71..b058656 100644
--- a/btc-wire/src/bin/btc-wire-utils.rs
+++ b/btc-wire/src/bin/btc-wire-utils.rs
@@ -18,7 +18,7 @@ use std::path::PathBuf;
 use bitcoin::{Address, Amount, Network};
 use btc_wire::{
     config::BitcoinConfig,
-    rpc::{BtcRpc, Category, Error, ErrorCode},
+    rpc::{Rpc, Category, Error, ErrorCode},
     rpc_utils::default_data_dir,
 };
 use taler_common::{
@@ -92,19 +92,19 @@ struct ClearCmd {
 
 struct App {
     config: BitcoinConfig,
-    client: BtcRpc,
+    client: Rpc,
 }
 
 impl App {
     pub fn start(data_dir: Option<PathBuf>) -> Self {
         let data_dir = data_dir.unwrap_or_else(default_data_dir);
         let config = BitcoinConfig::load(data_dir).unwrap();
-        let client = BtcRpc::common(&config).unwrap();
+        let client = Rpc::common(&config).unwrap();
 
         Self { config, client }
     }
 
-    pub fn auto_wallet(&mut self, name: &str) -> (BtcRpc, Address) {
+    pub fn auto_wallet(&mut self, name: &str) -> (Rpc, Address) {
         // Auto load
         if let Err(err) = self.client.load_wallet(name) {
             match err {
@@ -112,7 +112,7 @@ impl App {
                 e => Err(e).unwrap(),
             }
         }
-        let mut wallet = BtcRpc::wallet(&self.config, name).unwrap();
+        let mut wallet = Rpc::wallet(&self.config, name).unwrap();
         let addr = wallet
             .get_new_address()
             .unwrap_or_else(|_| panic!("Failed to get wallet address {}", 
name));
diff --git a/btc-wire/src/lib.rs b/btc-wire/src/lib.rs
index 4f824c9..3e9f692 100644
--- a/btc-wire/src/lib.rs
+++ b/btc-wire/src/lib.rs
@@ -16,7 +16,7 @@
 use std::str::FromStr;
 
 use bitcoin::{hashes::hex::FromHex, Address, Amount, Network, Txid};
-use rpc::{BtcRpc, Category, TransactionFull};
+use rpc::{Rpc, Category, TransactionFull};
 use rpc_utils::{segwit_min_amount, sender_address};
 use segwit::{decode_segwit_msg, encode_segwit_key};
 
@@ -42,7 +42,7 @@ pub enum GetOpReturnErr {
 }
 
 /// An extended bitcoincore JSON-RPC api client who can send and retrieve 
metadata with their transaction
-impl BtcRpc {
+impl Rpc {
     /// Send a transaction with a 32B key as metadata encoded using fake 
segwit addresses
     pub fn send_segwit_key(
         &mut self,
diff --git a/btc-wire/src/loops.rs b/btc-wire/src/loops.rs
index 999a671..3ad4ae8 100644
--- a/btc-wire/src/loops.rs
+++ b/btc-wire/src/loops.rs
@@ -26,7 +26,7 @@ pub mod worker;
 #[derive(Debug, thiserror::Error)]
 pub enum LoopError {
     #[error(transparent)]
-    RPC(#[from] rpc::Error),
+    Rpc(#[from] rpc::Error),
     #[error(transparent)]
     DB(#[from] postgres::Error),
     #[error("Another btc_wire process is running concurrently")]
diff --git a/btc-wire/src/loops/worker.rs b/btc-wire/src/loops/worker.rs
index e2a32d8..e752b50 100644
--- a/btc-wire/src/loops/worker.rs
+++ b/btc-wire/src/loops/worker.rs
@@ -22,7 +22,7 @@ use std::{
 
 use bitcoin::{hashes::Hash, Amount as BtcAmount, BlockHash, Txid};
 use btc_wire::{
-    rpc::{self, BtcRpc, Category, ErrorCode, TransactionFull},
+    rpc::{self, Rpc, Category, ErrorCode, TransactionFull},
     rpc_utils::sender_address,
     GetOpReturnErr, GetSegwitErr,
 };
@@ -37,7 +37,7 @@ use taler_common::{
 
 use crate::{
     fail_point::fail_point,
-    info::{decode_info, encode_info, Info},
+    metadata::OutMetadata,
     reconnect::{AutoReconnectRPC, AutoReconnectSql},
     sql::{sql_addr, sql_btc_amount, sql_txid},
     status::{BounceStatus, TxStatus},
@@ -129,7 +129,7 @@ pub fn worker(
             // approach is to wait for the next loop when an RPC error is 
caught to prevent endless logged errors.
             skip_notification = !matches!(
                 e,
-                LoopError::RPC(rpc::Error::RPC { .. } | rpc::Error::Bitcoin(_))
+                LoopError::Rpc(rpc::Error::RPC { .. } | rpc::Error::Bitcoin(_))
                     | LoopError::Concurrency
             );
         } else {
@@ -139,7 +139,7 @@ pub fn worker(
 }
 
 /// Send atransaction on the blockchain, return true if more transactions with 
the same status remains
-fn send(db: &mut Client, rpc: &mut BtcRpc, status: TxStatus) -> 
LoopResult<bool> {
+fn send(db: &mut Client, rpc: &mut Rpc, status: TxStatus) -> LoopResult<bool> {
     assert!(status == TxStatus::Delayed || status == TxStatus::Requested);
     // We rely on the advisory lock to ensure we are the only one sending 
transactions
     let row = db.query_opt(
@@ -152,8 +152,8 @@ fn send(db: &mut Client, rpc: &mut BtcRpc, status: 
TxStatus) -> LoopResult<bool>
         let wtid: [u8; 32] = sql_array(row, 2);
         let addr = sql_addr(row, 3);
         let url = sql_url(row, 4);
-        let info = Info::Transaction { wtid, url };
-        let metadata = encode_info(&info);
+        let info = OutMetadata::Transaction { wtid, url };
+        let metadata = info.encode();
 
         match rpc.send_op_return(&addr, &amount, &metadata, false, true) {
             Ok(tx_id) => {
@@ -180,7 +180,7 @@ fn send(db: &mut Client, rpc: &mut BtcRpc, status: 
TxStatus) -> LoopResult<bool>
 /// Bounce a transaction on the blockchain, return true if more bounce with 
the same status remains
 fn bounce(
     db: &mut Client,
-    rpc: &mut BtcRpc,
+    rpc: &mut Rpc,
     status: BounceStatus,
     fee: &BtcAmount,
 ) -> LoopResult<bool> {
@@ -193,10 +193,9 @@ fn bounce(
     if let Some(row) = &row {
         let id: i32 = row.get(0);
         let bounced: Txid = sql_txid(row, 1);
-        let info = Info::Bounce { bounced };
-        let metadata = encode_info(&info);
+        let info = OutMetadata::Bounce { bounced };
 
-        match rpc.bounce(&bounced, fee, &metadata) {
+        match rpc.bounce(&bounced, fee, &info.encode()) {
             Ok(it) => {
                 fail_point("(injected) fail bounce", 0.3)?;
                 db.execute(
@@ -238,7 +237,7 @@ fn last_hash(db: &mut Client) -> Result<Option<BlockHash>, 
postgres::Error> {
 
 /// Parse new transactions, return true if the database is up to date with the 
latest mined block
 fn sync_chain(
-    rpc: &mut BtcRpc,
+    rpc: &mut Rpc,
     db: &mut Client,
     config: &BtcConfig,
     state: &WireState,
@@ -324,7 +323,7 @@ fn sync_chain(
 fn sync_chain_removed(
     txs: &HashMap<Txid, (Category, i32)>,
     removed: &HashSet<Txid>,
-    rpc: &mut BtcRpc,
+    rpc: &mut Rpc,
     db: &mut Client,
     min_confirmations: i32,
 ) -> LoopResult<bool> {
@@ -396,19 +395,19 @@ fn sync_chain_removed(
 fn sync_chain_outgoing(
     id: &Txid,
     confirmations: i32,
-    rpc: &mut BtcRpc,
+    rpc: &mut Rpc,
     db: &mut Client,
     config: &BtcConfig,
 ) -> LoopResult<()> {
     match rpc
         .get_tx_op_return(id)
-        .map(|(full, bytes)| (full, decode_info(&bytes)))
+        .map(|(full, bytes)| (full, OutMetadata::decode(&bytes)))
     {
         Ok((full, Ok(info))) => match info {
-            Info::Transaction { wtid, .. } => {
+            OutMetadata::Transaction { wtid, .. } => {
                 sync_chain_outgoing_send(id, &full, &wtid, rpc, db, 
confirmations, config)?
             }
-            Info::Bounce { bounced } => {
+            OutMetadata::Bounce { bounced } => {
                 sync_chain_outgoing_bounce(id, &bounced, db, confirmations)?
             }
         },
@@ -426,7 +425,7 @@ fn sync_chain_outgoing_send(
     id: &Txid,
     full: &TransactionFull,
     wtid: &[u8; 32],
-    rpc: &mut BtcRpc,
+    rpc: &mut Rpc,
     db: &mut Client,
     confirmations: i32,
     config: &BtcConfig,
@@ -600,7 +599,7 @@ fn sync_chain_outgoing_bounce(
 /// Sync database with na incoming confirmed transaction
 fn sync_chain_incoming_confirmed(
     id: &Txid,
-    rpc: &mut BtcRpc,
+    rpc: &mut Rpc,
     db: &mut Client,
 ) -> Result<(), LoopError> {
     match rpc.get_tx_segwit_key(id) {
diff --git a/btc-wire/src/main.rs b/btc-wire/src/main.rs
index 672295a..0325253 100644
--- a/btc-wire/src/main.rs
+++ b/btc-wire/src/main.rs
@@ -16,7 +16,7 @@
 use bitcoin::Network;
 use btc_wire::{
     config::{BitcoinConfig, WIRE_WALLET_NAME},
-    rpc::BtcRpc,
+    rpc::Rpc,
     rpc_utils::default_data_dir,
 };
 use reconnect::{AutoReconnectRPC, AutoReconnectSql};
@@ -29,7 +29,7 @@ use taler_common::{
 use crate::loops::{analysis::analysis, watcher::watcher, worker::worker};
 
 mod fail_point;
-mod info;
+mod metadata;
 mod loops;
 mod reconnect;
 mod sql;
@@ -72,7 +72,7 @@ fn main() {
         confirmation: AtomicU16::new(config.confirmation),
     }));
 
-    let mut rpc = BtcRpc::common(&btc_config).unwrap();
+    let mut rpc = Rpc::common(&btc_config).unwrap();
     rpc.load_wallet(WIRE_WALLET_NAME).ok();
     let rpc_watcher = AutoReconnectRPC::new(btc_config.clone(), 
WIRE_WALLET_NAME);
     let rpc_analysis = AutoReconnectRPC::new(btc_config.clone(), 
WIRE_WALLET_NAME);
diff --git a/btc-wire/src/info.rs b/btc-wire/src/metadata.rs
similarity index 51%
rename from btc-wire/src/info.rs
rename to btc-wire/src/metadata.rs
index 05d3159..43fd1c4 100644
--- a/btc-wire/src/info.rs
+++ b/btc-wire/src/metadata.rs
@@ -28,13 +28,11 @@ pub enum DecodeErr {
     UnexpectedEOF,
 }
 
-// TODO rename Info to OutMetadata to match eth_wire
-// TODO use a common url format for both
-// TODO generic metadata struct ?
+// TODO use a common url format with eth-wire
 
 /// Encoded metadata for outgoing transaction
 #[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Info {
+pub enum OutMetadata {
     Transaction { wtid: [u8; 32], url: Url },
     Bounce { bounced: Txid },
 }
@@ -42,49 +40,51 @@ pub enum Info {
 // We leave a potential special meaning for u8::MAX
 const BOUNCE_BYTE: u8 = u8::MAX - 1;
 
-pub fn encode_info(info: &Info) -> Vec<u8> {
-    let mut buffer = Vec::new();
-    match info {
-        Info::Transaction { wtid, url } => {
-            buffer.push(if url.scheme() == "http" { 1 } else { 0 });
-            buffer.extend_from_slice(wtid);
-            let parts = format!("{}{}", url.domain().unwrap_or(""), 
url.path());
-            let packed = uri_pack::pack_uri(&parts).unwrap();
-            buffer.extend_from_slice(&packed);
-            return buffer;
-        }
-        Info::Bounce { bounced: id } => {
-            buffer.push(BOUNCE_BYTE);
-            buffer.extend_from_slice(id.as_ref());
+impl OutMetadata {
+    pub fn encode(&self) -> Vec<u8> {
+        let mut buffer = Vec::new();
+        match self {
+            OutMetadata::Transaction { wtid, url } => {
+                buffer.push(if url.scheme() == "http" { 1 } else { 0 });
+                buffer.extend_from_slice(wtid);
+                let parts = format!("{}{}", url.domain().unwrap_or(""), 
url.path());
+                let packed = uri_pack::pack_uri(&parts).unwrap();
+                buffer.extend_from_slice(&packed);
+                return buffer;
+            }
+            OutMetadata::Bounce { bounced: id } => {
+                buffer.push(BOUNCE_BYTE);
+                buffer.extend_from_slice(id.as_ref());
+            }
         }
+        return buffer;
     }
-    return buffer;
-}
 
-pub fn decode_info(bytes: &[u8]) -> Result<Info, DecodeErr> {
-    if bytes.is_empty() {
-        return Err(DecodeErr::UnexpectedEOF);
-    }
-    match bytes[0] {
-        0..=1 => {
-            if bytes.len() < 33 {
-                return Err(DecodeErr::UnexpectedEOF);
+    pub fn decode(bytes: &[u8]) -> Result<Self, DecodeErr> {
+        if bytes.is_empty() {
+            return Err(DecodeErr::UnexpectedEOF);
+        }
+        match bytes[0] {
+            0..=1 => {
+                if bytes.len() < 33 {
+                    return Err(DecodeErr::UnexpectedEOF);
+                }
+                let packed = format!(
+                    "http{}://{}",
+                    if bytes[0] == 0 { "s" } else { "" },
+                    uri_pack::unpack_uri(&bytes[33..])?,
+                );
+                let url = Url::parse(&packed).unwrap();
+                Ok(OutMetadata::Transaction {
+                    wtid: bytes[1..33].try_into().unwrap(),
+                    url,
+                })
             }
-            let packed = format!(
-                "http{}://{}",
-                if bytes[0] == 0 { "s" } else { "" },
-                uri_pack::unpack_uri(&bytes[33..])?,
-            );
-            let url = Url::parse(&packed).unwrap();
-            Ok(Info::Transaction {
-                wtid: bytes[1..33].try_into().unwrap(),
-                url,
-            })
+            BOUNCE_BYTE => Ok(OutMetadata::Bounce {
+                bounced: Txid::from_slice(&bytes[1..])?,
+            }),
+            unknown => Err(DecodeErr::UnknownFirstByte(unknown)),
         }
-        BOUNCE_BYTE => Ok(Info::Bounce {
-            bounced: Txid::from_slice(&bytes[1..])?,
-        }),
-        unknown => Err(DecodeErr::UnknownFirstByte(unknown)),
     }
 }
 
@@ -93,7 +93,7 @@ mod test {
     use bitcoin::{hashes::Hash, Txid};
     use taler_common::{rand_slice, url::Url};
 
-    use crate::info::{decode_info, encode_info, Info};
+    use crate::metadata::OutMetadata;
 
     #[test]
     fn decode_encode_tx() {
@@ -106,9 +106,9 @@ mod test {
         for url in urls {
             let wtid = rand_slice();
             let url = Url::parse(url).unwrap();
-            let info = Info::Transaction { wtid, url };
-            let encode = encode_info(&info);
-            let decoded = decode_info(&encode).unwrap();
+            let info = OutMetadata::Transaction { wtid, url };
+            let encoded = info.encode();
+            let decoded = OutMetadata::decode(&encoded).unwrap();
             assert_eq!(decoded, info);
         }
     }
@@ -117,11 +117,11 @@ mod test {
     fn decode_encode_bounce() {
         for _ in 0..4 {
             let id: [u8; 32] = rand_slice();
-            let info = Info::Bounce {
+            let info = OutMetadata::Bounce {
                 bounced: Txid::from_slice(&id).unwrap(),
             };
-            let encode = encode_info(&info);
-            let decoded = decode_info(&encode).unwrap();
+            let encoded = info.encode();
+            let decoded = OutMetadata::decode(&encoded).unwrap();
             assert_eq!(decoded, info);
         }
     }
diff --git a/btc-wire/src/reconnect.rs b/btc-wire/src/reconnect.rs
index b2bdc79..a3f15fd 100644
--- a/btc-wire/src/reconnect.rs
+++ b/btc-wire/src/reconnect.rs
@@ -17,7 +17,7 @@
 
 use std::time::Duration;
 
-use btc_wire::{config::BitcoinConfig, rpc::BtcRpc};
+use btc_wire::{config::BitcoinConfig, rpc::Rpc};
 use taler_common::log::log::error;
 use taler_common::postgres::{Client, NoTls};
 
@@ -27,7 +27,7 @@ const RECONNECT_DELAY: Duration = Duration::from_secs(5);
 pub struct AutoReconnectRPC {
     config: BitcoinConfig,
     wallet: String,
-    client: BtcRpc,
+    client: Rpc,
 }
 
 impl AutoReconnectRPC {
@@ -41,9 +41,9 @@ impl AutoReconnectRPC {
     }
 
     /// Connect a new client, loop on error
-    fn connect(config: &BitcoinConfig, wallet: &str) -> BtcRpc {
+    fn connect(config: &BitcoinConfig, wallet: &str) -> Rpc {
         loop {
-            match BtcRpc::wallet(config, wallet) {
+            match Rpc::wallet(config, wallet) {
                 Ok(mut new) => match new.net_info() {
                     Ok(_) => return new,
                     Err(err) => {
@@ -60,7 +60,7 @@ impl AutoReconnectRPC {
     }
 
     /// Get a mutable connection, block until a connection can be established
-    pub fn client(&mut self) -> &mut BtcRpc {
+    pub fn client(&mut self) -> &mut Rpc {
         if self.client.net_info().is_err() {
             self.client = Self::connect(&self.config, &self.wallet);
         }
diff --git a/btc-wire/src/rpc.rs b/btc-wire/src/rpc.rs
index 4f204b8..9ef0ae4 100644
--- a/btc-wire/src/rpc.rs
+++ b/btc-wire/src/rpc.rs
@@ -79,7 +79,7 @@ pub type Result<T> = std::result::Result<T, Error>;
 const EMPTY: [(); 0] = [];
 
 /// Bitcoin RPC connection
-pub struct BtcRpc {
+pub struct Rpc {
     path: String,
     id: u64,
     cookie: String,
@@ -87,7 +87,7 @@ pub struct BtcRpc {
     buf: Vec<u8>,
 }
 
-impl BtcRpc {
+impl Rpc {
     /// Start a RPC connection
     pub fn common(config: &BitcoinConfig) -> io::Result<Self> {
         Self::new(config, None)
diff --git a/btc-wire/src/rpc_utils.rs b/btc-wire/src/rpc_utils.rs
index 876293e..335b526 100644
--- a/btc-wire/src/rpc_utils.rs
+++ b/btc-wire/src/rpc_utils.rs
@@ -17,7 +17,7 @@ use std::{path::PathBuf, str::FromStr};
 
 use bitcoin::{Address, Amount};
 
-use crate::rpc::{self, BtcRpc, TransactionFull};
+use crate::rpc::{self, Rpc, TransactionFull};
 
 pub const CLIENT: &str = "client";
 pub const WIRE: &str = "wire";
@@ -48,7 +48,7 @@ pub fn segwit_min_amount() -> Amount {
 }
 
 /// Get the first sender address from a raw transaction
-pub fn sender_address(rpc: &mut BtcRpc, full: &TransactionFull) -> 
rpc::Result<Address> {
+pub fn sender_address(rpc: &mut Rpc, full: &TransactionFull) -> 
rpc::Result<Address> {
     let first = &full.decoded.vin[0];
     let tx = rpc.get_raw(&first.txid.unwrap())?;
     Ok(tx
diff --git a/docs/presentation.tex b/docs/presentation.tex
index 3eea3d0..0d6cb8b 100644
--- a/docs/presentation.tex
+++ b/docs/presentation.tex
@@ -1,6 +1,9 @@
 \documentclass{beamer}
  
 \usepackage{tikz}
+\usepackage{ragged2e}
+
+\apptocmd{\frame}{}{\justifying}{}
 
 \usetikzlibrary{positioning,fit}
 
@@ -35,7 +38,7 @@
         \begin{itemize}
             \item \textbf{Delay} block and confirmation delay
             \item \textbf{Cost} transaction fees
-            \item \textbf{Scalability} limited amount of transaction per 
seconds
+            \item \textbf{Scalability} limited amount of transaction per second
             \item \textbf{Ecological impact} computation redundancy
             \item \textbf{Privacy}
         \end{itemize}
@@ -65,19 +68,21 @@
 
 
             \node[above= of 1](A){Auditor};
-            \draw[sym] (A) -- node [midway, right] {\tiny Audit} (1);
+            \draw[sym] (A) -- node [midway, right] {\tiny Verify} (1);
         \end{tikzpicture}
     \end{center}
 \end{frame}
 
-\begin{frame}{Taler}{Coins}
-    - Blind signatures
-    - Currency agnostic
-    - Change signature every year, Forget previous transactions (Pruning)
-    - Compatibility ?
+\begin{frame}{Taler}{Coins - WIP}
+    \begin{itemize}
+        \item Blind signatures
+        \item Currency agnostic
+        \item Change signature every year, Forget previous transactions 
(Pruning)
+        \item Compatibility ?
+    \end{itemize}
 \end{frame}
 
-\begin{frame}{Taler}{Off the chain transaction}
+\begin{frame}{Taler}{Off-chain transactions}
     \begin{center}
         \begin{tikzpicture}[
                 rect/.style={rectangle, draw=black, minimum width=28mm},
@@ -129,9 +134,9 @@
 
 \begin{frame}{Depolymerization}{Metadata}
     \begin{itemize}
-        \item Metadata are stored alongside depolymerizer on-chain transactions
-        \item The whole transaction history can be retrieved from the 
blockchain
-        \item Easily auditable
+        \item Metadata are stored in depolymerizer on-chain transactions
+        \item The whole on-chain transaction history can be retrieved from the 
blockchain
+        \item \textbf{Easily auditable}
     \end{itemize}
 \end{frame}
 
@@ -151,6 +156,8 @@
             \draw[sym] (2) -- node [midway,above] {\tiny SQL} (3);
             \draw[sym] (3) -- node [midway,above] {\tiny SQL} (4);
             \draw[sym] (4) -- node [midway,left ] {\tiny RPC} (5);
+
+
         \end{tikzpicture}
     \end{center}
     Two processes sharing a common database for state and communication.
@@ -158,9 +165,9 @@
     every supported currency.
 \end{frame}
 
-\section{btc\_wire}
+\section{btc-wire}
 
-\begin{frame}{btc\_wire}{Architecture}
+\begin{frame}{btc-wire}{Architecture}
     \begin{center}
         \begin{tikzpicture}[
                 rect/.style={rectangle, draw=black, minimum height=6mm, 
minimum width=38mm},
@@ -182,7 +189,7 @@
 
             % Worker loop
             \node[rect, below right= -2mm and 1cm of wa1](wo1) {Wait for 
notification};
-            \node[rect, below=4mm of wo1](wo2) {Synchronize};
+            \node[rect, below=4mm of wo1](wo2) {Synchronize chain};
             \node[rect, below=4mm of wo2](wo3) {Send};
             \node[rect, below=4mm of wo3](wo4) {Bounce};
             \node[above=1mm of wo1]{Worker};
@@ -196,25 +203,25 @@
     Three concurrent loops
 \end{frame}
 
-\begin{frame}{btc\_wire}{Metadata}
-    \begin{block}{Deposit}
+\begin{frame}{btc-wire}{Metadata}
+    \begin{block}{Withdraw}
         \begin{itemize}
-            \item Transaction from common wallet software
-            \item Only 32B
-            \item \textbf{Fake Segwit Addresses}
+            \item Transaction from code
+            \item Only 32B + URI
+            \item \textbf{OP\_RETURN}
         \end{itemize}
     \end{block}
     \begin{block}{Deposit}
         \begin{itemize}
-            \item Transaction from code
-            \item Only 32B + URI
-            \item \textbf{OP\_RETURN}
+            \item Transaction from common wallet software
+            \item Only 32B
+            \item \textbf{Fake Segwit Addresses}
         \end{itemize}
     \end{block}
 \end{frame}
 
 
-\begin{frame}{btc\_wire}{Security features}
+\begin{frame}{btc-wire}{Security features}
     \begin{itemize}
         \item Reorg resilient
         \item Adaptive confirmation
@@ -222,7 +229,7 @@
     \end{itemize}
 \end{frame}
 
-\begin{frame}{btc\_wire}{Reorg resilient}
+\begin{frame}{btc-wire}{Reorg resilient}
     \begin{center}
         \begin{tikzpicture}[
                 block/.style={rectangle,draw=black,fill=black!10,minimum 
size=7mm},
@@ -276,21 +283,21 @@
             \node [right=17mm of 6]{\emph{active}};
         \end{tikzpicture}
     \end{center}
-    \only<1>{A fork is when concurrent blockchain state coexists. Node will 
follow the
-        longest chain replacing recent blocks if necessary. This is a 
blockchain
-        reorganisation. In Taler deposit transaction are expected to be
-        consistent, if a deposit transaction disappear from the blockchain
-        btc\_wire is comprised.}
-    \only<2>{As small forks are common, we apply a confirmation delay to handle
-        the most common disturbances and attack.}
-    \only<3>{If a reorganisation bigger than the confirmation delay happen,
-        but no deposit transaction are removed btc\_wire is safe.}
-    \only<4>{If a confirmed deposit transaction has been removed, it is
-        possible for a powerful attacker to have created a conflicting 
transaction. btc\_wire
-        stop functioning until lost deposit transactions reappeared.}
+    \only<1>{A fork is when concurrent blockchain states coexist. Nodes will
+        follow the longest chain, replacing recent blocks if necessary. That 
is a
+        blockchain reorganization. Taler expects deposit transactions to be
+        consistent. If a deposit transaction disappears from the blockchain 
btc-wire
+        is comprised.}
+    \only<2>{As small forks are common, we apply a confirmation delay to
+        handle the most common disturbances and attacks.}
+    \only<3>{If a reorganization longer than the confirmation delay happens,
+        but it does not remove deposits, btc-wire is safe.}
+    \only<4>{If it removed a confirmed deposit a powerful attacker may have
+        created a conflicting transaction. btc-wire suspends operation until
+        lost deposits reappear.}
 \end{frame}
 
-\begin{frame}{btc\_wire}{Adaptive confirmation}
+\begin{frame}{btc-wire}{Adaptive confirmation}
     \begin{center}
         \begin{tikzpicture}[
                 block/.style={rectangle,draw=black,fill=black!10,minimum 
size=7mm},
@@ -306,7 +313,6 @@
             \draw[->] (1) -- (2);
 
             % Current
-
             \node[block,conf,right=5mm of 2](3){};
             \node[block,right=5mm of 3](4){};
             \node[block,right=5mm of 4](5){};
@@ -345,13 +351,12 @@
         \end{tikzpicture}
     \end{center}
     If we experience a reorganisation once, its plausible for another one of 
the
-    same size to happen again. We update the confirmation time, learning from
-    previous disturbances.
+    same size to happen again. btc-wire learns from reorganizations by updating
+    its confirmation time.
 \end{frame}
 
 
-\begin{frame}{btc\_wire}{Handle stuck transactions}
-    \only<1>{We want transactions to be confirmed in a bounded time period}
+\begin{frame}{btc-wire}{Handle stuck transactions}
     \begin{center}
         \begin{tikzpicture}[
                 dot/.style={circle,fill,inner sep=1pt,}
@@ -381,11 +386,12 @@
             };
         \end{tikzpicture}
     \end{center}
-    \only<1>{However, transaction fees are variable and can only be predicted}
-    \only<2>{When a transaction is sent with a fee too small compared to other 
transaction,
-        it can take an unlimited amount of time for this transaction to be 
mined}
-    \only<3>{We monitor pending transaction and bump their fee if they take 
too muck time to be mined}
-
+    \only<1>{We want confirmation of transactions within a limited time frame.
+        However, transaction fees are variable, and we can only predict them.}
+    \only<2>{When we send a transaction with a fee too small compared to other
+        transactions, it can take an unlimited amount of time for it to be 
mined.}
+    \only<3>{You can configure btc-wire to monitor pending transactions and
+        bump their fees if they take too much time to be mined.}
 \end{frame}
 
 
@@ -414,7 +420,7 @@
         \item [$+$] Scalability, close to 100k txs per second
         \item [$+$] Ecological
         \item [$+$] Privacy when it can, transparency when it must (avoid tax 
evasion and money laundering)
-        \item [$+$] Currency agnostic
+        \item [$+$] Currency agnostic (payment system)
     \end{itemize}
 \end{frame}
 \end{document}
\ No newline at end of file
diff --git a/eth-wire/src/bin/eth-test.rs b/eth-wire/src/bin/eth-test.rs
deleted file mode 100644
index c979257..0000000
--- a/eth-wire/src/bin/eth-test.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2022 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU Affero General Public License as published by the Free 
Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  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 Affero General Public License for more 
details.
-
-  You should have received a copy of the GNU Affero General Public License 
along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-use std::{panic::AssertUnwindSafe, str::FromStr};
-
-use eth_wire::{
-    metadata::{InMetadata, OutMetadata},
-    rpc::{self, Rpc},
-};
-use ethereum_types::{H256, U256};
-use taler_common::{config::load_eth_config, rand_slice, url::Url};
-
-pub fn main() {
-    let path = std::env::args().nth(1).unwrap();
-    let config = load_eth_config(path);
-    let mut rpc = 
Rpc::new(config.core.data_dir.unwrap().join("geth.ipc")).unwrap();
-
-    let accounts = rpc.list_accounts().unwrap();
-    for account in &accounts {
-        rpc.unlock_account(&account, "password").unwrap();
-    }
-    let wire = accounts[0];
-    let client = accounts[1];
-    let reserve = accounts[2];
-
-    let test_value = U256::from(15000u32);
-    let bounce_value = U256::from(10000u32);
-    let test_url = Url::from_str("http://test.com";).unwrap();
-
-    let mut runner = TestRunner::new();
-
-    runner.test("Deposit", || {
-        let rng = rand_slice();
-        let hash = rpc.deposit(client, wire, test_value, rng).unwrap();
-        assert!(tx_pending(&mut rpc, &hash).unwrap());
-        mine_pending(&mut rpc).unwrap();
-        assert!(!tx_pending(&mut rpc, &hash).unwrap());
-        let tx = rpc.get_transaction(&hash).unwrap().unwrap();
-        let metadata = InMetadata::decode(&tx.input).unwrap();
-        assert!(matches!(metadata, InMetadata::Deposit { reserve_pub } if 
reserve_pub == rng));
-        assert_eq!(tx.value, test_value);
-    });
-
-    runner.test("Withdraw", || {
-        let rng = rand_slice();
-        let hash = rpc
-            .withdraw(wire, client, test_value, rng, test_url.clone())
-            .unwrap();
-        assert!(tx_pending(&mut rpc, &hash).unwrap());
-        mine_pending(&mut rpc).unwrap();
-        assert!(!tx_pending(&mut rpc, &hash).unwrap());
-        let tx = rpc.get_transaction(&hash).unwrap().unwrap();
-        let metadata = OutMetadata::decode(&tx.input).unwrap();
-        assert!(
-            matches!(metadata, OutMetadata::Withdraw { wtid, url } if wtid == 
rng && url == url)
-        );
-        assert_eq!(tx.value, test_value);
-    });
-
-    runner.test("Bounce", || {
-        let rng = rand_slice();
-        let deposit = rpc.deposit(client, wire, test_value, rng).unwrap();
-        let hash = rpc.bounce(deposit, bounce_value).unwrap();
-        assert!(tx_pending(&mut rpc, &hash).unwrap());
-        mine_pending(&mut rpc).unwrap();
-        assert!(!tx_pending(&mut rpc, &hash).unwrap());
-        let tx = rpc.get_transaction(&hash).unwrap().unwrap();
-        let metadata = OutMetadata::decode(&tx.input).unwrap();
-        assert!(matches!(metadata, OutMetadata::Bounce { bounced } if bounced 
== deposit));
-        assert_eq!(tx.value, test_value - bounce_value);
-    });
-
-    runner.conclude();
-}
-
-/// Check a specific transaction is pending
-fn tx_pending(rpc: &mut Rpc, id: &H256) -> rpc::Result<bool> {
-    Ok(rpc.pending_transactions()?.iter().any(|t| t.hash == *id))
-}
-
-/// Mine pending transactions
-fn mine_pending(rpc: &mut Rpc) -> rpc::Result<()> {
-    let mut notifier = rpc.subscribe_new_head()?;
-    rpc.miner_start()?;
-    while !rpc.pending_transactions()?.is_empty() {
-        notifier.next()?;
-    }
-    rpc.miner_stop()?;
-    Ok(())
-}
-
-/// Run test track success and errors
-struct TestRunner {
-    nb_ok: usize,
-    nb_err: usize,
-}
-
-impl TestRunner {
-    fn new() -> Self {
-        Self {
-            nb_err: 0,
-            nb_ok: 0,
-        }
-    }
-
-    fn test(&mut self, name: &str, test: impl FnOnce()) {
-        println!("{}", name);
-
-        let result = std::panic::catch_unwind(AssertUnwindSafe(test));
-        if result.is_ok() {
-            println!("OK");
-            self.nb_ok += 1;
-        } else {
-            println!("ERR");
-            self.nb_err += 1;
-        }
-    }
-
-    /// Wait for tests completion and print results
-    fn conclude(self) {
-        println!(
-            "Result for {} tests: {} ok and {} err",
-            self.nb_ok + self.nb_err,
-            self.nb_ok,
-            self.nb_err
-        );
-    }
-}
diff --git a/taler-common/src/lib.rs b/eth-wire/src/loops.rs
similarity index 66%
copy from taler-common/src/lib.rs
copy to eth-wire/src/loops.rs
index 8bdf0ec..6bcc715 100644
--- a/taler-common/src/lib.rs
+++ b/eth-wire/src/loops.rs
@@ -1,4 +1,3 @@
-use rand::{rngs::OsRng, RngCore};
 /*
   This file is part of TALER
   Copyright (C) 2022 Taler Systems SA
@@ -14,20 +13,6 @@ use rand::{rngs::OsRng, RngCore};
   You should have received a copy of the GNU Affero General Public License 
along with
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
-pub use postgres;
-pub use rand;
-pub use url;
 
-pub mod api_common;
-pub mod api_wire;
-pub mod config;
-pub mod error_codes;
-pub mod log;
-pub mod sql;
-
-/// Secure random slice generator using getrandom
-pub fn rand_slice<const N: usize>() -> [u8; N] {
-    let mut slice = [0; N];
-    OsRng.fill_bytes(slice.as_mut_slice());
-    slice
-}
+pub mod watcher;
+pub mod worker;
diff --git a/taler-common/src/lib.rs b/eth-wire/src/loops/watcher.rs
similarity index 66%
copy from taler-common/src/lib.rs
copy to eth-wire/src/loops/watcher.rs
index 8bdf0ec..79f03ab 100644
--- a/taler-common/src/lib.rs
+++ b/eth-wire/src/loops/watcher.rs
@@ -1,4 +1,3 @@
-use rand::{rngs::OsRng, RngCore};
 /*
   This file is part of TALER
   Copyright (C) 2022 Taler Systems SA
@@ -14,20 +13,13 @@ use rand::{rngs::OsRng, RngCore};
   You should have received a copy of the GNU Affero General Public License 
along with
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
-pub use postgres;
-pub use rand;
-pub use url;
+use eth_wire::rpc::Rpc;
+use taler_common::postgres::Client;
 
-pub mod api_common;
-pub mod api_wire;
-pub mod config;
-pub mod error_codes;
-pub mod log;
-pub mod sql;
-
-/// Secure random slice generator using getrandom
-pub fn rand_slice<const N: usize>() -> [u8; N] {
-    let mut slice = [0; N];
-    OsRng.fill_bytes(slice.as_mut_slice());
-    slice
+pub fn watcher(mut rpc: Rpc, mut db: Client) {
+    let mut notifier = rpc.subscribe_new_head().unwrap();
+    loop {
+        db.execute("NOTIFY new_block", &[]).unwrap();
+        notifier.next().unwrap();
+    }
 }
diff --git a/eth-wire/src/loops/worker.rs b/eth-wire/src/loops/worker.rs
new file mode 100644
index 0000000..8c2d74b
--- /dev/null
+++ b/eth-wire/src/loops/worker.rs
@@ -0,0 +1,150 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2022 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Affero General Public License as published by the Free 
Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 Affero General Public License for more 
details.
+
+  You should have received a copy of the GNU Affero General Public License 
along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+use std::time::SystemTime;
+
+use eth_wire::{
+    metadata::InMetadata,
+    rpc::Rpc,
+    taler_util::{eth_payto_url, eth_to_taler},
+    BlockState,
+};
+use taler_common::{
+    api_common::base32,
+    log::log::{error, info},
+    postgres::{fallible_iterator::FallibleIterator, Client},
+    sql::{sql_array, sql_url},
+};
+
+use crate::{
+    sql::{sql_addr, sql_eth_amount},
+    status::TxStatus,
+    LoopResult, WireState,
+};
+
+pub fn worker(mut rpc: Rpc, mut db: Client, state: &WireState) {
+    let mut skip_notification = false;
+    loop {
+        let result: LoopResult<()> = (|| {
+            // Listen to all channels
+            db.batch_execute("LISTEN new_block; LISTEN new_tx")?;
+            // Wait for the next notification
+            {
+                let mut ntf = db.notifications();
+                if !skip_notification && ntf.is_empty() {
+                    // Block until next notification
+                    ntf.blocking_iter().next()?;
+                }
+                // Conflate all notifications
+                let mut iter = ntf.iter();
+                while iter.next()?.is_some() {}
+            }
+
+            sync_chain(&mut rpc, &mut db, state)?;
+
+            while send(&mut db, &mut rpc, state)? {}
+            Ok(())
+        })();
+
+        if let Err(e) = result {
+            error!("worker: {}", e);
+            skip_notification = false;
+        } else {
+            skip_notification = false;
+        }
+    }
+}
+
+fn sync_chain(rpc: &mut Rpc, db: &mut Client, state: &WireState) -> 
LoopResult<bool> {
+    let row = db.query_one("SELECT value FROM state WHERE name='last_block'", 
&[])?;
+    let slice: &[u8] = row.get(0);
+    let block = BlockState::from_bytes(slice.try_into().unwrap());
+
+    let mut txs = Vec::new();
+
+    txs.extend(rpc.pending_transactions()?.into_iter().map(|t| (t, 0)));
+
+    let mut cursor = rpc.current_block()?;
+    let mut confirmation = 1;
+
+    // TODO check hash to detect reorg
+
+    while cursor.number.expect("Mined block") != block.number {
+        txs.extend(cursor.transactions.drain(..).map(|t| (t, confirmation)));
+        cursor = rpc.block(cursor.number.unwrap() - 1u64)?.unwrap();
+        confirmation += 1;
+    }
+
+    for (tx, _confirmation) in txs {
+        if tx.to == Some(state.address) {
+            let metadata = InMetadata::decode(&tx.input).unwrap();
+            match metadata {
+                InMetadata::Deposit { reserve_pub } => {
+                    let date = SystemTime::now();
+                    let amount = eth_to_taler(&tx.value);
+                    let credit_addr = tx.from.expect("Not coinbase");
+                    let nb = db.execute("INSERT INTO tx_in (_date, amount, 
reserve_pub, debit_acc, credit_acc) VALUES ($1, $2, $3, $4, $5) ON CONFLICT 
(reserve_pub) DO NOTHING ", &[
+                &date, &amount.to_string(), &reserve_pub.as_ref(), 
&eth_payto_url(&credit_addr).as_ref(), &state.config.payto.as_ref()
+            ])?;
+                    if nb > 0 {
+                        info!(
+                            "<< {} {} in {} from {}",
+                            amount,
+                            base32(&reserve_pub),
+                            hex::encode(tx.hash),
+                            hex::encode(credit_addr),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    Ok(true)
+}
+
+/// Send a transaction on the blockchain, return true if more transactions 
with the same status remains
+fn send(db: &mut Client, rpc: &mut Rpc, state: &WireState) -> LoopResult<bool> 
{
+    // We rely on the advisory lock to ensure we are the only one sending 
transactions
+    let row = db.query_opt(
+"SELECT id, amount, wtid, credit_acc, exchange_url FROM tx_out WHERE status=$1 
ORDER BY _date LIMIT 1",
+&[&(TxStatus::Requested as i16)],
+)?;
+    if let Some(row) = &row {
+        let id: i32 = row.get(0);
+        let amount = sql_eth_amount(row, 1);
+        let wtid: [u8; 32] = sql_array(row, 2);
+        let addr = sql_addr(row, 3);
+        let url = sql_url(row, 4);
+        match rpc.withdraw(state.address, addr, amount, wtid, url) {
+            Ok(tx_id) => {
+                db.execute(
+                    "UPDATE tx_out SET status=$1, txid=$2 WHERE id=$3",
+                    &[&(TxStatus::Sent as i16), &tx_id.as_ref(), &id],
+                )?;
+                let amount = eth_to_taler(&amount);
+                info!(">> {} {} in {} to {}", amount, base32(&wtid), tx_id, 
addr);
+            }
+            Err(e) => {
+                db.execute(
+                    "UPDATE tx_out SET status=$1 WHERE id=$2",
+                    &[&(TxStatus::Delayed as i16), &id],
+                )?;
+                Err(e)?;
+            }
+        }
+    }
+    Ok(row.is_some())
+}
diff --git a/eth-wire/src/main.rs b/eth-wire/src/main.rs
index 7005713..324041d 100644
--- a/eth-wire/src/main.rs
+++ b/eth-wire/src/main.rs
@@ -28,6 +28,8 @@ use taler_common::{
 };
 
 mod status;
+mod sql;
+mod loops;
 
 pub struct WireState {
     confirmation: AtomicU16,
@@ -49,188 +51,6 @@ pub enum LoopError {
 
 pub type LoopResult<T> = Result<T, LoopError>;
 
-mod sql {
-    use eth_wire::taler_util::{eth_payto_addr, taler_to_eth};
-    use ethereum_types::{H160, U256};
-    use taler_common::{
-        postgres::Row,
-        sql::{sql_amount, sql_url},
-    };
-
-    pub fn sql_eth_amount(row: &Row, idx: usize) -> U256 {
-        let amount = sql_amount(row, idx);
-        taler_to_eth(&amount).unwrap_or_else(|_| {
-            panic!(
-                "Database invariant: expected an ethereum amount got {}",
-                amount
-            )
-        })
-    }
-
-    pub fn sql_addr(row: &Row, idx: usize) -> H160 {
-        let url = sql_url(row, idx);
-        eth_payto_addr(&url).unwrap_or_else(|_| {
-            panic!(
-                "Database invariant: expected an ethereum payto url got {}",
-                url
-            )
-        })
-    }
-}
-
-mod loops {
-    pub mod watcher {
-        use eth_wire::rpc::Rpc;
-        use taler_common::postgres::Client;
-
-        pub fn watcher(mut rpc: Rpc, mut db: Client) {
-            let mut notifier = rpc.subscribe_new_head().unwrap();
-            loop {
-                db.execute("NOTIFY new_block", &[]).unwrap();
-                notifier.next().unwrap();
-            }
-        }
-    }
-
-    pub mod worker {
-        use std::time::SystemTime;
-
-        use eth_wire::{
-            metadata::InMetadata,
-            rpc::Rpc,
-            taler_util::{eth_payto_url, eth_to_taler},
-            BlockState,
-        };
-        use taler_common::{
-            api_common::base32,
-            log::log::{error, info},
-            postgres::{fallible_iterator::FallibleIterator, Client},
-            sql::{sql_array, sql_url},
-        };
-
-        use crate::{
-            sql::{sql_addr, sql_eth_amount},
-            status::TxStatus,
-            LoopResult, WireState,
-        };
-
-        pub fn worker(mut rpc: Rpc, mut db: Client, state: &WireState) {
-            let mut skip_notification = false;
-            loop {
-                let result: LoopResult<()> = (|| {
-                    // Listen to all channels
-                    db.batch_execute("LISTEN new_block; LISTEN new_tx")?;
-                    // Wait for the next notification
-                    {
-                        let mut ntf = db.notifications();
-                        if !skip_notification && ntf.is_empty() {
-                            // Block until next notification
-                            ntf.blocking_iter().next()?;
-                        }
-                        // Conflate all notifications
-                        let mut iter = ntf.iter();
-                        while iter.next()?.is_some() {}
-                    }
-
-                    sync_chain(&mut rpc, &mut db, state)?;
-
-                    while send(&mut db, &mut rpc, state)? {}
-                    Ok(())
-                })();
-
-                if let Err(e) = result {
-                    error!("worker: {}", e);
-                    skip_notification = false;
-                } else {
-                    skip_notification = false;
-                }
-            }
-        }
-
-        fn sync_chain(rpc: &mut Rpc, db: &mut Client, state: &WireState) -> 
LoopResult<bool> {
-            let row = db.query_one("SELECT value FROM state WHERE 
name='last_block'", &[])?;
-            let slice: &[u8] = row.get(0);
-            let block = BlockState::from_bytes(slice.try_into().unwrap());
-
-            let mut txs = Vec::new();
-
-            txs.extend(rpc.pending_transactions()?.into_iter().map(|t| (t, 
0)));
-
-            let mut cursor = rpc.current_block()?;
-            let mut confirmation = 1;
-
-            // TODO check hash to detect reorg
-
-            while cursor.number.expect("Mined block") != block.number {
-                txs.extend(cursor.transactions.drain(..).map(|t| (t, 
confirmation)));
-                cursor = rpc.block(cursor.number.unwrap() - 1u64)?.unwrap();
-                confirmation += 1;
-            }
-
-            for (tx, _confirmation) in txs {
-                if tx.to == Some(state.address) {
-                    let metadata = InMetadata::decode(&tx.input).unwrap();
-                    match metadata {
-                        InMetadata::Deposit { reserve_pub } => {
-                            let date = SystemTime::now();
-                            let amount = eth_to_taler(&tx.value);
-                            let credit_addr = tx.from.expect("Not coinbase");
-                            let nb = db.execute("INSERT INTO tx_in (_date, 
amount, reserve_pub, debit_acc, credit_acc) VALUES ($1, $2, $3, $4, $5) ON 
CONFLICT (reserve_pub) DO NOTHING ", &[
-                        &date, &amount.to_string(), &reserve_pub.as_ref(), 
&eth_payto_url(&credit_addr).as_ref(), &state.config.payto.as_ref()
-                    ])?;
-                            if nb > 0 {
-                                info!(
-                                    "<< {} {} in {} from {}",
-                                    amount,
-                                    base32(&reserve_pub),
-                                    hex::encode(tx.hash),
-                                    hex::encode(credit_addr),
-                                );
-                            }
-                        }
-                    }
-                }
-            }
-
-            Ok(true)
-        }
-
-        /// Send a transaction on the blockchain, return true if more 
transactions with the same status remains
-        fn send(db: &mut Client, rpc: &mut Rpc, state: &WireState) -> 
LoopResult<bool> {
-            // We rely on the advisory lock to ensure we are the only one 
sending transactions
-            let row = db.query_opt(
-        "SELECT id, amount, wtid, credit_acc, exchange_url FROM tx_out WHERE 
status=$1 ORDER BY _date LIMIT 1",
-        &[&(TxStatus::Requested as i16)],
-    )?;
-            if let Some(row) = &row {
-                let id: i32 = row.get(0);
-                let amount = sql_eth_amount(row, 1);
-                let wtid: [u8; 32] = sql_array(row, 2);
-                let addr = sql_addr(row, 3);
-                let url = sql_url(row, 4);
-                match rpc.withdraw(state.address, addr, amount, wtid, url) {
-                    Ok(tx_id) => {
-                        db.execute(
-                            "UPDATE tx_out SET status=$1, txid=$2 WHERE id=$3",
-                            &[&(TxStatus::Sent as i16), &tx_id.as_ref(), &id],
-                        )?;
-                        let amount = eth_to_taler(&amount);
-                        info!(">> {} {} in {} to {}", amount, base32(&wtid), 
tx_id, addr);
-                    }
-                    Err(e) => {
-                        db.execute(
-                            "UPDATE tx_out SET status=$1 WHERE id=$2",
-                            &[&(TxStatus::Delayed as i16), &id],
-                        )?;
-                        Err(e)?;
-                    }
-                }
-            }
-            Ok(row.is_some())
-        }
-    }
-}
-
 fn main() {
     taler_common::log::init();
 
diff --git a/eth-wire/src/rpc.rs b/eth-wire/src/rpc.rs
index f5c7fc6..1581bbb 100644
--- a/eth-wire/src/rpc.rs
+++ b/eth-wire/src/rpc.rs
@@ -131,7 +131,7 @@ impl Rpc {
                             }
                             Err(err) if err.classify() == Category::Eof => {
                                 if nb == 0 {
-                                    return Err(std::io::Error::new(
+                                    Err(std::io::Error::new(
                                         ErrorKind::UnexpectedEof,
                                         "Stream EOF",
                                     ))?;
diff --git a/btc-wire/src/sql.rs b/eth-wire/src/sql.rs
similarity index 51%
copy from btc-wire/src/sql.rs
copy to eth-wire/src/sql.rs
index edcfcf3..fe7af54 100644
--- a/btc-wire/src/sql.rs
+++ b/eth-wire/src/sql.rs
@@ -13,39 +13,29 @@
   You should have received a copy of the GNU Affero General Public License 
along with
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
-
-use bitcoin::{hashes::Hash, Address, Amount as BtcAmount, Txid};
-use taler_common::postgres::Row;
-use taler_common::sql::{sql_amount, sql_url};
-
-use crate::taler_util::{btc_payto_addr, taler_to_btc};
-
-pub fn sql_btc_amount(row: &Row, idx: usize) -> BtcAmount {
+use eth_wire::taler_util::{eth_payto_addr, taler_to_eth};
+use ethereum_types::{H160, U256};
+use taler_common::{
+    postgres::Row,
+    sql::{sql_amount, sql_url},
+};
+
+pub fn sql_eth_amount(row: &Row, idx: usize) -> U256 {
     let amount = sql_amount(row, idx);
-    taler_to_btc(&amount).unwrap_or_else(|_| {
+    taler_to_eth(&amount).unwrap_or_else(|_| {
         panic!(
-            "Database invariant: expected an bitcoin amount got {}",
+            "Database invariant: expected an ethereum amount got {}",
             amount
         )
     })
 }
 
-pub fn sql_addr(row: &Row, idx: usize) -> Address {
+pub fn sql_addr(row: &Row, idx: usize) -> H160 {
     let url = sql_url(row, idx);
-    btc_payto_addr(&url).unwrap_or_else(|_| {
+    eth_payto_addr(&url).unwrap_or_else(|_| {
         panic!(
-            "Database invariant: expected an bitcoin payto url got {}",
+            "Database invariant: expected an ethereum payto url got {}",
             url
         )
     })
 }
-
-pub fn sql_txid(row: &Row, idx: usize) -> Txid {
-    let slice: &[u8] = row.get(idx);
-    Txid::from_slice(slice).unwrap_or_else(|_| {
-        panic!(
-            "Database invariant: expected a transaction if got an array of 
{}B",
-            slice.len()
-        )
-    })
-}
diff --git a/eth-wire/src/taler_util.rs b/eth-wire/src/taler_util.rs
index 40c8fff..f755ce3 100644
--- a/eth-wire/src/taler_util.rs
+++ b/eth-wire/src/taler_util.rs
@@ -1,3 +1,18 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2022 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Affero General Public License as published by the Free 
Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  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 Affero General Public License for more 
details.
+
+  You should have received a copy of the GNU Affero General Public License 
along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
 use std::str::FromStr;
 
 use ethereum_types::{Address, U256};
diff --git a/taler-common/src/config.rs b/taler-common/src/config.rs
index 5f5d008..0aefa35 100644
--- a/taler-common/src/config.rs
+++ b/taler-common/src/config.rs
@@ -25,7 +25,7 @@ pub trait Config: Sized {
     fn load_from_file(config_file: impl AsRef<Path>) -> Self {
         let conf = ini::Ini::load_from_file(config_file).expect("Failed to 
open the config file");
         let taler = section(&conf, "taler");
-        let currency = require(&taler, "CURRENCY", string);
+        let currency = require(taler, "CURRENCY", string);
         let section_name = match currency.as_str() {
             "BTC" => "depolymerizer-bitcoin",
             "ETH" => "depolymerizer-ethereum",

-- 
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]