at master 5.0 kB view raw
1{ 2 lib, 3 pkgs, 4 nodes, 5 ... 6}: 7 8let 9 cfgNodes = pkgs.callPackage ./nodes.nix { inherit lib; }; 10 bankConfig = nodes.bank.environment.etc."libeufin/libeufin.conf".source; 11 12 inherit (cfgNodes) CURRENCY FIAT_CURRENCY; 13in 14{ 15 commonScripts = 16 # python 17 '' 18 def succeed(machine, commands): 19 """A more convenient `machine.succeed` that supports multi-line inputs""" 20 flattened_commands = [c.replace("\n", "") for c in commands] # flatten multi-line 21 return machine.succeed(" ".join(flattened_commands)) 22 23 24 def systemd_run(machine, cmd, user="nobody", group="nobody"): 25 """Execute command as a systemd DynamicUser""" 26 machine.log(f"Executing command (via systemd-run): \"{cmd}\"") 27 28 (status, out) = machine.execute( " ".join([ 29 "systemd-run", 30 "--service-type=exec", 31 "--quiet", 32 "--wait", 33 "-E PATH=\"$PATH\"", 34 "-p StandardOutput=journal", 35 "-p StandardError=journal", 36 "-p DynamicUser=yes", 37 f"-p Group={group}" if group != "nobody" else "", 38 f"-p User={user}" if user != "nobody" else "", 39 f"$SHELL -c '{cmd}'" 40 ]) ) 41 42 if status != 0: 43 raise Exception(f"systemd_run failed (status {status})") 44 45 machine.log("systemd-run finished successfully") 46 47 48 def register_bank_account(username, password, name, is_exchange=False): 49 """Register Libeufin bank account for the x-taler-bank wire method""" 50 return systemd_run(bank, " ".join([ 51 'libeufin-bank', 52 'create-account', 53 '-c ${bankConfig}', 54 f'--username {username}', 55 f'--password {password}', 56 f'--name {name}', 57 f'--payto_uri="payto://x-taler-bank/bank:8082/{username}?receiver-name={name}"', 58 '--exchange' if (is_exchange or username.lower()=="exchange") else ' ' 59 ]), 60 user="libeufin-bank") 61 62 63 def wallet_cli(command): 64 """Wrapper for the Taler CLI wallet""" 65 return client.succeed( 66 "taler-wallet-cli " 67 "--no-throttle " # don't do any request throttling 68 + command 69 ) 70 71 # https://docs.taler.net/core/api-corebank.html#authentication 72 def create_token(machine, username, password): 73 """Create a read-write bank access token for a user""" 74 response = succeed(machine, [ 75 "curl -X POST", 76 f"-u {username}:{password}", 77 "-H 'Content-Type: application/json'", 78 """ 79 --data '{ "scope": "readwrite" }' 80 """, 81 f"-sSfL 'http://bank:8082/accounts/{username}/token'" 82 ]) 83 return json.loads(response)["access_token"] 84 85 86 # Basic auth is deprecated, so exchange credentials must be set at 87 # runtime because it requires a token from the bank. 88 def create_exchange_auth(token: str): 89 template = f""" 90 [exchange-accountcredentials-test] 91 WIRE_GATEWAY_URL = http://bank:8082/accounts/exchange/taler-wire-gateway/ 92 WIRE_GATEWAY_AUTH_METHOD = BEARER 93 TOKEN = "{token}" 94 """ 95 return "\n".join([line.strip() for line in template.splitlines()]) 96 97 def verify_balance(balanceWanted: str): 98 """Compare Taler CLI wallet balance with expected amount""" 99 balance = wallet_cli("balance --json") 100 try: 101 balanceGot = json.loads(balance)["balances"][0]["available"] 102 except: 103 balanceGot = "${CURRENCY}:0" 104 105 # Compare balance with expected value 106 if balanceGot != balanceWanted: 107 client.fail(f'echo Wanted balance: "{balanceWanted}", got: "{balanceGot}"') 108 else: 109 client.succeed(f"echo Withdraw successfully made. New balance: {balanceWanted}") 110 111 112 def verify_conversion(regionalWanted: str, accessToken: str): 113 """Compare converted Libeufin Nexus funds with expected regional currency""" 114 # Get transaction details 115 response = json.loads( 116 succeed(bank, [ 117 "curl -sSfL", 118 f"-H 'Authorization: Bearer {accessToken}'", 119 # TODO: get exchange from config? 120 "http://bank:8082/accounts/exchange/transactions" 121 ]) 122 ) 123 amount = response["transactions"][0]["amount"].split(":") # CURRENCY:VALUE 124 currencyGot, regionalGot = amount 125 126 # Check conversion (1:1 ratio) 127 if (regionalGot != regionalWanted) or (currencyGot != "${CURRENCY}"): 128 client.fail(f'echo Wanted "${CURRENCY}:{regionalWanted}", got: "{currencyGot}:{regionalGot}"') 129 else: 130 client.succeed(f'echo Conversion successfully made: "${FIAT_CURRENCY}:{regionalWanted}" -> "{currencyGot}:{regionalGot}"') 131 ''; 132}