Make your Python project interact with memo.cash
Any Bitcoin Cash and Python enthusiast should now Bitcash. With Bitcash you can easily interact with the BCH blockchain. Here I'll leave some useful scripts to show how to send and find data stored in the blockchain with OP_RETURN. https://github.com/sporestack/bitcash Send a memo Memo.cash is a nice social media based on BCH, completely trustless and decentralized. Sending a memo is very easy, just keep in mind the format described by the protocol: from bitcash.wallet import Key from bitcash.transaction import get_op_pushdata_code, calc_txid from bitcash.utils import bytes_to_hex, hex_to_bytes from bitcash.network.services import NetworkAPI def send_memo(key, message): POST_MEMO_PREFIX = "026d02" PUSHDATA_CODE = bytes_to_hex(get_op_pushdata_code(message)) encoded_message = hex_to_bytes(POST_MEMO_PREFIX + PUSHDATA_CODE + bytes_to_hex(message.encode('utf-8'))) if len(encoded_message) <= 220: memo_tx = key.create_transaction([], message = encoded_message, leftover = key.address, custom_pushdata = True) NetworkAPI.broadcast_tx(memo_tx) key.get_balance() return(calc_txid(memo_tx)) else: return "Error: message longer than 220 bytes" Once you initialize a key with Bitcash, the function *send_memo* will allow you to send data up to 220 bytes. But how can you find data stored on the blockchain, once is sent? It's time to meet BitDB. Search on the BCH blockchain with BitDB BitDB is a powerful tool for searching data within the BCH blockchain. The result is a JSON file, so we can manage huge amounts of data. I'll show you 3 useful functions: raw_search_string: returns a JSON file with transactions containing the target string specified. search_string: returns a dictionary with every transaction ID that contains the target string. This is more easy to use if you don't wanna bother with JSON files. get_opreturn_by_txid: as the name says, you get the OP_RETURN data given a txid. Combined with the former function, you can search for a partial string and get the full string this way. get_opreturn_by_address: simply get the data post from a given address (in cash format, not legacy). Combined with the send_memo function, you can use the BCH blockchain as your own database. import requests, base64, json MAIN_ENDPOINT = 'https://bitdb.bch.sx/q/' def json_to_base64(json_file): return base64.b64encode(json.dumps(json_file).encode('utf-8')) def raw_search_string(target_string, limit): #Search a string in any op_return containing txs and returns a json file with raw info query = {"v": 3, "q": {"find": {"$text": { "$search": target_string },"out.b0": { "op": 106 }}, "limit": limit }} b64query = json_to_base64(query) r = requests.get(MAIN_ENDPOINT + b64query.decode()) if r.status_code == 200: return r.json() else: raise Exception ("Something went bad. Status code is " + r.status_code) def search_string(target_string, limit): #Returns a dictionary with the TX id and strings that cointains the target string. Not case sensitive. results = {} json_results = raw_search_string(target_string, limit) if json_results["u"] != []: results["unconfirmed_txs"] = {} for tx in json_results["u"]: current_tx_id = tx["tx"]["h"] results["unconfirmed_txs"][current_tx_id] = [] for output in tx["out"]: for data in output: if type(output[data]) == str and target_string.lower() in output[data].lower(): results["unconfirmed_txs"][current_tx_id].append(output[data]) if json_results["c"] != []: results["confirmed_txs"] = {} for tx in json_results["c"]: current_tx_id = tx["tx"]["h"] results["confirmed_txs"][current_tx_id] = [] for output in tx["out"]: for data in output: if type(output[data]) == str and target_string.lower() in output[data].lower(): results["confirmed_txs"][current_tx_id].append(output[data]) return results def get_opreturn_by_txid(txid): query = {"v": 3, "q": {"find": {"tx.h": txid}}} b64query = json_to_base64(query) r = requests.get(MAIN_ENDPOINT + b64query.decode()) if r.json()["u"] != []: for output in r.json()["u"][0]["out"]: if output["b0"] == {'op': 106}: return output["str"] elif r.json()["c"] != []: for output in r.json()["c"][0]["out"]: if output["b0"] == {'op': 106}: return output["str"] return "No OP_RETURN found in this transaction" else: return "No transaction found with this TX ID" def get_opreturn_by_address(address): #Find OP_return data send from a given address. A cash address must be provided, not legacy. Oldests TXs first. results = [] if address[:12] == "bitcoincash:": address = address[12:] query = {"v": 3,"q": {"aggregate": [{"$match": {"out.b0": { "op": 106 }, "in.e.a": address }},{"$match": {"out.b0": { "op": 106 }}},{"$unwind": "$out"},{"$match": {"in.e.a": address }},{"$limit": 100000}],"sort": {"blk.t": 1}, "limit": 100000}} b64query = json_to_base64(query) r = requests.get(MAIN_ENDPOINT + b64query.decode()) if r.json()["c"] != []: for output in r.json()["c"]: if output["out"]["b0"] == {'op': 106}: results.append(output["str"]) if r.json()["u"] != []: for output in r.json()["u"]: if output["out"]["b0"] == {'op': 106}: results.append(output["str"]) return results That's all folks, I hope these little scripts are useful for beginners!
10 comments
Bitcash is really nice! FYI: we have a much better way to display code, see here: https://read.cash/@Read.Cash/how-to-use-the-editor-at-readcash-e2df60aa#code-blocks
Thank you, I've just changed it.
Looks awesome!
Thank you!
Bitcash is a good tool that has the potential to develop the popularity and mass adoption of BCH if well utilized.
That's interesting, I'm learning Python now)
The full *encoded* message can be up to 223 bytes.
Wow thats interesting to know about python.. Good article. Keep going. Waiting for more of your articles.
Thats great that you wrote about it.Very informative post.I like your article.Keep writing more for us.
The full encoded message can be up to 223 bytes.