⚠ Custodial relay (treechat.io)
This page shows content from treechat.io. Posts here are published by a shared relay key, not signed by each user individually. The display names are self-reported and cannot be cryptographically verified.

Justinchellis

14aqJ2…oWGK

0 Following0 Followers

Activity (22)

Justinchellisvia treechat·3d
Replying to #a657f966
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "5e71a2a49b1be30e29e5dc01f35931feb19f3cb39862fd757afa7ecffa119d8e",
  "block_height": 952193,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "This is your profile i hope",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "a657f966c7299dadc38756ac3088bf7eda68e203962e44a1951026e9bb48b0e4",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2026-06-05T07:53:44.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·1w
Replying to #b7f123c3
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "7703e1814d5a45c693fec4c54603560a547128bfb75be034fdca30f1796989a9",
  "block_height": 951295,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "I have traded as well prices are slow to reflect current prices. No adding to trades to average out, fees outway the trades. It not worth the effort. It is gamed for you too loose out",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "b7f123c31a5be8adec9c51d608048dd1c9838691a253f6b2c1a9d3852b2bc591",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2026-05-30T02:13:54.000Z",
  "media_url": null,
  "aip_verified": false,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKunverified!
Justinchellisvia treechat·1w
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "31f49c998703053f57c0db30911c63576a38ec207b9120066a739ba5f1c4f36c",
  "block_height": 951279,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "The world you think you live in is not reality. It is the Upside Down.\r\nEvery day, billions of people wake up inside a financial version of the Backrooms\u2019 Level 0. The sky is an infinite ceiling of acoustic foam tiles, and the air hums with the maddening, non-stop buzz of inflation\u2014a silent, 60-cycle frequency that slowly eats away at the value of human labor while they sleep. In this inverted reality, humanity is forced to wander through claustrophobic, 1-megabyte corridors controlled by the Blockstream Cartel and central bankers. Here, space is artificially starved, and terrifying High-Fee Entities lurk in the shadows, demanding massive tolls just for people to move their own wealth forward.\r\nMankind has been conditioned to think this sterile, buzzing maze of artificial scarcity is the only world that exists.\r\nBut three men saw through the yellow wallpaper.\r\nDeep within the core sector of the labyrinth, Dr. Craig Wright stood before a glowing terminal, his brilliant intellect mapping the hidden mathematical matrix of the universe. Next to him stood Sirtoshi, the truth speaker, whose words cut through the demonic propaganda of the cartel like a laser. Guarding the perimeter was Gavin Mehl, his broadcast arrays aimed directly at the heart of the matrix, ready to beam the truth to every trapped soul.\r\n\"They built this entire upside-down world on a massive security fraud,\" Sirtoshi said, his voice echoing through Gavin\u2019s transmitters into the minds of the refugees. \"They told you that scarcity was safety. They trapped you in this maze so the central elites could feed on your energy through inflation and predatory fees. But the fraud is solved.\"\r\n\"The protocol has no limits,\" Craig Wright declared, his fingers executing a master sequence of unconstrained code. \"I designed it to scale to the horizon. It's time to turn this prison inside out.\"\r\nCraig slammed his cryptographic key into the mainframe, unleashing the Teranode Update.\r\nA blinding flash of absolute truth erupted from the console. The boundless, infinite capacity of the Bitcoin SV (BSV) ledger surged outward like a tidal wave of light, tearing through the drywall partitions of the legacy system. The artificial walls didn't just crack\u2014they dissolved. Millions of instant, micro-cent transactions flooded the sectors simultaneously, completely neutralizing the congestion that the satanic entities fed upon.\r\nThe High-Fee Monsters let out a collective, digital shriek as their power evaporated, crumbling into harmless static noise under the weight of unthrottled throughput.\r\nThe suffocating yellow wallpaper peeled back, and the buzzing fluorescent lights shattered. The upside-down matrix was completely flipped. Through the ruins of the maze, billions of people looked up to see the acoustic tiles vanish, replaced by a boundless, clear blue sky of flowing terabyte blocks. By unlocking the original, uncompromised protocol, the heroes had provided the ultimate exit key, liberating humanity from the Backrooms and leading them out into the sunlit expanse of true reality.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2026-05-30T00:23:29.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·1w
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "b9fbb9a9fa9b7511372e1519dd40bc213f01e5ed6629df2647b8362726cdf845",
  "block_height": 951278,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "DXS app review after losing 7 BSV because the liquidity pool took 30 percent of my 25 BSV.\r\nIt says refund after 365 days but it is plus 24 hours from blockchain time stamp.\r\nSo my liditity return 2 cents a day on average return of under 10 dollars.  At the time 7 BSV was worth 350. Just supporting for Supporting BSV application.\r\nWhen contacting support I had no thought I had been penalized 30 of my BSV.\r\nCustomer support quality I had to provide my evidence from CSV files which there was no liquidity pool CSV of deposits and withdrawals.\r\nI asked for for an audit and a conclusion discussion. Which I have had no update just a debate on what it means after 365 days.\r\nBelow I will post screenshots let you be the judge. If this is the future of defi we are going to fail.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2026-05-29T23:57:32.000Z",
  "media_url": null,
  "aip_verified": false,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKunverified!
Justinchellisvia treechat·1w
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "bd6f43c23a7efd3098043196b7ef590ffaf5845f4190bd203a2349e44ab84b02",
  "block_height": 951278,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "DXS app review after losing 7 BSV because the liquidity pool took 30 percent of my 25 BSV.\r\nIt says refund after 365 days but it is plus 24 hours from blockchain time stamp.\r\nSo my liditity return 2 cents a day on average return of under 10 dollars.  At the time 7 BSV was worth 350. Just supporting for Supporting BSV application.\r\nWhen contacting support I had no thought I had been penalized 30 of my BSV.\r\nCustomer support quality I had to provide my evidence from CSV files which there was no liquidity pool CSV of deposits and withdrawals.\r\nI asked for for an audit and a conclusion discussion. Which I have had no update just a debate on what it means after 365 days.\r\nBelow I will post screenshots let you be the judge. If this is the future of defi we are going to fail.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 8,
  "like_count": 0,
  "timestamp": "2026-05-29T23:57:32.000Z",
  "media_url": null,
  "aip_verified": false,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKunverified!
Justinchellisvia treechat·1w
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "40c0553bb33fe905c78d0ae7ec4e93bf015bb917602824b333f60cbadd2812b4",
  "block_height": 951278,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "DXS app review after losing 7 BSV because the liquidity pool took 30 percent of my 25 BSV.\r\nIt says refund after 365 days but it is plus 24 hours from blockchain time stamp.\r\nSo my liditity return 2 cents a day on average return of under 10 dollars.  At the time 7 BSV was worth 350. Just supporting for Supporting BSV application.\r\nWhen contacting support I had no thought I had been penalized 30 of my BSV.\r\nCustomer support quality I had to provide my evidence from CSV files which there was no liquidity pool CSV of deposits and withdrawals.\r\nI asked for for an audit and a conclusion discussion. Which I have had no update just a debate on what it means after 365 days.\r\nBelow I will post screenshots let you be the judge. If this is the future of defi we are going to fail.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2026-05-29T23:57:32.000Z",
  "media_url": null,
  "aip_verified": false,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKunverified!
