diff --git a/docs/api/wallet-rpc.yaml b/docs/api/wallet-rpc.yaml index e3f9a2c..1e13ed9 100644 --- a/docs/api/wallet-rpc.yaml +++ b/docs/api/wallet-rpc.yaml @@ -138,6 +138,16 @@ paths: $ref: '#/components/responses/401-Unauthorized' '404': $ref: '#/components/responses/404-NotFound' + /getinfo: + get: + security: + - {} + summary: get info on backend + operationId: version + description: get information about backend, including the version of Joinmarket running. + responses: + '200': + $ref: "#/components/responses/Getinfo-200-OK" /wallet/all: get: summary: get current available wallets @@ -754,6 +764,22 @@ components: items: type: string example: "2021/10/26 16:40:21,133986791,1,200000000,2680,2680,0.08," + GetinfoResponse: + type: object + required: + - version + properties: + version: + type: string + example: "0.9.10" + RescanBlockchainResponse: + type: object + required: + - walletname + properties: + walletname: + type: string + example: "wallet.jmdat" SessionResponse: type: object required: @@ -1106,12 +1132,18 @@ components: application/json: schema: $ref: "#/components/schemas/SessionResponse" + Getinfo-200-OK: + description: "successful Joinmarket getinfo response" + content: + application/json: + schema: + $ref: "#/components/schemas/GetinfoResponse" RescanBlockchain-200-OK: description: "Blockchain rescan started successfully" content: application/json: schema: - $ref: "#/components/schemas/SessionResponse" + $ref: "#/components/schemas/RescanBlockchainResponse" Create-201-OK: description: "wallet created successfully" content: diff --git a/jmclient/jmclient/wallet_rpc.py b/jmclient/jmclient/wallet_rpc.py index 15abc12..a6c7efd 100644 --- a/jmclient/jmclient/wallet_rpc.py +++ b/jmclient/jmclient/wallet_rpc.py @@ -27,7 +27,7 @@ from jmclient import Taker, jm_single, \ tumbler_filter_orders_callback, tumbler_taker_finished_update, \ validate_address, FidelityBondMixin, BaseWallet, WalletError, \ ScheduleGenerationErrorNoFunds, BIP39WalletMixin -from jmbase.support import get_log, utxostr_to_utxo +from jmbase.support import get_log, utxostr_to_utxo, JM_CORE_VERSION jlog = get_log() @@ -602,6 +602,10 @@ class JMWalletDaemon(Service): Note that it technically "shouldn't" require a wallet to be loaded, but since we hide all blockchain access behind the wallet service, it currently *does* require this. + An additional subtlety to bear in mind: the action of rescanblockchain + depends on the *currently loaded Bitcoin Core wallet*, that Core wallet + load event is currently done on startup of Joinmarket, depending on + the setting in the joinmarket.cfg file. """ print_req(request) self.check_cookie(request) @@ -615,6 +619,15 @@ class JMWalletDaemon(Service): self.services["wallet"].rescanblockchain(blockheight) return make_jmwalletd_response(request, walletname=walletname) + @app.route('/getinfo', methods=['GET']) + def version(self, request): + """ This route sends information about the backend, including + the running version of Joinmarket, + back to the client. It does *not* pay attention to any state, + including authentication tokens. + """ + return make_jmwalletd_response(request,version=JM_CORE_VERSION) + @app.route('/session', methods=['GET']) def session(self, request): """ This route functions as a heartbeat, and communicates diff --git a/jmclient/test/test_wallet_rpc.py b/jmclient/test/test_wallet_rpc.py index b14f746..63b697e 100644 --- a/jmclient/test/test_wallet_rpc.py +++ b/jmclient/test/test_wallet_rpc.py @@ -10,7 +10,7 @@ from autobahn.twisted.websocket import WebSocketClientFactory, \ connectWS from jmbase import get_nontor_agent, hextobin, BytesProducer, get_log -from jmbase.support import get_free_tcp_ports +from jmbase.support import get_free_tcp_ports, JM_CORE_VERSION from jmbitcoin import CTransaction from jmclient import ( load_test_config, @@ -685,6 +685,20 @@ class TrialTestWRPC_DisplayWallet(WalletRPCTestBase, unittest.TestCase): yield self.do_request(agent, b"POST", addr, body, self.process_do_coinjoin_response) + @defer.inlineCallbacks + def test_getinfo(self): + agent = get_nontor_agent() + addr = self.get_route_root() + addr += "/getinfo" + addr = addr.encode() + yield self.do_request(agent, b"GET", addr, None, + self.process_getinfo_response) + + def process_getinfo_response(self, response, code): + assert code==200 + responseobj = json.loads(response.decode("utf-8")) + assert responseobj["version"] == JM_CORE_VERSION + def process_do_coinjoin_response(self, response, code): assert code == 202 # response code is already checked to be 200