Skip to content

Commit

Permalink
Merge branch 'main' into teams
Browse files Browse the repository at this point in the history
  • Loading branch information
tsu-ki authored Feb 1, 2025
2 parents 5175f71 + 3dfb25e commit 11abe5e
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ BLUESKY_USERNAME=example.bsky.social
BLUESKY_PASSWORD='example#123'

GITHUB_ACCESS_TOKEN="abc123"

ORD_SERVER_URL="http://ipv4:port"
37 changes: 11 additions & 26 deletions BACON/BLT BTC Runes documentation .md
Original file line number Diff line number Diff line change
@@ -1,39 +1,27 @@
# Documentation for etching runes for BACON

**2 Jan, 2025\.**
**11AM IST.**
**31 Jan, 2025\.**
**1:30AM IST.**

Right now, we have two servers with alphaVPS as the provider.
Right now, we have three servers with alphaVPS as the provider.

One node runs a testnet, where we plan to etch the BTC runes initially for POC purposes.
One node runs a regtest, where we etched the BTC runes(BLT•BACON•TOKENS) initially for POC purposes

And another one is syncing up with the mainnet, where we plan to etch the BACON token.
And two others are syncing up with the mainnet, where we plan to etch the BACON token again.

**The current state while writing:**
1\. Testnet server has a corrupted chain index (started reindexing today), due to random killing of the bitcoind process, we might have to raise a ticket with alphaVPS for this, since its probable they do this because of I/O limits.
1\. Regtest and ord server are running peacefully and all the operations are getting handled smoothly.

2\. The mainnet is syncing slow and steady and is upto \~46.5% as of writing.
2\. The mainnet1 has synced upto 90% and the mainnet2 has synced upto 70% as of now.

**Current Workflow**

1. On the testnet node, one tmux session is used to run the node and other is used to run the ord server.
2. Once both of these sync up, we will probably create another tmux session to create wallet and etch runes.
3. On the mainnet node, we just have a single tmux session as of writing where the bitcoind process is syncing the node with the mainnet.
1. On the regtest node, we have a regtest.service daemon process running the bitcoin blockchain and the ord-flask.service daemon running for interaction of sending bacon tokens to the users submitted in /send-bacon-tokens endpoint ,tmux process on bitcoin user running the ordinal server to index the blocks on regtest and perform wallet operations(creating wallet, etching runes, transferring funds).
2. First we will do a complete integration with the regtest , and once the mainnet spins up , we'll run an ord server that index the mainnet blocks and perform wallet operations.

**Some useful references:**
[https://ordtutorial.vercel.app/ordtestnet](https://ordtutorial.vercel.app/ordtestnet)

**Current bitcoind config on testnet.**
server=1
testnet=1
txindex=1
rpcuser=apoorva
blockfilterindex=1
rpcpassword=y^2DhUnxrhFr7qAj2yjhvykFz
rpcallowip=127.0.0.1
[test]
rpcport=8332
rpcbind=127.0.0.1
The ordicord discord server

**Current bitcoind config on the mainnet:**
server=1
Expand All @@ -47,12 +35,9 @@ blockfilterindex=1

Side note: We might want to add rpcbind here after the node syncs completely.

**Command to start the bitcoind process on the testnet, note that we use the bitcoind snap package on both our servers.**
**Command to start the bitcoind process on the mainnet, as we use the bitcoind snap package on this server.**
bitcoin-core.daemon \-datadir=/home/apoorva/test-btc-data \-dbcache=256 \-rpcworkqueue=1000

**Command to start the ordinal server to index blocks after syncing the node completely, we will create a wallet and etch runes once this completes.**
sudo ./ord \--bitcoin-rpc-user apoorva \--bitcoin-rpc-pass y^2DhUnxrhFr7qAj2yjhvykFz \--rpc-url http://127.0.0.1:8332 \--data-dir /home/apoorva/ord-data \--bitcoin-data-dir /home/apoorva/test-btc-data \--index-runes \--testnet \--verbose server

**Some additional observations:**

1. I found that ^C takes a lot of time to stop the bitcoind process,so another way to kill it instantly is finding the PID of the bitcoind process and killing it, saves a lot of time, but use with caution, since it might corrupt the indexing and syncing.
Expand Down
12 changes: 12 additions & 0 deletions BACON/bacon-etch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mode: separate-outputs

etching:
rune: BLT.BACON.TOKENS
turbo: true
divisibility: 8
premine: 1000000
supply: 1000000
symbol: 🥓

inscriptions:
- file: /blockchain/bacon.png
Binary file added BACON/bacon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions BACON/example-split.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# example split file

# output fields:
# address: output recipient bitcoin address
# value: output bitcoin value (optional, defaults to minimal-non dust value for `address`)
# runes: output rune value map (values respect rune divisibility)
outputs:
- address: bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297
value: 10 sat
runes:
UNCOMMON•GOODS: 1234
GRIEF•WAGE: 5000000
- address: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
runes:
HELLO•WORLD: 22.5
13 changes: 13 additions & 0 deletions BACON/regtest-bitcoind.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
datacarriersize=1000000
regtest=1
datadir=/blockchain/regtest/data
listen=0
txindex=1
printtoconsole=1
rpcuser=bitcoin
rpcpassword=bitcoin

[regtest]
rpcport=18443
rpcbind=0.0.0.0:18443
rpcallowip=0.0.0.0/0
2 changes: 2 additions & 0 deletions blt/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,5 @@
},
},
}