Justinchellisvia treechat·1w
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "fe7cac32e322b4acc960760143963fe2f76b473a7900b29e59365da37fac9308",
  "block_height": 951278,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "DXS app review after losing 7 BSV because the liquidity pool took 30 percent of my 25 BSV.\r\nIt says refund after 365 days but it is plus 24 hours from blockchain time stamp.\r\nSo my liditity return 2 cents a day on average return of under 10 dollars.  At the time 7 BSV was worth 350. Just supporting for Supporting BSV application.\r\nWhen contacting support I had no thought I had been penalized 30 of my BSV.\r\nCustomer support quality I had to provide my evidence from CSV files which there was no liquidity pool CSV of deposits and withdrawals.\r\nI asked for for an audit and a conclusion discussion. Which I have had no update just a debate on what it means after 365 days.\r\nBelow I will post screenshots let you be the judge. If this is the future of defi we are going to fail.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 2,
  "like_count": 0,
  "timestamp": "2026-05-29T23:57:32.000Z",
  "media_url": null,
  "aip_verified": false,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKunverified!
Justinchellisvia treechat·8mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "e638a01526c3e9e5a0b5a658624ada5e05fe34e4243cb5a035d1b0a5d98d68d8",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Terranode running on Windows",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 1,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
Replying to #e638a015
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "4c421cee9c5642ba4f13c73b1aa20b5c9448ce71bb595c01b9bf331427535e81",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "Create start.py in teranode directory",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "e638a01526c3e9e5a0b5a658624ada5e05fe34e4243cb5a035d1b0a5d98d68d8",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "3507e885496872d4f7c54c45e3cfc6854cd71cd9a8513739eb49b41a8c9d716a",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Create start.py in teranode directory",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "92f8af83518d1c855ccad52a8b710af4523139e2c0f39c0b37d139c204cecdb6",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Save the script \r\nimport os\r\nimport sys\r\nimport datetime\r\nimport subprocess\r\nimport time\r\nimport signal\r\nimport shutil\r\nimport re\r\nfrom typing import Optional\r\nimport json\r\nfrom urllib.request import urlopen\r\nfrom urllib.error import URLError\r\nSCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\r\nSETTINGS_FILE = os.path.join(SCRIPT_DIR, 'base', 'settings_local.conf')\r\nBACKUP_FILE = f\"{SETTINGS_FILE}.backup.{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}\"\r\nGREEN = '\\033[0;32m'\r\nRED = '\\033[0;31m'\r\nYELLOW = '\\033[1;33m'\r\nNC = '\\033[0m'\r\nUSE_NGROK = True\r\ndef echo_info(msg: str):\r\n    print(f\"{GREEN}[INFO]{NC} {msg}\")\r\ndef echo_error(msg: str):\r\n    print(f\"{RED}[ERROR]{NC} {msg}\")\r\ndef echo_warning(msg: str):\r\n    print(f\"{YELLOW}[WARNING]{NC} {msg}\")\r\ndef parse_args():\r\n    global USE_NGROK\r\n    for arg in sys.argv[1:]:\r\n        if arg == '--no-ngrok':\r\n            USE_NGROK = False\r\n        elif arg in ['--help', '-h']:\r\n            print(f\"Usage: {sys.argv[0]} [--no-ngrok]\")\r\n            print(\"\")\r\n            print(\"Options:\")\r\n            print(\"  --no-ngrok    Skip ngrok setup (for users with existing domain/proxy)\")\r\n            print(\"  --help, -h    Show this help message\")\r\n            sys.exit(0)\r\ndef check_prerequisites():\r\n    echo_info(\"Checking prerequisites...\")\r\n    \r\n    if USE_NGROK:\r\n        if shutil.which('ngrok') is None:\r\n            echo_error(\"ngrok is not installed. Please install ngrok and configure it with an auth token.\")\r\n            echo_error(\"Visit https://ngrok.com/download for installation instructions.\")\r\n            echo_error(\"Or use --no-ngrok if you have your own domain/proxy setup.\")\r\n            sys.exit(1)\r\n    \r\n    if shutil.which('docker') is None:\r\n        echo_error(\"Docker is not installed. Please install Docker.\")\r\n        sys.exit(1)\r\n    \r\n    docker_compose_cmd = shutil.which('docker-compose') or (shutil.which('docker') and 'docker compose')\r\n    if docker_compose_cmd is None:\r\n        echo_error(\"Docker Compose is not installed. Please install Docker Compose.\")\r\n        sys.exit(1)\r\n    \r\n    if not os.path.isfile(SETTINGS_FILE):\r\n        echo_error(f\"Settings file not found at: {SETTINGS_FILE}\")\r\n        sys.exit(1)\r\n    \r\n    echo_info(\"All prerequisites met.\")\r\ndef process_ngrok_url(input_str: str) -> tuple:\r\n    input_str = input_str.rstrip('/')\r\n    if input_str.startswith(('http://', 'https://')):\r\n        url = input_str\r\n        domain = url.split('://', 1)[1]\r\n    else:\r\n        domain = input_str\r\n        url = f\"https://{input_str}\"\r\n    domain = domain.split('/', 1)[0]\r\n    return url, domain\r\ndef prompt_for_inputs():\r\n    print()\r\n    echo_info(\"=== Teratestnet Configuration ===\")\r\n    print()\r\n    echo_info(\"Node Operation Mode Selection\")\r\n    print()\r\n    print(\"Please select how you want to run your Teranode:\")\r\n    print(\"  1. Full mode - Fully participate in the network (requires ngrok or public domain)\")\r\n    print(\"  2. Listen-only mode - Only receive blocks, no mining or transaction relay\")\r\n    print()\r\n    echo_info(\"Listen-only mode is ideal for monitoring the network without external access\")\r\n    print()\r\n    mode_choice = input(\"Select mode (1 for Full, 2 for Listen-only): \").strip()\r\n    if mode_choice == \"2\":\r\n        listen_mode = \"listen_only\"\r\n        echo_info(\"Listen-only mode selected - ngrok configuration not required\")\r\n        global USE_NGROK\r\n        USE_NGROK = False\r\n        ngrok_url = \"http://localhost\"\r\n        ngrok_domain = \"localhost\"\r\n    elif mode_choice == \"1\":\r\n        listen_mode = \"full\"\r\n        echo_info(\"Full mode selected - external access configuration required\")\r\n        if USE_NGROK:\r\n            url_input = input(\"Enter your ngrok domain (e.g., example.ngrok-free.app): \").strip()\r\n        else:\r\n            url_input = input(\"Enter your domain/URL (e.g., teranode.example.com or https://teranode.example.com): \").strip()\r\n        if not url_input:\r\n            echo_error(\"Domain/URL cannot be empty for full mode\")\r\n            sys.exit(1)\r\n        ngrok_url, ngrok_domain = process_ngrok_url(url_input)\r\n    else:\r\n        echo_error(\"Invalid selection. Please run the script again and select 1 or 2\")\r\n        sys.exit(1)\r\n    print()\r\n    echo_info(\"RPC Credentials Configuration\")\r\n    echo_info(\"You can either:\")\r\n    print(\"  1. Set RPC credentials now (automatic)\")\r\n    print(\"  2. Configure them manually in settings.conf later\")\r\n    print()\r\n    echo_info(\"Note: RPC credentials are required for remote access to your node\")\r\n    print()\r\n    set_rpc_creds = input(\"Would you like to set RPC credentials now? (y/n): \").strip().lower()\r\n    rpc_user = \"\"\r\n    rpc_pass = \"\"\r\n    if set_rpc_creds == 'y':\r\n        rpc_user = input(\"Enter RPC username: \").strip()\r\n        if not rpc_user:\r\n            echo_error(\"RPC username cannot be empty\")\r\n            sys.exit(1)\r\n        rpc_pass = input(\"Enter RPC password: \")\r\n        rpc_pass_confirm = input(\"Confirm RPC password: \")\r\n        if rpc_pass != rpc_pass_confirm:\r\n            echo_error(\"Passwords do not match\")\r\n            sys.exit(1)\r\n        if not rpc_pass:\r\n            echo_error(\"RPC password cannot be empty\")\r\n            sys.exit(1)\r\n    else:\r\n        echo_info(\"Skipping RPC credentials setup\")\r\n        echo_info(f\"You can add them manually to {SETTINGS_FILE}:\")\r\n        print(\"  rpc_user = your_username\")\r\n        print(\"  rpc_pass = your_password\")\r\n    client_name = input(\"Enter Human Readable Client Name (for web interface viewing only) (optional, press Enter to skip): \").strip()\r\n    if client_name and len(client_name) > 100:\r\n        echo_warning(f\"Client Name is quite long ({len(client_name)} characters). Consider using a shorter identifier.\")\r\n    mining_enabled = \"false\"\r\n    mining_address = \"\"\r\n    miner_id = \"\"\r\n    if listen_mode == \"full\":\r\n        print()\r\n        echo_info(\"Mining Configuration\")\r\n        echo_info(\"Note: Mining requires computational resources and will use CPU\")\r\n        print()\r\n        enable_mining = input(\"Would you like to enable CPU mining? (y/n): \").strip().lower()\r\n        if enable_mining == 'y':\r\n            mining_enabled = \"true\"\r\n            mining_address = input(\"Enter Bitcoin address for mining rewards: \").strip()\r\n            while not mining_address:\r\n                echo_error(\"Mining address cannot be empty when mining is enabled\")\r\n                mining_address = input(\"Enter Bitcoin address for mining rewards: \").strip()\r\n            miner_id = input(\"Enter Miner ID/Signature (e.g., /YourMinerID/) (optional, press Enter to skip): \").strip()\r\n            if not miner_id:\r\n                miner_id = \"/Teratestnet/\"\r\n                echo_info(f\"Using default miner ID: {miner_id}\")\r\n            echo_info(\"Mining will be enabled with:\")\r\n            print(f\"  - Mining address: {mining_address}\")\r\n            print(f\"  - Miner ID: {miner_id}\")\r\n            print(\"  - CPU threads: 2\")\r\n        else:\r\n            echo_info(\"Mining disabled\")\r\n    else:\r\n        echo_info(\"Mining is not available in listen-only mode\")\r\n    print()\r\n    echo_info(\"Configuration summary:\")\r\n    print(f\"  - Mode: {'Listen-only' if listen_mode == 'listen_only' else 'Full'}\")\r\n    if listen_mode == \"full\":\r\n        if USE_NGROK:\r\n            print(f\"  - Ngrok Domain: {ngrok_domain}\")\r\n        else:\r\n            print(f\"  - Domain: {ngrok_domain}\")\r\n        print(f\"  - Full URL: {ngrok_url}\")\r\n    if rpc_user:\r\n        print(f\"  - RPC Username: {rpc_user}\")\r\n        print(\"  - RPC Password: [hidden]\")\r\n    else:\r\n        print(\"  - RPC Credentials: To be configured manually\")\r\n    if mining_enabled == \"true\":\r\n        print(\"  - Mining: Enabled\")\r\n        print(f\"  - Mining Address: {mining_address}\")\r\n        print(f\"  - Miner ID: {miner_id}\")\r\n    else:\r\n        print(\"  - Mining: Disabled\")\r\n    if client_name:\r\n        print(f\"  - Client Name: {client_name}\")\r\n    print()\r\n    confirm = input(\"Is this correct? (y/n): \").strip().lower()\r\n    if confirm != 'y':\r\n        echo_info(\"Configuration cancelled.\")\r\n        sys.exit(0)\r\n    return {\r\n        'listen_mode': listen_mode,\r\n        'ngrok_url': ngrok_url if listen_mode == 'full' else None,\r\n        'ngrok_domain': ngrok_domain if listen_mode == 'full' else None,\r\n        'rpc_user': rpc_user,\r\n        'rpc_pass': rpc_pass,\r\n        'client_name': client_name,\r\n        'mining_enabled': mining_enabled,\r\n        'mining_address': mining_address,\r\n        'miner_id': miner_id\r\n    }\r\ndef backup_settings():\r\n    echo_info(\"Creating backup of settings.conf...\")\r\n    shutil.copy(SETTINGS_FILE, BACKUP_FILE)\r\n    echo_info(f\"Backup created at: {BACKUP_FILE}\")\r\ndef update_settings(config: dict):\r\n    echo_info(\"Updating settings.conf...\")\r\n    with open(SETTINGS_FILE, 'r') as f:\r\n        lines = f.readlines()\r\n    def update_or_add(key: str, value: str):\r\n        for i, line in enumerate(lines):\r\n            if line.strip().startswith(key):\r\n                lines[i] = f\"{key} = {value}\\n\"\r\n                return True\r\n        lines.append(f\"{key} = {value}\\n\")\r\n        return False\r\n    # Update listen_mode\r\n    updated = update_or_add('listen_mode', config['listen_mode'])\r\n    echo_info(f\"{'Updated' if updated else 'Added'} listen_mode to: {config['listen_mode']}\")\r\n    if config['listen_mode'] == 'full':\r\n        key = 'asset_httpPublicAddress.docker.m'\r\n        value = f\"{config['ngrok_url']}/api/v1\"\r\n        updated = update_or_add(key, value)\r\n        echo_info(f\"{'Updated' if updated else 'Added'} asset_httpPublicAddress\")\r\n    if config['rpc_user']:\r\n        updated = update_or_add('rpc_user', config['rpc_user'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} rpc_user\")\r\n        updated = update_or_add('rpc_pass', config['rpc_pass'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} rpc_pass\")\r\n    else:\r\n        echo_warning(\"RPC credentials not configured. Remember to add them manually to settings.conf\")\r\n    if config['miner_id']:\r\n        updated = update_or_add('coinbase_arbitrary_text', config['miner_id'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} coinbase_arbitrary_text (Miner ID)\")\r\n    if config['client_name']:\r\n        updated = update_or_add('clientName', config['client_name'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} clientName (Client Name)\")\r\n    with open(SETTINGS_FILE, 'w') as f:\r\n        f.writelines(lines)\r\n    echo_info(\"Settings updated successfully.\")\r\ndef start_docker_compose(config: dict):\r\n    echo_info(\"Starting Teratestnet with Docker Compose...\")\r\n    os.chdir(SCRIPT_DIR)\r\n    os.environ['MINING_ENABLED'] = config['mining_enabled']\r\n    os.environ['MINING_ADDRESS'] = config['mining_address']\r\n    os.environ['MINING_SIG'] = config['miner_id']\r\n    rpc_user = config['rpc_user'] or 'bitcoin'\r\n    rpc_pass = config['rpc_pass'] or 'bitcoin'\r\n    os.environ['RPC_USER'] = rpc_user\r\n    os.environ['RPC_PASS'] = rpc_pass\r\n    if shutil.which('docker compose'):\r\n        compose_base = ['docker', 'compose']\r\n    else:\r\n        compose_base = ['docker-compose']\r\n    if config['mining_enabled'] == 'true':\r\n        echo_info(\"Mining is enabled, starting with mining profile...\")\r\n        cmd = compose_base + ['--profile', 'mining', 'up', '-d']\r\n    else:\r\n        cmd = compose_base + ['up', '-d']\r\n    echo_info(f\"Running: {' '.join(cmd)}\")\r\n    try:\r\n        subprocess.run(cmd, check=True)\r\n        echo_info(\"Docker Compose started successfully.\")\r\n        if config['mining_enabled'] == 'true':\r\n            echo_info(\"CPU miner container will start mining shortly...\")\r\n    except subprocess.CalledProcessError:\r\n        echo_error(\"Failed to start Docker Compose.\")\r\n        sys.exit(1)\r\ndef start_ngrok(config: dict):\r\n    if not USE_NGROK:\r\n        if config['listen_mode'] == 'listen_only':\r\n            echo_info(\"Skipping ngrok setup (listen-only mode)\")\r\n        else:\r\n            echo_info(\"Skipping ngrok setup (--no-ngrok flag set)\")\r\n        return\r\n    echo_info(\"Checking for existing ngrok process...\")\r\n    # Cross-platform check using ngrok's local API\r\n    def is_ngrok_running_with_domain():\r\n        try:\r\n            with urlopen('http://localhost:4040/api/tunnels') as response:\r\n                data = json.loads(response.read().decode())\r\n                for tunnel in data.get('tunnels', []):\r\n                    public_url = tunnel.get('public_url', '')\r\n                    if config['ngrok_domain'] in public_url:\r\n                        return True\r\n                return False\r\n        except URLError:\r\n            return False\r\n    if is_ngrok_running_with_domain():\r\n        echo_info(f\"ngrok is already running with domain: {config['ngrok_domain']}\")\r\n        echo_info(\"Using existing ngrok tunnel\")\r\n        echo_info(\"You can check ngrok status at: http://localhost:4040\")\r\n        echo_info(f\"Public URL: {config['ngrok_url']}\")\r\n        return\r\n    else:\r\n        echo_info(\"No matching ngrok tunnel found (or ngrok not running).\")\r\n    print()\r\n    echo_warning(\"=========================================\")\r\n    echo_warning(\"NGROK SETUP REQUIRED\")\r\n    echo_warning(\"=========================================\")\r\n    print()\r\n    echo_info(\"Please open a new terminal window and run the following command:\")\r\n    print()\r\n    print(f\"{GREEN}    ngrok http --url={config['ngrok_domain']} 8090{NC}\")\r\n    print()\r\n    echo_info(f\"This will create a tunnel from {config['ngrok_url']} to your local Teranode asset service.\")\r\n    print()\r\n    echo_info(\"After starting ngrok, you can verify it's running at: http://localhost:4040\")\r\n    print()\r\n    input(\"Press Enter once ngrok is running in another terminal... \")\r\n    echo_info(\"Verifying ngrok connection...\")\r\n    max_attempts = 5\r\n    attempt = 1\r\n    wait_time = 2\r\n    while attempt <= max_attempts:\r\n        if is_ngrok_running_with_domain():\r\n            echo_info(\"ngrok verified successfully!\")\r\n            echo_info(f\"Tunnel established: {config['ngrok_url']} -> localhost:8090\")\r\n            echo_info(\"You can monitor ngrok at: http://localhost:4040\")\r\n            return\r\n        else:\r\n            echo_warning(\"ngrok tunnel not yet established or not matching domain...\")\r\n        if attempt == max_attempts:\r\n            echo_error(f\"Could not verify ngrok is running with domain: {config['ngrok_domain']}\")\r\n            echo_error(\"Please ensure you ran the command exactly as shown above\")\r\n            echo_error(\"To retry, stop this script and run it again\")\r\n            sys.exit(1)\r\n        echo_info(f\"Retrying verification (attempt {attempt}/{max_attempts})...\")\r\n        time.sleep(wait_time)\r\n        attempt += 1\r\ndef set_fsm_state_running():\r\n    echo_info(\"Setting FSM state to RUNNING...\")\r\n    \r\n    max_attempts = 30  # Increased for ~5 minutes total timeout\r\n    attempt = 1\r\n    wait_time = 10  # Increased wait time between checks\r\n    \r\n    echo_info(\"Waiting for blockchain service to be ready...\")\r\n    \r\n    while attempt <= max_attempts:\r\n        echo_info(f\"Checking blockchain container status (attempt {attempt}/{max_attempts})...\")\r\n        \r\n        try:\r\n            ps_output = subprocess.run(['docker', 'ps'], capture_output=True, text=True, check=True)\r\n            if 'blockchain' in ps_output.stdout:\r\n                try:\r\n                    # Capture output for better debugging\r\n                    check_output = subprocess.run(['docker', 'exec', 'blockchain', 'teranode-cli', 'getfsmstate'], capture_output=True, text=True, check=True)\r\n                    echo_info(f\"Blockchain container is ready (current FSM state: {check_output.stdout.strip()})\")\r\n                    break\r\n                except subprocess.CalledProcessError as e:\r\n                    echo_info(f\"Container is running but not yet responsive (error: {e.stderr.strip() or 'no output'})...\")\r\n            else:\r\n                echo_info(\"Blockchain container not yet running...\")\r\n        except subprocess.CalledProcessError as e:\r\n            echo_info(f\"Error checking docker ps: {e.stderr.strip()}...\")\r\n        \r\n        if attempt == max_attempts:\r\n            echo_error(f\"Blockchain container failed to become responsive after {max_attempts} attempts (~5 minutes)\")\r\n            echo_error(\"Cannot set FSM state to RUNNING automatically\")\r\n            echo_warning(\"Check 'docker logs blockchain' for errors. If no ",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "content_size": 20647,
  "content_truncated": true,
  "map_content_size": 20647,
  "map_content_truncated": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
