Skip to content

Commit d9971d7

Browse files
authored
Merge pull request #111 from bridgedragon/feature/Method_getTransaction_only_returns_in-wallet_transactions
Feature/method get transaction only returns in wallet transactions
2 parents e076930 + b160596 commit d9971d7

File tree

9 files changed

+224
-100
lines changed

9 files changed

+224
-100
lines changed

Connector/btc/apirpc.py

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from logger import logger
55
from rpcutils import error
66
from rpcutils.rpcconnector import RPCConnector
7+
from rpcutils.rpcsocketconnector import RPCSocketConnector
78
from . import utils
89
from .constants import *
910

@@ -367,7 +368,7 @@ def getTransactionHex(id, params, config):
367368
rawTransaction = RPCConnector.request(
368369
endpoint=config.bitcoincoreRpcEndpoint,
369370
id=id,
370-
method=GET_TRANSACTION_METHOD,
371+
method=GET_RAW_TRANSACTION_METHOD,
371372
params=[params["txHash"]]
372373
)
373374

@@ -383,7 +384,6 @@ def getTransactionHex(id, params, config):
383384
@rpcmethod.rpcMethod(coin=COIN_SYMBOL)
384385
@httpmethod.postHttpMethod(coin=COIN_SYMBOL)
385386
def getTransaction(id, params, config):
386-
387387
logger.printInfo(f"Executing RPC method getTransaction with id {id} and params {params}")
388388

389389
requestSchema, responseSchema = utils.getMethodSchemas(GET_TRANSACTION)
@@ -393,53 +393,47 @@ def getTransaction(id, params, config):
393393
raise error.RpcBadRequestError(err.message)
394394

395395
try:
396-
# Parameters: TransactionId, include_watchonly, verbose
397396
transaction = RPCConnector.request(
398397
endpoint=config.bitcoincoreRpcEndpoint,
399398
id=id,
400-
method=GET_TRANSACTION_METHOD,
399+
method=GET_RAW_TRANSACTION_METHOD,
401400
params=[
402401
params["txHash"],
403-
True,
404402
True
405403
]
406404
)
407405

408-
vinAddressBalances = {}
409-
transactionAmount = 0
406+
# Check if transaction is confirmed, and obtain block number
407+
if "blockhash" in transaction:
408+
transactionBlock = RPCConnector.request(
409+
endpoint=config.bitcoincoreRpcEndpoint,
410+
id=id,
411+
method=GET_BLOCK,
412+
params=[transaction["blockhash"], 1]
413+
)
414+
blockNumber = transactionBlock["height"]
415+
else:
416+
blockNumber = None
410417

411-
if "generated" not in transaction:
412418

413-
for vin in transaction["decoded"]["vin"]:
414-
inputTransaction = RPCConnector.request(
415-
endpoint=config.bitcoincoreRpcEndpoint,
416-
id=id,
417-
method=GET_TRANSACTION_METHOD,
418-
params=[
419-
vin["txid"],
420-
True,
421-
True
422-
]
423-
)
419+
transactionDetails = utils.decodeTransactionDetails(transaction, config.bitcoincoreRpcEndpoint)
424420

425-
transactionAmount += inputTransaction["decoded"]["vout"][vin["vout"]]["value"]
426-
address = inputTransaction["decoded"]["vout"][vin["vout"]]["scriptPubKey"]["addresses"][0]
427-
value = inputTransaction["decoded"]["vout"][vin["vout"]]["value"]
428-
vinAddressBalances[address] = value
421+
# Converting all transaction details to str
422+
transactionDetails["fee"] = str(transactionDetails["fee"])
423+
for input in transactionDetails["inputs"]:
424+
input["amount"] = str(input["amount"])
425+
for output in transactionDetails["outputs"]:
426+
output["amount"] = str(output["amount"])
429427

430428
response = {
431429
"transaction": {
432-
"txHash": params["txHash"],
433-
"blockhash": transaction["blockhash"] if transaction["confirmations"] >= 1 else None,
434-
"blockNumber": str(transaction["blockheight"]) if transaction["confirmations"] >= 1 else None,
435-
"fee": str(utils.convertToSatoshi(-transaction["fee"])) if "generated" not in transaction else "0",
436-
"transfers": utils.parseBalancesToTransfers(
437-
vinAddressBalances,
438-
transaction["details"],
439-
-transaction["fee"] if "generated" not in transaction else 0,
440-
transactionAmount
441-
),
442-
"data": transaction["decoded"]
430+
"txId": transaction["txid"],
431+
"txHash": transaction["hash"],
432+
"blockNumber": str(blockNumber) if blockNumber is not None else blockNumber,
433+
"fee": transactionDetails["fee"],
434+
"inputs": transactionDetails["inputs"],
435+
"outputs": transactionDetails["outputs"],
436+
"data": transaction
443437
}
444438
}
445439

Connector/btc/config.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def __init__(self, coin, networkName):
2424
self._electrumPassword = ""
2525
self._bitcoincoreCallbackProtocol = ""
2626
self._bitcoincoreCallbackHost = ""
27+
self._electrumxHost = ""
28+
self._electrumxPort = 0
2729

