playweb-node 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. playweb/__init__.py +18 -0
  2. playweb/api/__init__.py +4 -0
  3. playweb/api/erc20.py +66 -0
  4. playweb/api/erc721.py +88 -0
  5. playweb/api/metadata.py +86 -0
  6. playweb/api/node_api.py +224 -0
  7. playweb/api/public_api.py +496 -0
  8. playweb/api/rpc.py +247 -0
  9. playweb/client.py +341 -0
  10. playweb/config.py +168 -0
  11. playweb/consensus/__init__.py +5 -0
  12. playweb/consensus/leader.py +50 -0
  13. playweb/consensus/nvf_bft.py +540 -0
  14. playweb/consensus/vote.py +108 -0
  15. playweb/core/__init__.py +6 -0
  16. playweb/core/block.py +156 -0
  17. playweb/core/blockchain.py +358 -0
  18. playweb/core/fee_engine.py +312 -0
  19. playweb/core/mempool.py +112 -0
  20. playweb/core/royalty_engine.py +207 -0
  21. playweb/core/transaction.py +270 -0
  22. playweb/network/__init__.py +6 -0
  23. playweb/network/bootstrap.py +217 -0
  24. playweb/network/gossip.py +222 -0
  25. playweb/network/peer_manager.py +164 -0
  26. playweb/network/sync.py +244 -0
  27. playweb/node.py +303 -0
  28. playweb/plugin/__init__.py +4 -0
  29. playweb/plugin/base_plugin.py +225 -0
  30. playweb/plugin/plugin_manager.py +131 -0
  31. playweb/registry/__init__.py +4 -0
  32. playweb/registry/content_registry.py +259 -0
  33. playweb/registry/edition_registry.py +220 -0
  34. playweb/storage/__init__.py +11 -0
  35. playweb/storage/base.py +154 -0
  36. playweb/storage/ram_storage.py +123 -0
  37. playweb/storage/sqlite_storage.py +369 -0
  38. playweb/storage/supabase_storage.py +389 -0
  39. playweb_node-1.0.0.dist-info/METADATA +416 -0
  40. playweb_node-1.0.0.dist-info/RECORD +43 -0
  41. playweb_node-1.0.0.dist-info/WHEEL +5 -0
  42. playweb_node-1.0.0.dist-info/licenses/LICENSE +201 -0
  43. playweb_node-1.0.0.dist-info/top_level.txt +1 -0