ORD_SERVER_URL = os.getenv("ORD_SERVER_URL", "http://localhost:9001") # Default to local for development
3 changes: 3 additions & 0 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
UserIssueViewSet,
UserProfileViewSet,
)
from website.views.bitcoin import batch_send_bacon_tokens_view, pending_transactions_view
from website.views.blog import PostCreateView, PostDeleteView, PostDetailView, PostListView, PostUpdateView
from website.views.company import (
AddDomainView,
Expand Down Expand Up @@ -848,6 +849,8 @@
path("project/<slug:slug>/", ProjectsDetailView.as_view(), name="projects_detail"),
path("slack/events", slack_events, name="slack_events"),
path("owasp/", TemplateView.as_view(template_name="owasp.html"), name="owasp"),
path("batch-send-bacon-tokens/", batch_send_bacon_tokens_view, name="batch_send_bacon_tokens"),
path("pending-transactions/", pending_transactions_view, name="pending_transactions"),
]

if settings.DEBUG:
Expand Down
40 changes: 20 additions & 20 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ tld = "0.13"
[tool.poetry.group.dev.dependencies]
black = "^24.8.0"
isort = "^5.13.2"
ruff = "^0.9.3"
ruff = "^0.9.4"
pre-commit = "^3.8.0"
selenium = "^4.28.1"
webdriver-manager = "^4.0.2"
Expand Down
30 changes: 29 additions & 1 deletion website/feed_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,20 @@
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver

from .models import Activity, Badge, Bid, Hunt, IpReport, Issue, Post, Suggestion, TimeLog, UserBadge, UserProfile
from .models import (
Activity,
BaconEarning,
Badge,
Bid,
Hunt,
IpReport,
Issue,
Post,
Suggestion,
TimeLog,
UserBadge,
UserProfile,
)


def get_default_user():
Expand Down Expand Up @@ -45,11 +58,26 @@ def create_activity(instance, action_type):
)


def giveBacon(user):
# Check if the user already has a token record
if user is None or user.is_authenticated is False:
return
token_earning, created = BaconEarning.objects.get_or_create(user=user)

if created:
token_earning.tokens_earned = 1 # Reward 10 tokens for completing the action (adjust as needed)
else:
token_earning.tokens_earned += 1 # Add 10 tokens if the user already exists in the system

token_earning.save() # Save the updated record


@receiver(post_save)
def handle_post_save(sender, instance, created, **kwargs):
"""Generic handler for post_save signal."""
if sender == IpReport and created: # Track first IP report
assign_first_action_badge(instance.user, "First IP Reported")
giveBacon(instance.user)
create_activity(instance, "created")

elif sender == Post and created: # Track first blog post
Expand Down
41 changes: 41 additions & 0 deletions website/migrations/0187_baconearning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 5.1.5 on 2025-01-30 20:27

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("website", "0186_userprofile_contribution_rank_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="BaconEarning",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"tokens_earned",
models.DecimalField(decimal_places=2, default=0.0, max_digits=10),
),
("timestamp", models.DateTimeField(auto_now_add=True)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
),
]
2 changes: 1 addition & 1 deletion website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1439,7 +1439,7 @@ class BaconEarning(models.Model):
def __str__(self):
return f"{self.user.username} - {self.tokens_earned} Tokens"


class Kudos(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="kudos_sent")
receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name="kudos_received")
Expand Down
71 changes: 71 additions & 0 deletions website/views/bitcoin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import json

import requests
from django.conf import settings
from django.http import JsonResponse

from blt import settings
from website.models import BaconEarning


# @login_required
def batch_send_bacon_tokens_view(request):
# Get all users with non-zero tokens_earned
users_with_tokens = BaconEarning.objects.filter(tokens_earned__gt=0)

if not users_with_tokens.exists():
return JsonResponse({"status": "error", "message": "No eligible users with tokens to send."})

# Build YAML content
yaml_outputs = []
for token_earning in users_with_tokens:
user = token_earning.user
btc_address = getattr(user.userprofile, "btc_address", None)
tokens_to_send = token_earning.tokens_earned

if btc_address and tokens_to_send > 0:
yaml_outputs.append(f"- address: {btc_address}\n runes:\n BLT•BACON•TOKENS: {tokens_to_send}")

# Form the YAML string payload
yaml_content = "outputs:\n" + "\n".join(yaml_outputs)

# Payload for POST request
payload = {"yaml_content": yaml_content}
ORD_SERVER_URL = settings.ORD_SERVER_URL
try:
# Send the request to the ORD server
response = requests.post(
f"{ORD_SERVER_URL}/send-bacon-tokens",
headers={"Content-Type": "application/json"},
data=json.dumps(payload),
)
response_data = response.json()

# Reset the tokens_earned for all users if the request was successful
if response.status_code == 200 and response_data.get("success"):
users_with_tokens.update(tokens_earned=0)
return JsonResponse(
{
"status": "success",
"message": "Tokens successfully sent to all eligible users. If it doesnt appear in the users wallet yet , wait for the miners to confirm the transaction.",
}
)
else:
return JsonResponse({"status": "error", "message": response_data.get("error", "Unknown error")})

except requests.RequestException as e:
return JsonResponse({"status": "error", "message": str(e)})


def pending_transactions_view(request):
# Fetch all users with non-zero tokens_earned
pending_transactions = BaconEarning.objects.filter(tokens_earned__gt=0)
# Prepare a list of user: address: tokens data
transactions_data = []
for transaction in pending_transactions:
user = transaction.user
btc_address = getattr(user.userprofile, "btc_address", None)
transactions_data = [{"user": user.username, "address": btc_address, "tokens": transaction.tokens_earned}]

# If you want to return it as a JSON response:
return JsonResponse({"pending_transactions": transactions_data})
Loading

0 comments on commit 11abe5e

Please sign in to comment.