2830
def loadConfig(self, config):
2931

@@ -57,6 +59,8 @@ def loadConfig(self, config):
5759
else defaultConfig["bitcoincoreCallbackProtocol"]
5860
self.bitcoincoreCallbackHost = config["bitcoincoreCallbackHost"] if "bitcoincoreCallbackHost" in config \
5961
else defaultConfig["bitcoincoreCallbackHost"]
62+
self.electrumxHost = config["electrumxHost"] if "electrumxHost" in config else defaultConfig["electrumxHost"]
63+
self.electrumxPort = config["electrumxPort"] if "electrumxPort" in config else defaultConfig["electrumxPort"]
6064

6165
return True, None
6266

@@ -184,6 +188,22 @@ def bitcoincoreCallbackHost(self):
184188
def bitcoincoreCallbackHost(self, value):
185189
self._bitcoincoreCallbackHost = value
186190

191+
@property
192+
def electrumxHost(self):
193+
return self._electrumxHost
194+
195+
@electrumxHost.setter
196+
def electrumxHost(self, value):
197+
self._electrumxHost = value
198+
199+
@property
200+
def electrumxPort(self):
201+
return self._electrumxPort
202+
203+
@electrumxPort.setter
204+
def electrumxPort(self, value):
205+
self._electrumxPort = value
206+
187207
@property
188208
def bitcoincoreRpcEndpoint(self):
189209
return f"{self.bitcoincoreProtocol}://" \
@@ -226,5 +246,7 @@ def encode(self, o):
226246
"electrumHost": o.electrumHost,
227247
"electrumPort": o.electrumPort,
228248
"electrumUser": o.electrumUser,
229-
"electrumPassword": o.electrumPassword
249+
"electrumPassword": o.electrumPassword,
250+
"electrumxHost": o.electrumxHost,
251+
"electrumxPort": o.electrumxPort
230252
}

Connector/btc/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
GET_BLOCK_HASH_METHOD = "getblockhash"
99
GET_BLOCK_COUNT_METHOD = "getblockcount"
1010
ESTIMATE_SMART_FEE_METHOD = "estimatesmartfee"
11-
GET_TRANSACTION_METHOD = "gettransaction"
11+
GET_RAW_TRANSACTION_METHOD = "getrawtransaction"
1212
DECODE_RAW_TRANSACTION_METHOD = "decoderawtransaction"
1313
SEND_RAW_TRANSACTION_METHOD = "sendrawtransaction"
1414
NOTIFY_METHOD = "notify"
@@ -100,6 +100,7 @@
100100
NOTIFY = "notify"
101101
NEW_HASH_BLOCK_ZMQ_TOPIC = "hashblock"
102102
NEW_RAW_BLOCK_ZMQ_TOPIC = "rawblock"
103+
GET_BLOCK = "getblock"
103104

104105
SUBSCRIBE_ADDRESS_BALANCE = "subscribetoaddressbalance"
105106
UNSUBSCRIBE_ADDRESS_BALANCE = "unsubscribefromaddressbalance"

Connector/btc/defaultConf.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@
1212
"electrumUser": "swapper",
1313
"electrumPassword": "swapper",
1414
"bitcoincoreCallbackProtocol": "http",
15-
"bitcoincoreCallbackHost": "connector"
15+
"bitcoincoreCallbackHost": "connector",
16+
"electrumxHost": "electrs",
17+
"electrumxPort": 60001
1618
}