playweb/config.py ADDED
@@ -0,0 +1,168 @@
1
+ """
2
+ PlayWebit Network — L1 Configuration
3
+ All constants hardcoded here. Never in .env.
4
+ Node operators cannot override these — consensus enforces them.
5
+ """
6
+
7
+ import os
8
+
9
+ # ─────────────────────────────────────────────
10
+ # NETWORK IDENTITY
11
+ # ─────────────────────────────────────────────
12
+
13
+ NETWORK_NAME = "PlayWebit Network"
14
+ CHAIN_ID = 4968
15
+ CURRENCY = "PLWB"
16
+ DECIMALS = 18
17
+
18
+ # ─────────────────────────────────────────────
19
+ # AUTHORITY WALLET
20
+ # Hardcoded — public and intentional.
21
+ # Every node enforces fees go here.
22
+ # Changing this = your blocks get rejected by network.
23
+ # ─────────────────────────────────────────────
24
+
25
+ AUTHORITY_WALLET = "0x119411e1CB00FE009b907eEA54467bFa5C8604dd"
26
+
27
+ # ─────────────────────────────────────────────
28
+ # L1 FEES — enforced by consensus
29
+ # These are the ONLY fees L1 knows about.
30
+ # Platform fees (list, buy, delist etc) are L2 territory.
31
+ # ─────────────────────────────────────────────
32
+
33
+ TRANSACTION_FEE = 1 # PLWB — every tx on the network
34
+ CV_LINK_FEE = 5 # PLWB — linking a CID to the chain
35
+ PLWB_REDEMPTION_FEE = 0.05 # 5% — fee on PLWB redemption (100% authority)
36
+ PLWB_RATE_USD = 0.10 # $0.10 per 1 PLWB
37
+ PLWB_MIN_PURCHASE = 10 # minimum PLWB per purchase
38
+ PLWB_MIN_REDEMPTION = 50 # minimum PLWB to redeem
39
+
40
+ # ─────────────────────────────────────────────
41
+ # FEE SPLIT — enforced by consensus
42
+ # Every node validates this on every block.
43
+ # Wrong split = block rejected.
44
+ # ─────────────────────────────────────────────
45
+
46
+ FEE_SPLIT_AUTHORITY = 0.50 # 50% → AUTHORITY_WALLET
47
+ FEE_SPLIT_NODE = 0.50 # 50% → node operator wallet
48
+
49
+ # Which fee tx_types get the 50/50 split
50
+ SPLITTABLE_FEE_TYPES = [
51
+ "fee", # base network tx fee (1 PLWB)
52
+ "cv_link", # CID link fee (5 PLWB)
53
+ ]
54
+
55
+ # Which fee tx_types go 100% to authority
56
+ AUTHORITY_ONLY_FEE_TYPES = [
57
+ "plwb_redeem", # redemption fee
58
+ ]
59
+
60
+ # ─────────────────────────────────────────────
61
+ # TRANSACTION TYPES — L1 knows only these
62
+ # Everything else is L2 / plugin territory.
63
+ # ─────────────────────────────────────────────
64
+
65
+ L1_TX_TYPES = [
66
+ "transfer", # PLWB transfer between wallets
67
+ "fee", # network fee (auto-split 50/50)
68
+ "cv_link", # link CID to chain (content registration fee)
69
+ "content_register", # register CID ownership on chain
70
+ "ownership_transfer", # transfer CID ownership
71
+ "edition_transfer", # transfer specific edition
72
+ "spider_hash_anchor", # anchor a spider hash (L2 integrity proof)
73
+ "plwb_redeem", # user redeems PLWB for fiat
74
+ "plwb_purchase", # user purchases PLWB
75
+ "genesis", # chain genesis transaction
76
+ "reward", # block reward
77
+ "node_register", # node registers on chain
78
+ ]
79
+
80
+ # These tx types skip signature verification (authority only)
81
+ AUTHORITY_TX_TYPES = [
82
+ "genesis",
83
+ "reward",
84
+ "plwb_purchase",
85
+ "plwb_redeem",
86
+ "spider_hash_anchor",
87
+ "node_register",
88
+ ]
89
+
90
+ # ─────────────────────────────────────────────
91
+ # CONSENSUS — NVF-BFT
92
+ # ─────────────────────────────────────────────
93
+
94
+ CONSENSUS_QUORUM = 0.667 # 2/3 of active nodes must vote
95
+ BLOCK_TIME = 30 # seconds between blocks
96
+ CONSENSUS_TIMEOUT = 15 # seconds before round times out
97
+ CONSENSUS_ROUND_PHASES = [
98
+ "PROPOSE", # leader broadcasts block candidate
99
+ "PREPARE", # peers verify + sign
100
+ "VOTE", # peers broadcast votes
101
+ "COMMIT", # 2/3 quorum reached → finalise
102
+ "ANCHOR", # write to storage
103
+ "NOTIFY", # notify plugins
104
+ ]
105
+
106
+ # ─────────────────────────────────────────────
107
+ # BOOTSTRAP — Cloudflare Worker
108
+ # ─────────────────────────────────────────────
109
+
110
+ BOOTSTRAP_URL = os.getenv(
111
+ "PLAYWEBIT_BOOTSTRAP_URL",
112
+ "https://small-field-be1c.playwebit.workers.dev"
113
+ )
114
+
115
+ BOOTSTRAP_ENDPOINTS = {
116
+ "nodes": "/nodes",
117
+ "register": "/nodes/register",
118
+ "heartbeat": "/nodes/heartbeat",
119
+ "deregister": "/nodes/deregister",
120
+ "health": "/nodes/health",
121
+ }
122
+
123
+ # Fallback — your own permanent nodes
124
+ # Used if Cloudflare is unreachable
125
+ BOOTSTRAP_FALLBACK_NODES = [
126
+ "https://node1.playwebit.com",
127
+ "https://node2.playwebit.com",
128
+ ]
129
+
130
+ BOOTSTRAP_HEARTBEAT_INTERVAL = 43200 # 12 hours in seconds
131
+ NODE_TTL = 86400 # 24 hours — auto-expire dead nodes
132
+
133
+ # ─────────────────────────────────────────────
134
+ # MINING
135
+ # ─────────────────────────────────────────────
136
+
137
+ MINING_MODE = "nvf_bft"
138
+ WRITE_DELAY = 5 # seconds between storage writes (rate limiting)
139
+ BATCH_TIMEOUT = 300 # 5 minutes — mine after this regardless
140
+ MAX_TX_PER_BLOCK = 10
141
+
142
+ # ─────────────────────────────────────────────
143
+ # NETWORK / P2P
144
+ # ─────────────────────────────────────────────
145
+
146
+ # Default port nodes listen on for peer-to-peer communication
147
+ # Node operators can override via NODE_PORT env var
148
+ NODE_PORT = int(os.getenv("NODE_PORT", 7860))
149
+
150
+ # How many peers to maintain connections with
151
+ MAX_PEERS = 20
152
+ MIN_PEERS = 3
153
+
154
+ # Gossip — how many peers to forward to
155
+ GOSSIP_FANOUT = 5
156
+
157
+ # Sync chunk size when downloading chain
158
+ SYNC_CHUNK_SIZE = 50 # blocks per request
159
+
160
+ # Peer timeout
161
+ PEER_TIMEOUT = 10 # seconds
162
+
163
+ # ─────────────────────────────────────────────
164
+ # LOGGING
165
+ # ─────────────────────────────────────────────
166
+
167
+ LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
168
+ DEBUG = os.getenv("DEBUG", "False").lower() == "true"
@@ -0,0 +1,5 @@
1
+ from playweb.consensus.nvf_bft import NVFBFTConsensus
2
+ from playweb.consensus.leader import LeaderElection
3
+ from playweb.consensus.vote import Vote
4
+
5
+ __all__ = ["NVFBFTConsensus", "LeaderElection", "Vote"]
@@ -0,0 +1,50 @@
1
+ """
2
+ PlayWebit Network — Leader Election
3
+ Rotating leader by block index. Deterministic — all nodes agree.
4
+ No randomness, no voting on who leads. Just math.
5
+ """
6
+
7
+ import logging
8
+ from typing import List, Optional
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class LeaderElection:
14
+
15
+ def get_leader(
16
+ self,
17
+ block_index: int,
18
+ active_nodes: List[str], # list of wallet addresses
19
+ ) -> Optional[str]:
20
+ """
21
+ Get the leader wallet for a given block index.
22
+ Deterministic: block_index % len(active_nodes)
23
+ Every node on the network computes the same result.
24
+ """
25
+ if not active_nodes:
26
+ return None
27
+
28
+ sorted_nodes = sorted(active_nodes) # sort for determinism
29
+ leader_index = block_index % len(sorted_nodes)
30
+ return sorted_nodes[leader_index]
31
+
32
+ def is_leader(
33
+ self,
34
+ my_wallet: str,
35
+ block_index: int,
36
+ active_nodes: List[str],
37
+ ) -> bool:
38
+ """Check if this node is the leader for this block."""
39
+ leader = self.get_leader(block_index, active_nodes)
40
+ if not leader:
41
+ return False
42
+ return leader.lower() == my_wallet.lower()
43
+
44
+ def get_next_leader(
45
+ self,
46
+ block_index: int,
47
+ active_nodes: List[str],
48
+ ) -> Optional[str]:
49
+ """Get the leader for the NEXT block — for planning ahead."""
50
+ return self.get_leader(block_index + 1, active_nodes)