Browse Source

Add freeze method to RPC-API

Fixes #1093. This adds a POST method freeze for a wallet,
in which the utxo must be specified as a standard hex txid:n
string in the body, along with a boolean value of 'freeze', to
toggle the frozen/unfrozen state of the given utxo in the wallet.
master
Adam Gibson 4 years ago
parent
commit
29b459aa84
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 43
      jmclient/jmclient/wallet-rpc-api.yaml
  2. 31
      jmclient/jmclient/wallet_rpc.py
  3. 35
      jmclient/test/test_wallet_rpc.py

43
jmclient/jmclient/wallet-rpc-api.yaml

@ -399,6 +399,31 @@ paths:
$ref: "#/components/responses/401-Unauthorized"
'409':
$ref: '#/components/responses/409-NoConfig'
/wallet/{walletname}/freeze:
post:
security:
- bearerAuth: []
summary: freeze or unfreeze an individual utxo for spending
operationId: freeze
description: freeze or unfreeze an individual utxo for spending
parameters:
- name: walletname
in: path
description: name of wallet including .jmdat
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/FreezeRequest'
description: utxo string and freeze toggle as boolean
responses:
'200':
$ref: "#/components/responses/Freeze-200-OK"
'400':
$ref: '#/components/responses/400-BadRequest'
/wallet/{walletname}/getseed:
get:
security:
@ -432,6 +457,16 @@ components:
scheme: bearer
bearerFormat: JWT
schemas:
FreezeRequest:
type: object
required:
- utxo-string
- freeze
properties:
utxo-string:
type: string
freeze:
type: boolean
ConfigSetRequest:
type: object
required:
@ -464,6 +499,8 @@ components:
type: string
ConfigSetResponse:
type: object
FreezeResponse:
type: object
DoCoinjoinRequest:
type: object
required:
@ -830,6 +867,12 @@ components:
application/json:
schema:
$ref: "#/components/schemas/GetSeedResponse"
Freeze-200-OK:
description: "freeze or unfreeze utxo action completed successfully"
content:
application/json:
schema:
$ref: "#/components/schemas/FreezeResponse"
202-Accepted:
description: The request has been submitted successfully for processing, but the processing has not been completed.
204-NoResultFound:

31
jmclient/jmclient/wallet_rpc.py

@ -22,7 +22,7 @@ from jmclient import Taker, jm_single, \
StorageError, StoragePasswordError, JmwalletdWebSocketServerFactory, \
JmwalletdWebSocketServerProtocol, RetryableStorageError, \
SegwitWalletFidelityBonds, wallet_gettimelockaddress
from jmbase.support import get_log
from jmbase.support import get_log, utxostr_to_utxo
jlog = get_log()
@ -791,6 +791,35 @@ class JMWalletDaemon(Service):
# null return indicates success in updating:
return make_jmwalletd_response(request)
@app.route('/wallet/<string:walletname>/freeze', methods=["POST"])
def freeze(self, request, walletname):
""" Freeze (true) or unfreeze (false), for spending a specified utxo
in this wallet. Note that this is persisted in the wallet file,
so the status survives across sessions. Note that re-application of
the same state is allowed and does not alter the 200 OK return.
"""
self.check_cookie(request)
if not self.wallet_name == walletname:
raise InvalidRequestFormat()
freeze_json = self.get_POST_body(request, ["utxo-string", "freeze"])
if not freeze_json:
raise InvalidRequestFormat()
to_disable = freeze_json["freeze"]
valid, txidindex = utxostr_to_utxo(freeze_json["utxo-string"])
if not valid:
raise InvalidRequestFormat()
txid, index = txidindex
try:
# note: this does not raise or fail if the applied
# disable state (true/false) is the same as the current
# one; that is accepted and not an error.
self.wallet_service.disable_utxo(txid, index, to_disable)
except AssertionError:
# should be impossible because format checked by
# utxostr_to_utxo:
raise InvalidRequestFormat()
return make_jmwalletd_response(request)
def get_listutxos_response(self, utxos):
res = []
for k, v in utxos.items():

35
jmclient/test/test_wallet_rpc.py

@ -381,16 +381,31 @@ class TrialTestWRPC_DisplayWallet(WalletRPCTestBase, unittest.TestCase):
assert validate_address(json_body["address"])[0]
@defer.inlineCallbacks
def test_listutxos(self):
def test_listutxos_and_freeze(self):
self.daemon.auth_disabled = True
agent = get_nontor_agent()
addr = self.get_route_root()
addr += "/wallet/"
addr += self.daemon.wallet_name
addr += "/utxos"
pre_addr = self.get_route_root()
pre_addr += "/wallet/"
pre_addr += self.daemon.wallet_name
addr = pre_addr + "/utxos"
addr = addr.encode()
yield self.do_request(agent, b"GET", addr, None,
self.process_listutxos_response)
# Test of freezing is currently very primitive: we only
# check that the action was accepted; a full test would
# involve checking that spending the coin works or doesn't
# work, as expected.
addr = pre_addr + "/freeze"
addr = addr.encode()
utxostr = self.mixdepth1_utxos[0]["utxo"]
body = BytesProducer(json.dumps({"utxo-string": utxostr,
"freeze": True}).encode())
yield self.do_request(agent, b"POST", addr, body,
self.process_utxo_freeze)
body = BytesProducer(json.dumps({"utxo-string": utxostr,
"freeze": False}).encode())
yield self.do_request(agent, b"POST", addr, body,
self.process_utxo_freeze)
def process_listutxos_response(self, response, code):
assert code == 200
@ -399,11 +414,15 @@ class TrialTestWRPC_DisplayWallet(WalletRPCTestBase, unittest.TestCase):
# have depend on what other tests occurred.
# For now, we at least check that we have 3 utxos in mixdepth
# 1 because none of the other tests spend them:
mixdepth1_utxos = 0
mixdepth1_utxos = []
for d in json_body["utxos"]:
if d["mixdepth"] == 1:
mixdepth1_utxos += 1
assert mixdepth1_utxos == 3
mixdepth1_utxos.append(d)
assert len(mixdepth1_utxos) == 3
self.mixdepth1_utxos = mixdepth1_utxos
def process_utxo_freeze(self, response, code):
assert code == 200
@defer.inlineCallbacks
def test_session(self):

Loading…
Cancel
Save