Skip to content

Commit cbe2d57

Browse files
committed
Merge dev squashed
0 parents  commit cbe2d57

17 files changed

Lines changed: 1694 additions & 0 deletions

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#TokenDex
2+
3+
A plugin for ElectronCash-SLP that allows you to trade SLP tokens with BCH (Token -> BCH and BCH -> Token) in a noncustodial manner. Everything including the order book is on the blockchain. There are no centralized servers.
4+
5+
##Installation
6+
1. Download the latest release.
7+
2. From the ElectronCash-SLP application menu select `Tools -> Installed Plugins`, then click `Add plugin` and then select the downloaded file from step 1.
8+
3. The plugin will then be installed and enabled.
9+
10+
Now you should see a new tab in your wallet window.
11+
12+
##Brief Usage Overview
13+
14+
1. Select one of the tokens available in your wallet.
15+
2. You can place a sell or buy order using the "Place Order" form.
16+
3. You can take any of the orders from their specified sections.
17+
4. Taking sell orders are instant but for taking the buy orders, the other party have to accept your take signal.
18+
5. If someone signals one of your buy orders, a button will appear next to order in the "Your Orders" section.
19+
20+
## Support
21+
If you had any question regarding the plugin, please feel free to drop a message in [simpleledger Telegram group](https://t.me/simpleledger).
22+
23+
## Support The Developer
24+
If you wish to donate to the developer, you can use the following address: `bitcoincash:qz2q3c4svltz5x047j87g8a7gkrh03xmc5mh0lvz0j`
25+
26+
##Special Thanks
27+
Very special thanks to those who helped fund the project.
28+
29+
##License
30+
MIT License

TokenDex/.gitignore

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95+
__pypackages__/
96+
97+
# Celery stuff
98+
celerybeat-schedule
99+
celerybeat.pid
100+
101+
# SageMath parsed files
102+
*.sage.py
103+
104+
# Environments
105+
.env
106+
.venv
107+
env/
108+
venv/
109+
ENV/
110+
env.bak/
111+
venv.bak/
112+
113+
# Spyder project settings
114+
.spyderproject
115+
.spyproject
116+
117+
# Rope project settings
118+
.ropeproject
119+
120+
# mkdocs documentation
121+
/site
122+
123+
# mypy
124+
.mypy_cache/
125+
.dmypy.json
126+
dmypy.json
127+
128+
# Pyre type checker
129+
.pyre/

TokenDex/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 OPReturn
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

TokenDex/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fullname = "TokenDex"
2+
available_for = ["qt"]
3+
description = "SLP on-chain noncustodial token swap"

TokenDex/bfp.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import hashlib
2+
3+
from electroncash import bitcoinfiles
4+
from electroncash.transaction import Transaction
5+
6+
7+
def upload_file(wallet, file_bytes, config={}, password=None):
8+
file_tx_id = None
9+
tx_batch = []
10+
11+
file_size = len(file_bytes)
12+
assert file_size <= 10522
13+
14+
metadata = dict()
15+
metadata['filename'] = 'data'
16+
metadata['fileext'] = 'json'
17+
metadata['filesize'] = file_size
18+
metadata['file_sha256'] = hashlib.sha256(file_bytes).hexdigest()
19+
metadata['prev_file_sha256'] = None
20+
metadata['uri'] = None
21+
22+
cost = bitcoinfiles.calculateUploadCost(file_size, metadata)
23+
file_receiver_address = wallet.get_addresses()[0] # todo change this
24+
25+
# TODO, guard tokens during this transaction?
26+
#####################################################################################
27+
28+
file_220_chunks = []
29+
for i in range(1, (len(file_bytes) // 220) + 2):
30+
file_220_chunks.append(file_bytes[(i-1)*220:i*220])
31+
32+
funding_tx = bitcoinfiles.getFundingTxn(wallet, file_receiver_address, cost, config)
33+
wallet.sign_transaction(funding_tx, password)
34+
tx_batch.append(funding_tx)
35+
36+
prev_tx = funding_tx
37+
for i in range(len(file_220_chunks)):
38+
tx, is_metadata_tx = bitcoinfiles.getUploadTxn(
39+
wallet, prev_tx=prev_tx, chunk_index=i, chunk_count=len(file_220_chunks),
40+
chunk_data=file_220_chunks[i], config=config, metadata=metadata, file_receiver=file_receiver_address
41+
)
42+
wallet.sign_transaction(tx, password)
43+
tx_batch.append(tx)
44+
prev_tx = tx
45+
46+
if not is_metadata_tx: # last chunk didn't fit into the metadata tx
47+
tx, is_metadata_tx = bitcoinfiles.getUploadTxn(
48+
wallet, prev_tx=prev_tx, chunk_index=i+1, chunk_count=len(file_220_chunks),
49+
chunk_data=b'', config=config, metadata=metadata, file_receiver=file_receiver_address
50+
)
51+
wallet.sign_transaction(tx, password)
52+
tx_batch.append(tx)
53+
if is_metadata_tx:
54+
file_tx_id = tx.txid()
55+
56+
for tx in tx_batch:
57+
status, tx_id = wallet.network.broadcast_transaction(tx)
58+
assert status
59+
return file_tx_id
60+
61+
62+
def download_file(wallet, tx_id):
63+
network = wallet.network
64+
65+
status, raw_metadata_tx = network.get_raw_tx_for_txid(tx_id)
66+
assert status
67+
metadata_tx = Transaction(raw_metadata_tx)
68+
69+
bitcoin_files_metadata_msg = bitcoinfiles.BfpMessage.parseBfpScriptOutput(metadata_tx.outputs()[0][1])
70+
71+
chunk_count = bitcoin_files_metadata_msg.op_return_fields['chunk_count']
72+
chunk_data = bitcoin_files_metadata_msg.op_return_fields['chunk_data']
73+
chunk_data_is_empty = chunk_data == b''
74+
75+
downloaded_transactions = []
76+
assert chunk_count != 0
77+
78+
def get_tx_chunks(tx_id, index):
79+
status, raw_tx = network.get_raw_tx_for_txid(tx_id)
80+
assert status is True
81+
tx = Transaction(raw_tx)
82+
try:
83+
data = bitcoinfiles.parseOpreturnToChunks(
84+
tx.outputs()[0][1].to_script(), allow_op_0=False, allow_op_number=False
85+
)
86+
except bitcoinfiles.BfpOpreturnError: # It's the funding tx probably
87+
return
88+
downloaded_transactions.append(
89+
{'tx_id': metadata_tx.txid(),
90+
'data': data[0]
91+
}
92+
)
93+
index += 1
94+
if index <= chunk_count - 1: # TODO removed <= to <
95+
get_tx_chunks(tx.inputs()[0]['prevout_hash'], index)
96+
97+
if chunk_count == 1:
98+
if not chunk_data_is_empty:
99+
downloaded_transactions.append({'tx_id': metadata_tx.txid(), 'data': chunk_data})
100+
# DONE! FINISHED!
101+
if chunk_count > 1 or (chunk_count == 1 and chunk_data_is_empty):
102+
if not chunk_data_is_empty:
103+
downloaded_transactions.append({'tx_id': metadata_tx.txid(), 'data': chunk_data})
104+
index = 0
105+
get_tx_chunks(metadata_tx.inputs()[0]['prevout_hash'], index)
106+
107+
f = b''
108+
downloaded_transactions.reverse()
109+
for element in downloaded_transactions:
110+
f += element['data']
111+
assert hashlib.sha256(f).hexdigest() == bitcoin_files_metadata_msg.op_return_fields['file_sha256'].hex()
112+
return f
113+
114+

0 commit comments

Comments
 (0)