Connector/btc/rpcschemas/gettransaction_response.json

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,31 @@
2828
"fee": {
2929
"type": "string"
3030
},
31-
"transfers": {
31+
"inputs": {
3232
"type": "array",
3333
"items": {
3434
"properties": {
35-
"from": {
36-
"type": "string"
37-
},
38-
"to": {
39-
"type": "string"
35+
"address": {
36+
"type": [
37+
"string",
38+
"null"
39+
]
4040
},
41-
"fee": {
41+
"amount": {
4242
"type": "string"
43+
}
44+
}
45+
}
46+
},
47+
"outputs": {
48+
"type": "array",
49+
"items": {
50+
"properties": {
51+
"address": {
52+
"type": [
53+
"string",
54+
"null"
55+
]
4356
},
4457
"amount": {
4558
"type": "string"

Connector/btc/utils.py

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
#!/usr/bin/python3
2+
import binascii
3+
import hashlib
4+
import math
25
from decimal import Decimal
36
import random
47
import sys
58
from logger import logger
69
from rpcutils import error as rpcerrorhandler
710
from wsutils import topics
11+
from rpcutils.rpcconnector import RPCConnector
12+
from rpcutils.rpcsocketconnector import RPCSocketConnector
813
from .constants import *
914
from . import apirpc
1015

@@ -64,49 +69,53 @@ def closeAddrBalanceTopic(topicName):
6469
raise rpcerrorhandler.BadRequestError(f"Can not unsubscribe {topicName} to node")
6570

6671

67-
def parseBalancesToTransfers(vin, vout, fee, amount):
68-
69-
transfers = []
70-
diff = 0
71-
72-
for utxo in vout:
73-
74-
if utxo["category"] == "send":
75-
76-
for address in list(vin.keys()):
77-
78-
voutAmount = -utxo["amount"]
79-
vinAmount = vin[address]
80-
81-
if vinAmount <= (voutAmount + diff):
82-
transfer = {
83-
"from": address,
84-
"to": utxo["address"],
85-
"amount": str(convertToSatoshi(vinAmount)),
86-
"fee": str(convertToSatoshi(round(vinAmount * fee / amount, BTC_PRECISION)))
87-
}
88-
del vin[address]
89-
else:
90-
transfer = {
91-
"from": address,
92-
"to": utxo["address"],
93-
"amount": str(convertToSatoshi(voutAmount)),
94-
"fee": str(convertToSatoshi(round(voutAmount * fee / amount, BTC_PRECISION)))
95-
}
96-
97-
diff = diff + voutAmount - vinAmount
98-
transfers.append(transfer)
99-
100-
if utxo["category"] in ["generate", "immature", "orphan"]:
101-
transfers.append(
102-
{
103-
"to": utxo["address"],
104-
"fee": "0",
105-
"amount": str(convertToSatoshi(utxo["maount"]))
106-
}
107-
)
108-
109-
return transfers
72+
def decodeTransactionDetails(txDecoded, bitcoincoreRpcEndpoint):
73+
outputs = []
74+
for output in txDecoded["vout"]:
75+
if "addresses" in output["scriptPubKey"] and len(output["scriptPubKey"]["addresses"]) == 1:
76+
outputs.append(
77+
{"amount": math.trunc(output["value"] * 100000000), "address": output["scriptPubKey"]["addresses"][0]})
78+
else:
79+
outputs.append({"amount": math.trunc(output["value"] * 100000000), "address": None})
80+
81+
sumOutputs = 0
82+
for output in outputs:
83+
sumOutputs += output["amount"]
84+
85+
inputs = []
86+
for txInput in txDecoded["vin"]:
87+
88+
if "coinbase" in txInput: # This is a coinbase transaction and thus it have one only input of 'sumOutputs'
89+
inputs.append({"amount": sumOutputs, "address": None})
90+
break
91+
92+
transaction = RPCConnector.request(
93+
endpoint=bitcoincoreRpcEndpoint,
94+
id=0,
95+
method="getrawtransaction",
96+
params=[
97+
txInput["txid"],
98+
True
99+
]
100+
)
101+
102+
for txOutput in transaction["vout"]:
103+
if txOutput["n"] == txInput["vout"] and "addresses" in txOutput["scriptPubKey"] and len(
104+
txOutput["scriptPubKey"]["addresses"]) == 1:
105+
inputs.append({"amount": math.trunc(txOutput["value"] * 100000000),
106+
"address": txOutput["scriptPubKey"]["addresses"][0]})
107+
elif "addresses" not in txOutput["scriptPubKey"] or len(txOutput["scriptPubKey"]["addresses"]) != 1:
108+
inputs.append({"amount": math.trunc(txOutput["value"] * 100000000), "address": None})
109+
110+
sumInputs = 0
111+
for txInput in inputs:
112+
sumInputs += txInput["amount"]
113+
114+
fee = sumInputs - sumOutputs
115+
116+
transactionsDetails = {"fee": fee, "inputs": inputs, "outputs": outputs}
117+
118+
return transactionsDetails
110119

111120

112121
def sortUnspentOutputs(outputs):

Connector/eth/apirpc.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,16 @@ def getTransaction(id, params, config):
222222
"blockHash": transaction["blockHash"],
223223
"blockNumber": str(int(transaction["blockNumber"], 16)) if transaction["blockNumber"] is not None else None,
224224
"data": transaction,
225-
"transfers": [
225+
"inputs": [
226226
{
227-
"from": transaction["from"],
228-
"to": transaction["to"],
229-
"amount": str(utils.toWei(transaction["value"])),
230-
"fee": str(utils.toWei(transaction["gasPrice"]) * utils.toWei(transaction["gas"]))
227+
"address": transaction["from"],
228+
"amount": str(utils.toWei(transaction["value"]))
229+
}
230+
],
231+
"outputs": [
232+
{
233+
"address": transaction["to"],
234+
"amount": str(utils.toWei(transaction["value"]))
231235
}
232236
]
233237
}

Connector/eth/rpcschemas/gettransaction_response.json

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,31 @@
2525
"fee": {
2626
"type": "string"
2727
},
28-
"transfers": {
28+
"inputs": {
2929
"type": "array",
3030
"items": {
31-
"type": "object",
3231
"properties": {
33-
"from": {
34-
"type": "string"
35-
},
36-
"to": {
37-
"type": "string"
32+
"address": {
33+
"type": [
34+
"string"
35+
]
3836
},
3937
"amount": {
4038
"type": "string"
39+
}
40+
}
41+
}
42+
},
43+
"outputs": {
44+
"type": "array",
45+
"items": {
46+
"properties": {
47+
"address": {
48+
"type": [
49+
"string"
50+
]
4151
},
42-
"fee": {
52+
"amount": {
4353
"type": "string"
4454
}
4555
}

0 commit comments

Comments
 (0)