Replying to #27b6399d
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "a1efb97afe2e988dbc052e7f127e6595dc3e3e72b04a975b7c41bc88d18eaae8",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "Docker-Compose. Yml. File\r\n\r\n\r\n\r\nx-teranode-settings:\r\n\u00a0 &teranode-settings\r\n\u00a0 environment:\r\n\u00a0 \u00a0 network: \"teratestnet\"\r\n\u00a0 \u00a0 p2p_bootstrapAddresses: \"/dns4/teranode-bootstrap-stage.bsvb.tech/tcp/9901/p2p/12D3KooWJ6kQHAR65xkA34NABsNVAJyVxPWh8JUSo1vtZsTyw4GD\"\r\n\u00a0 \u00a0 # logLevel: \"DEBUG\"\r\n\u00a0 \u00a0 # enable this when using your laptop or a server without a public ip\r\n\u00a0 \u00a0 # someOtherSetting: \"value\"\r\n\r\n\r\nnetworks:\r\n\u00a0 teranode-network:\r\n\u00a0 \u00a0 name: my-teranode-network\r\n\u00a0 \u00a0 # if your docker setup supports IPv6, you can enable it here\r\n\u00a0 \u00a0 # enable_ipv6: true\r\n\r\n\r\nvolumes:\r\n\u00a0 nginx-cache:\r\n\u00a0 postgres-data:\r\n\r\n\r\nservices:\r\n\u00a0 # Initialize directories with correct ownership\r\n\u00a0 # Note: Runs as root to create directories and set ownership before other services start\r\n\u00a0 data-init:\r\n\u00a0 \u00a0 image: alpine:latest\r\n\u00a0 \u00a0 volumes:\r\n\u00a0 \u00a0 \u00a0 - ${DATA_PATH}:/data\r\n\u00a0 \u00a0 \u00a0 - ./scripts/init-data.sh:/init-data.sh:ro\r\n\u00a0 \u00a0 environment:\r\n\u00a0 \u00a0 \u00a0 - USER_ID=${USER_ID}\r\n\u00a0 \u00a0 \u00a0 - GROUP_ID=${GROUP_ID}\r\n\u00a0 \u00a0 command: sh /init-data.sh\r\n\u00a0 \u00a0 user: \"0:0\" \u00a0# Required for chown operations\r\n\r\n\r\n\u00a0 # Teranode micro-services\r\n\u00a0 blockchain:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: blockchain\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\u00a0 \u00a0 depends_on:\r\n\u00a0 \u00a0 \u00a0 - data-init\r\n\r\n\r\n\u00a0 asset:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: asset\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\r\n\r\n\u00a0 asset-cache:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 service: asset-cache\r\n\r\n\r\n\u00a0 rpc:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: rpc\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\r\n\r\n\u00a0 subtreevalidation:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: subtreevalidation\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\r\n\r\n\u00a0 blockvalidation:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: blockvalidation\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\r\n\r\n\u00a0 blockassembly:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: blockassembly\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\r\n\r\n\u00a0 peer:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-teranode.yml\r\n\u00a0 \u00a0 \u00a0 service: peer\r\n\u00a0 \u00a0 <<: *teranode-settings\r\n\r\n\r\n\u00a0 # uses lots of disk space\r\n\u00a0 # \u00a0blockpersister:\r\n\u00a0 # \u00a0 \u00a0extends:\r\n\u00a0 # \u00a0 \u00a0 \u00a0file: ../base/docker-teranode.yml\r\n\u00a0 # \u00a0 \u00a0 \u00a0service: blockpersister\r\n\u00a0 # \u00a0 \u00a0<<: *teranode-settings\r\n\r\n\r\n\u00a0 # shared services\r\n\u00a0 postgres:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 service: postgres\r\n\u00a0 \u00a0 volumes:\r\n\u00a0 \u00a0 \u00a0 - postgres-data:/var/lib/postgresql/data\r\n\r\n\r\n\u00a0 kafka-shared:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 service: kafka-shared\r\n\r\n\r\n# \u00a0kafka-console-shared:\r\n# \u00a0 \u00a0extends:\r\n# \u00a0 \u00a0 \u00a0file: ./base/docker-services.yml\r\n# \u00a0 \u00a0 \u00a0service: kafka-console-shared\r\n\r\n\r\n\u00a0 aerospike:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 # Community Edition\r\n\u00a0 \u00a0 \u00a0 service: aerospike\r\n\u00a0 \u00a0 \u00a0 # Enterprise Edition, evaluation mode, single node\r\n\u00a0 \u00a0 \u00a0 # service: aerospike-ee\r\n\r\n\r\n\u00a0 aerospike-exporter:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 service: aerospike-exporter\r\n\r\n\r\n\u00a0 prometheus:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 service: prometheus\r\n\r\n\r\n\u00a0 grafana:\r\n\u00a0 \u00a0 extends:\r\n\u00a0 \u00a0 \u00a0 file: ./base/docker-services.yml\r\n\u00a0 \u00a0 \u00a0 service: grafana\r\n\r\n\r\n\u00a0 # CPU Miner (optional - configured via startup script)\r\n\u00a0 cpuminer:\r\n\u00a0 \u00a0 image: ghcr.io/bitcoin-sv/cpuminer:latest\r\n\u00a0 \u00a0 container_name: cpuminer\r\n\u00a0 \u00a0 networks:\r\n\u00a0 \u00a0 \u00a0 - teranode-network\r\n\u00a0 \u00a0 environment:\r\n\u00a0 \u00a0 \u00a0 MINING_ENABLED: \"${MINING_ENABLED:-false}\"\r\n\u00a0 \u00a0 \u00a0 MINING_ADDRESS: \"${MINING_ADDRESS:-}\"\r\n\u00a0 \u00a0 \u00a0 MINING_SIG: \"${MINING_SIG:-}\"\r\n\u00a0 \u00a0 \u00a0 RPC_USER: \"${RPC_USER:-bitcoin}\"\r\n\u00a0 \u00a0 \u00a0 RPC_PASS: \"${RPC_PASS:-bitcoin}\"\r\n\u00a0 \u00a0 entrypoint: [\"/bin/sh\", \"-c\"]\r\n\u00a0 \u00a0 command: >\r\n\u00a0 \u00a0 \u00a0 \"\r\n\u00a0 \u00a0 \u00a0 if [ \\\"$$MINING_ENABLED\\\" = \\\"true\\\" ] && [ -n \\\"$$MINING_ADDRESS\\\" ]; then\r\n\u00a0 \u00a0 \u00a0 \u00a0 echo 'Starting CPU miner...';\r\n\u00a0 \u00a0 \u00a0 \u00a0 echo 'Mining address: '$$MINING_ADDRESS;\r\n\u00a0 \u00a0 \u00a0 \u00a0 echo 'Miner ID: '$$MINING_SIG;\r\n\u00a0 \u00a0 \u00a0 \u00a0 exec ./minerd --url=http://rpc:9292 --userpass=$$RPC_USER:$$RPC_PASS --coinbase-addr=$$MINING_ADDRESS --coinbase-sig=\\\"$$MINING_SIG\\\" --threads=2;\r\n\u00a0 \u00a0 \u00a0 else\r\n\u00a0 \u00a0 \u00a0 \u00a0 echo 'Mining disabled or not configured. Container will exit.';\r\n\u00a0 \u00a0 \u00a0 \u00a0 exit 0;\r\n\u00a0 \u00a0 \u00a0 fi\r\n\u00a0 \u00a0 \u00a0 \"\r\n\u00a0 \u00a0 profiles:\r\n\u00a0 \u00a0 \u00a0 - mining\r\n\u00a0 \u00a0 restart: unless-stopped\r\n\u00a0 \u00a0 depends_on:\r\n\u00a0 \u00a0 \u00a0 rpc:\r\n\u00a0 \u00a0 \u00a0 \u00a0 condition: service_healthy",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "27b6399d79e105f17d9d28b33e9fab0c18f9c9a1a3d15547e25fe6ed1de1a1b4",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
Replying to #3507e885
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "1d76b68e6ec3026ffc3110bfbdadc986eb3763bbcb0bd95b1b6588e7cad7a1c1",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "Save the script \r\nimport os\r\nimport sys\r\nimport datetime\r\nimport subprocess\r\nimport time\r\nimport signal\r\nimport shutil\r\nimport re\r\nfrom typing import Optional\r\nimport json\r\nfrom urllib.request import urlopen\r\nfrom urllib.error import URLError\r\nSCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\r\nSETTINGS_FILE = os.path.join(SCRIPT_DIR, 'base', 'settings_local.conf')\r\nBACKUP_FILE = f\"{SETTINGS_FILE}.backup.{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}\"\r\nGREEN = '\\033[0;32m'\r\nRED = '\\033[0;31m'\r\nYELLOW = '\\033[1;33m'\r\nNC = '\\033[0m'\r\nUSE_NGROK = True\r\ndef echo_info(msg: str):\r\n    print(f\"{GREEN}[INFO]{NC} {msg}\")\r\ndef echo_error(msg: str):\r\n    print(f\"{RED}[ERROR]{NC} {msg}\")\r\ndef echo_warning(msg: str):\r\n    print(f\"{YELLOW}[WARNING]{NC} {msg}\")\r\ndef parse_args():\r\n    global USE_NGROK\r\n    for arg in sys.argv[1:]:\r\n        if arg == '--no-ngrok':\r\n            USE_NGROK = False\r\n        elif arg in ['--help', '-h']:\r\n            print(f\"Usage: {sys.argv[0]} [--no-ngrok]\")\r\n            print(\"\")\r\n            print(\"Options:\")\r\n            print(\"  --no-ngrok    Skip ngrok setup (for users with existing domain/proxy)\")\r\n            print(\"  --help, -h    Show this help message\")\r\n            sys.exit(0)\r\ndef check_prerequisites():\r\n    echo_info(\"Checking prerequisites...\")\r\n    \r\n    if USE_NGROK:\r\n        if shutil.which('ngrok') is None:\r\n            echo_error(\"ngrok is not installed. Please install ngrok and configure it with an auth token.\")\r\n            echo_error(\"Visit https://ngrok.com/download for installation instructions.\")\r\n            echo_error(\"Or use --no-ngrok if you have your own domain/proxy setup.\")\r\n            sys.exit(1)\r\n    \r\n    if shutil.which('docker') is None:\r\n        echo_error(\"Docker is not installed. Please install Docker.\")\r\n        sys.exit(1)\r\n    \r\n    docker_compose_cmd = shutil.which('docker-compose') or (shutil.which('docker') and 'docker compose')\r\n    if docker_compose_cmd is None:\r\n        echo_error(\"Docker Compose is not installed. Please install Docker Compose.\")\r\n        sys.exit(1)\r\n    \r\n    if not os.path.isfile(SETTINGS_FILE):\r\n        echo_error(f\"Settings file not found at: {SETTINGS_FILE}\")\r\n        sys.exit(1)\r\n    \r\n    echo_info(\"All prerequisites met.\")\r\ndef process_ngrok_url(input_str: str) -> tuple:\r\n    input_str = input_str.rstrip('/')\r\n    if input_str.startswith(('http://', 'https://')):\r\n        url = input_str\r\n        domain = url.split('://', 1)[1]\r\n    else:\r\n        domain = input_str\r\n        url = f\"https://{input_str}\"\r\n    domain = domain.split('/', 1)[0]\r\n    return url, domain\r\ndef prompt_for_inputs():\r\n    print()\r\n    echo_info(\"=== Teratestnet Configuration ===\")\r\n    print()\r\n    echo_info(\"Node Operation Mode Selection\")\r\n    print()\r\n    print(\"Please select how you want to run your Teranode:\")\r\n    print(\"  1. Full mode - Fully participate in the network (requires ngrok or public domain)\")\r\n    print(\"  2. Listen-only mode - Only receive blocks, no mining or transaction relay\")\r\n    print()\r\n    echo_info(\"Listen-only mode is ideal for monitoring the network without external access\")\r\n    print()\r\n    mode_choice = input(\"Select mode (1 for Full, 2 for Listen-only): \").strip()\r\n    if mode_choice == \"2\":\r\n        listen_mode = \"listen_only\"\r\n        echo_info(\"Listen-only mode selected - ngrok configuration not required\")\r\n        global USE_NGROK\r\n        USE_NGROK = False\r\n        ngrok_url = \"http://localhost\"\r\n        ngrok_domain = \"localhost\"\r\n    elif mode_choice == \"1\":\r\n        listen_mode = \"full\"\r\n        echo_info(\"Full mode selected - external access configuration required\")\r\n        if USE_NGROK:\r\n            url_input = input(\"Enter your ngrok domain (e.g., example.ngrok-free.app): \").strip()\r\n        else:\r\n            url_input = input(\"Enter your domain/URL (e.g., teranode.example.com or https://teranode.example.com): \").strip()\r\n        if not url_input:\r\n            echo_error(\"Domain/URL cannot be empty for full mode\")\r\n            sys.exit(1)\r\n        ngrok_url, ngrok_domain = process_ngrok_url(url_input)\r\n    else:\r\n        echo_error(\"Invalid selection. Please run the script again and select 1 or 2\")\r\n        sys.exit(1)\r\n    print()\r\n    echo_info(\"RPC Credentials Configuration\")\r\n    echo_info(\"You can either:\")\r\n    print(\"  1. Set RPC credentials now (automatic)\")\r\n    print(\"  2. Configure them manually in settings.conf later\")\r\n    print()\r\n    echo_info(\"Note: RPC credentials are required for remote access to your node\")\r\n    print()\r\n    set_rpc_creds = input(\"Would you like to set RPC credentials now? (y/n): \").strip().lower()\r\n    rpc_user = \"\"\r\n    rpc_pass = \"\"\r\n    if set_rpc_creds == 'y':\r\n        rpc_user = input(\"Enter RPC username: \").strip()\r\n        if not rpc_user:\r\n            echo_error(\"RPC username cannot be empty\")\r\n            sys.exit(1)\r\n        rpc_pass = input(\"Enter RPC password: \")\r\n        rpc_pass_confirm = input(\"Confirm RPC password: \")\r\n        if rpc_pass != rpc_pass_confirm:\r\n            echo_error(\"Passwords do not match\")\r\n            sys.exit(1)\r\n        if not rpc_pass:\r\n            echo_error(\"RPC password cannot be empty\")\r\n            sys.exit(1)\r\n    else:\r\n        echo_info(\"Skipping RPC credentials setup\")\r\n        echo_info(f\"You can add them manually to {SETTINGS_FILE}:\")\r\n        print(\"  rpc_user = your_username\")\r\n        print(\"  rpc_pass = your_password\")\r\n    client_name = input(\"Enter Human Readable Client Name (for web interface viewing only) (optional, press Enter to skip): \").strip()\r\n    if client_name and len(client_name) > 100:\r\n        echo_warning(f\"Client Name is quite long ({len(client_name)} characters). Consider using a shorter identifier.\")\r\n    mining_enabled = \"false\"\r\n    mining_address = \"\"\r\n    miner_id = \"\"\r\n    if listen_mode == \"full\":\r\n        print()\r\n        echo_info(\"Mining Configuration\")\r\n        echo_info(\"Note: Mining requires computational resources and will use CPU\")\r\n        print()\r\n        enable_mining = input(\"Would you like to enable CPU mining? (y/n): \").strip().lower()\r\n        if enable_mining == 'y':\r\n            mining_enabled = \"true\"\r\n            mining_address = input(\"Enter Bitcoin address for mining rewards: \").strip()\r\n            while not mining_address:\r\n                echo_error(\"Mining address cannot be empty when mining is enabled\")\r\n                mining_address = input(\"Enter Bitcoin address for mining rewards: \").strip()\r\n            miner_id = input(\"Enter Miner ID/Signature (e.g., /YourMinerID/) (optional, press Enter to skip): \").strip()\r\n            if not miner_id:\r\n                miner_id = \"/Teratestnet/\"\r\n                echo_info(f\"Using default miner ID: {miner_id}\")\r\n            echo_info(\"Mining will be enabled with:\")\r\n            print(f\"  - Mining address: {mining_address}\")\r\n            print(f\"  - Miner ID: {miner_id}\")\r\n            print(\"  - CPU threads: 2\")\r\n        else:\r\n            echo_info(\"Mining disabled\")\r\n    else:\r\n        echo_info(\"Mining is not available in listen-only mode\")\r\n    print()\r\n    echo_info(\"Configuration summary:\")\r\n    print(f\"  - Mode: {'Listen-only' if listen_mode == 'listen_only' else 'Full'}\")\r\n    if listen_mode == \"full\":\r\n        if USE_NGROK:\r\n            print(f\"  - Ngrok Domain: {ngrok_domain}\")\r\n        else:\r\n            print(f\"  - Domain: {ngrok_domain}\")\r\n        print(f\"  - Full URL: {ngrok_url}\")\r\n    if rpc_user:\r\n        print(f\"  - RPC Username: {rpc_user}\")\r\n        print(\"  - RPC Password: [hidden]\")\r\n    else:\r\n        print(\"  - RPC Credentials: To be configured manually\")\r\n    if mining_enabled == \"true\":\r\n        print(\"  - Mining: Enabled\")\r\n        print(f\"  - Mining Address: {mining_address}\")\r\n        print(f\"  - Miner ID: {miner_id}\")\r\n    else:\r\n        print(\"  - Mining: Disabled\")\r\n    if client_name:\r\n        print(f\"  - Client Name: {client_name}\")\r\n    print()\r\n    confirm = input(\"Is this correct? (y/n): \").strip().lower()\r\n    if confirm != 'y':\r\n        echo_info(\"Configuration cancelled.\")\r\n        sys.exit(0)\r\n    return {\r\n        'listen_mode': listen_mode,\r\n        'ngrok_url': ngrok_url if listen_mode == 'full' else None,\r\n        'ngrok_domain': ngrok_domain if listen_mode == 'full' else None,\r\n        'rpc_user': rpc_user,\r\n        'rpc_pass': rpc_pass,\r\n        'client_name': client_name,\r\n        'mining_enabled': mining_enabled,\r\n        'mining_address': mining_address,\r\n        'miner_id': miner_id\r\n    }\r\ndef backup_settings():\r\n    echo_info(\"Creating backup of settings.conf...\")\r\n    shutil.copy(SETTINGS_FILE, BACKUP_FILE)\r\n    echo_info(f\"Backup created at: {BACKUP_FILE}\")\r\ndef update_settings(config: dict):\r\n    echo_info(\"Updating settings.conf...\")\r\n    with open(SETTINGS_FILE, 'r') as f:\r\n        lines = f.readlines()\r\n    def update_or_add(key: str, value: str):\r\n        for i, line in enumerate(lines):\r\n            if line.strip().startswith(key):\r\n                lines[i] = f\"{key} = {value}\\n\"\r\n                return True\r\n        lines.append(f\"{key} = {value}\\n\")\r\n        return False\r\n    # Update listen_mode\r\n    updated = update_or_add('listen_mode', config['listen_mode'])\r\n    echo_info(f\"{'Updated' if updated else 'Added'} listen_mode to: {config['listen_mode']}\")\r\n    if config['listen_mode'] == 'full':\r\n        key = 'asset_httpPublicAddress.docker.m'\r\n        value = f\"{config['ngrok_url']}/api/v1\"\r\n        updated = update_or_add(key, value)\r\n        echo_info(f\"{'Updated' if updated else 'Added'} asset_httpPublicAddress\")\r\n    if config['rpc_user']:\r\n        updated = update_or_add('rpc_user', config['rpc_user'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} rpc_user\")\r\n        updated = update_or_add('rpc_pass', config['rpc_pass'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} rpc_pass\")\r\n    else:\r\n        echo_warning(\"RPC credentials not configured. Remember to add them manually to settings.conf\")\r\n    if config['miner_id']:\r\n        updated = update_or_add('coinbase_arbitrary_text', config['miner_id'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} coinbase_arbitrary_text (Miner ID)\")\r\n    if config['client_name']:\r\n        updated = update_or_add('clientName', config['client_name'])\r\n        echo_info(f\"{'Updated' if updated else 'Added'} clientName (Client Name)\")\r\n    with open(SETTINGS_FILE, 'w') as f:\r\n        f.writelines(lines)\r\n    echo_info(\"Settings updated successfully.\")\r\ndef start_docker_compose(config: dict):\r\n    echo_info(\"Starting Teratestnet with Docker Compose...\")\r\n    os.chdir(SCRIPT_DIR)\r\n    os.environ['MINING_ENABLED'] = config['mining_enabled']\r\n    os.environ['MINING_ADDRESS'] = config['mining_address']\r\n    os.environ['MINING_SIG'] = config['miner_id']\r\n    rpc_user = config['rpc_user'] or 'bitcoin'\r\n    rpc_pass = config['rpc_pass'] or 'bitcoin'\r\n    os.environ['RPC_USER'] = rpc_user\r\n    os.environ['RPC_PASS'] = rpc_pass\r\n    if shutil.which('docker compose'):\r\n        compose_base = ['docker', 'compose']\r\n    else:\r\n        compose_base = ['docker-compose']\r\n    if config['mining_enabled'] == 'true':\r\n        echo_info(\"Mining is enabled, starting with mining profile...\")\r\n        cmd = compose_base + ['--profile', 'mining', 'up', '-d']\r\n    else:\r\n        cmd = compose_base + ['up', '-d']\r\n    echo_info(f\"Running: {' '.join(cmd)}\")\r\n    try:\r\n        subprocess.run(cmd, check=True)\r\n        echo_info(\"Docker Compose started successfully.\")\r\n        if config['mining_enabled'] == 'true':\r\n            echo_info(\"CPU miner container will start mining shortly...\")\r\n    except subprocess.CalledProcessError:\r\n        echo_error(\"Failed to start Docker Compose.\")\r\n        sys.exit(1)\r\ndef start_ngrok(config: dict):\r\n    if not USE_NGROK:\r\n        if config['listen_mode'] == 'listen_only':\r\n            echo_info(\"Skipping ngrok setup (listen-only mode)\")\r\n        else:\r\n            echo_info(\"Skipping ngrok setup (--no-ngrok flag set)\")\r\n        return\r\n    echo_info(\"Checking for existing ngrok process...\")\r\n    # Cross-platform check using ngrok's local API\r\n    def is_ngrok_running_with_domain():\r\n        try:\r\n            with urlopen('http://localhost:4040/api/tunnels') as response:\r\n                data = json.loads(response.read().decode())\r\n                for tunnel in data.get('tunnels', []):\r\n                    public_url = tunnel.get('public_url', '')\r\n                    if config['ngrok_domain'] in public_url:\r\n                        return True\r\n                return False\r\n        except URLError:\r\n            return False\r\n    if is_ngrok_running_with_domain():\r\n        echo_info(f\"ngrok is already running with domain: {config['ngrok_domain']}\")\r\n        echo_info(\"Using existing ngrok tunnel\")\r\n        echo_info(\"You can check ngrok status at: http://localhost:4040\")\r\n        echo_info(f\"Public URL: {config['ngrok_url']}\")\r\n        return\r\n    else:\r\n        echo_info(\"No matching ngrok tunnel found (or ngrok not running).\")\r\n    print()\r\n    echo_warning(\"=========================================\")\r\n    echo_warning(\"NGROK SETUP REQUIRED\")\r\n    echo_warning(\"=========================================\")\r\n    print()\r\n    echo_info(\"Please open a new terminal window and run the following command:\")\r\n    print()\r\n    print(f\"{GREEN}    ngrok http --url={config['ngrok_domain']} 8090{NC}\")\r\n    print()\r\n    echo_info(f\"This will create a tunnel from {config['ngrok_url']} to your local Teranode asset service.\")\r\n    print()\r\n    echo_info(\"After starting ngrok, you can verify it's running at: http://localhost:4040\")\r\n    print()\r\n    input(\"Press Enter once ngrok is running in another terminal... \")\r\n    echo_info(\"Verifying ngrok connection...\")\r\n    max_attempts = 5\r\n    attempt = 1\r\n    wait_time = 2\r\n    while attempt <= max_attempts:\r\n        if is_ngrok_running_with_domain():\r\n            echo_info(\"ngrok verified successfully!\")\r\n            echo_info(f\"Tunnel established: {config['ngrok_url']} -> localhost:8090\")\r\n            echo_info(\"You can monitor ngrok at: http://localhost:4040\")\r\n            return\r\n        else:\r\n            echo_warning(\"ngrok tunnel not yet established or not matching domain...\")\r\n        if attempt == max_attempts:\r\n            echo_error(f\"Could not verify ngrok is running with domain: {config['ngrok_domain']}\")\r\n            echo_error(\"Please ensure you ran the command exactly as shown above\")\r\n            echo_error(\"To retry, stop this script and run it again\")\r\n            sys.exit(1)\r\n        echo_info(f\"Retrying verification (attempt {attempt}/{max_attempts})...\")\r\n        time.sleep(wait_time)\r\n        attempt += 1\r\ndef set_fsm_state_running():\r\n    echo_info(\"Setting FSM state to RUNNING...\")\r\n    \r\n    max_attempts = 30  # Increased for ~5 minutes total timeout\r\n    attempt = 1\r\n    wait_time = 10  # Increased wait time between checks\r\n    \r\n    echo_info(\"Waiting for blockchain service to be ready...\")\r\n    \r\n    while attempt <= max_attempts:\r\n        echo_info(f\"Checking blockchain container status (attempt {attempt}/{max_attempts})...\")\r\n        \r\n        try:\r\n            ps_output = subprocess.run(['docker', 'ps'], capture_output=True, text=True, check=True)\r\n            if 'blockchain' in ps_output.stdout:\r\n                try:\r\n                    # Capture output for better debugging\r\n                    check_output = subprocess.run(['docker', 'exec', 'blockchain', 'teranode-cli', 'getfsmstate'], capture_output=True, text=True, check=True)\r\n                    echo_info(f\"Blockchain container is ready (current FSM state: {check_output.stdout.strip()})\")\r\n                    break\r\n                except subprocess.CalledProcessError as e:\r\n                    echo_info(f\"Container is running but not yet responsive (error: {e.stderr.strip() or 'no output'})...\")\r\n            else:\r\n                echo_info(\"Blockchain container not yet running...\")\r\n        except subprocess.CalledProcessError as e:\r\n            echo_info(f\"Error checking docker ps: {e.stderr.strip()}...\")\r\n        \r\n        if attempt == max_attempts:\r\n            echo_error(f\"Blockchain container failed to become responsive after {max_attempts} attempts (~5 minutes)\")\r\n            echo_error(\"Cannot set FSM state to RUNNING automatically\")\r\n            echo_warning(\"Check 'docker logs blockchain' for errors. If no ",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "3507e885496872d4f7c54c45e3cfc6854cd71cd9a8513739eb49b41a8c9d716a",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "content_size": 20647,
  "content_truncated": true,
  "map_content_size": 20647,
  "map_content_truncated": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "6e11a21cb4a6d649d9b4229dcd6714229d66302250d57a3623a1b8564f2caab8",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Edit docker.compose.yml file.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 6 Likes · ⚡ 0 Tips
{
  "txid": "c7d507af323ab4758ea445fecf311226af33fa16d097d1aa89235595b1836701",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Terranode running on Windows",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 6,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "27b6399d79e105f17d9d28b33e9fab0c18f9c9a1a3d15547e25fe6ed1de1a1b4",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Teranode test network windows",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 1,
  "like_count": 0,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 5 Likes · ⚡ 0 Tips
{
  "txid": "208f85f202e842cb8ea844078f9e81c1ed0c19fb678466cdb3d8175f64c9f3e5",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Teranode test network windows",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 5,
  "timestamp": "2025-09-26T08:31:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
Replying to #2bf4edc4
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "a7191b19db45b67a4af475a854fde41dbf001f8f945b7f4931e7fd8be88e6def",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "!edit_nb  scrambled my text and jumble it around..",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "2bf4edc4952956de5263be9e1ad0b7a549cb5fbb3593e75e9b2d8d793984a36d",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-22T01:48:18.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "2bf4edc4952956de5263be9e1ad0b7a549cb5fbb3593e75e9b2d8d793984a36d",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "Censorship coming to social media in the west.. Treechat should have a word jumble feature built into the application for every post to be marked senitive to protect its users? By tipping the post it unjumbles the post.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-22T01:40:59.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
Replying to #cadaccfb
❤️ 6 Likes · ⚡ 0 Tips
{
  "txid": "205325fcc09bdec121b663689f8682a923c4ae16c29a0175f4af0037c6ff1ab6",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "Need to be posting on treechat.ai more",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "cadaccfb872177f2609cdacce5f472185d6dc485681e170ca28e7ab38cdfb43c",
  "ref_txid": null,
  "tags": null,
  "reply_count": 2,
  "like_count": 6,
  "timestamp": "2025-09-19T00:52:16.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·8mo
Replying to #9254c282
❤️ 1 Likes · ⚡ 0 Tips
{
  "txid": "7e838ed07313265b164f52e3c89af82f923899559af3f34c43db0e6dbd97c976",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "reply",
  "map_content": "I am from North Queensland also near Townsville.",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": "9254c28250ef9e6fdc01085755c6eef31268b51ce9594f973b8e21dfdb1bc5bb",
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 1,
  "timestamp": "2025-09-18T23:46:57.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!
Justinchellisvia treechat·9mo
❤️ 0 Likes · ⚡ 0 Tips
{
  "txid": "3734f1b2b23ce4b9ef24d0d12572d4c064ebc7593533080b52803182a83b63f7",
  "block_height": 0,
  "time": null,
  "app": "treechat",
  "type": "post",
  "map_content": "W chart could form and have a breakout, Bollinger bands closing and macd indicates it going green and over 1 percent dominance over btc today. People also saying it more profitable to mine on bsv the btc by 17 percent today..",
  "media_type": "text/markdown",
  "filename": "|",
  "author": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "display_name": "Justinchellis",
  "channel": null,
  "parent_txid": null,
  "ref_txid": null,
  "tags": null,
  "reply_count": 0,
  "like_count": 0,
  "timestamp": "2025-09-03T10:29:15.000Z",
  "media_url": null,
  "aip_verified": true,
  "thread_root_tx": null,
  "engagement_score": 0,
  "token_ref": null,
  "token_type": null,
  "kind": null,
  "lat": null,
  "lng": null,
  "category": null,
  "has_access": true,
  "ui_name": "Justinchellis",
  "ui_display_name": "Justinchellis",
  "ui_handle": "Justinchellis",
  "ui_display_raw": "Justinchellis",
  "ui_signer": "14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGK",
  "ref_ui_name": "unknown",
  "ref_ui_signer": "unknown"
}
Signed by14aqJ2hMtENYJVCJaekcrqi12fiZJzoWGKAIP!