hypnex-staking 0.1.0__tar.gz

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.
@@ -0,0 +1,66 @@
1
+ # --- Python ---
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ build/
7
+ dist/
8
+ .eggs/
9
+ .pytest_cache/
10
+ .ruff_cache/
11
+ .tox/
12
+ .coverage
13
+ .coverage.*
14
+ htmlcov/
15
+ .venv/
16
+ venv/
17
+ env/
18
+
19
+ # --- Node / TypeScript ---
20
+ node_modules/
21
+ *.tsbuildinfo
22
+ .npm/
23
+ .yarn/
24
+ .pnpm-store/
25
+ .parcel-cache/
26
+
27
+ # --- Next.js (apps/stake) ---
28
+ .next/
29
+ out/
30
+ .vercel/
31
+
32
+ # --- Wrangler / Cloudflare ---
33
+ .wrangler/
34
+
35
+ # --- Foundry (registry-contracts) ---
36
+ forge-cache/
37
+ broadcast/
38
+
39
+ # --- Editor / OS ---
40
+ .idea/
41
+ .vscode/
42
+ .DS_Store
43
+ *.swp
44
+ *.swo
45
+ *~
46
+
47
+ # --- Local secrets — never commit ---
48
+ .env
49
+ .env.*
50
+ !.env.example
51
+ .env.local
52
+ .env.production
53
+
54
+ # --- Log + tmp ---
55
+ *.log
56
+ logs/
57
+ tmp/
58
+
59
+ # --- Build outputs in apps/bench ---
60
+ apps/bench/out/
61
+
62
+ # --- Generated bench data is committed (audit trail) but local runs aren't ---
63
+ python-bench/data/*.jsonl
64
+
65
+ # Claude Code session artifacts — never commit
66
+ .claude/
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: hypnex-staking
3
+ Version: 0.1.0
4
+ Summary: On-chain staking helpers for the Morpheus AI capital pool. Wraps DepositPool.stake() with referrer support (MRC 73 unlocked-MOR rewards).
5
+ Project-URL: Homepage, https://hypnex.xyz
6
+ Project-URL: Documentation, https://docs.hypnex.xyz/staking
7
+ Project-URL: Repository, https://github.com/hypnex-labs/hypnex
8
+ Project-URL: Issues, https://github.com/hypnex-labs/hypnex/issues
9
+ Author: Hypnex Labs
10
+ License: MIT
11
+ Keywords: aave,defi,ethereum,mor,morpheus,onchain,referral,staking,web3
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Office/Business :: Financial :: Investment
21
+ Requires-Python: >=3.9
22
+ Requires-Dist: eth-account>=0.10.0
23
+ Requires-Dist: web3<8.0,>=6.15.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.5; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # hypnex-staking (Python)
30
+
31
+ On-chain helpers for the **Morpheus AI capital pool** on Ethereum mainnet. Wraps `DepositPool.stake()` and `claimReferrerTier()` so a Python developer can stake stETH/USDC/USDT/wBTC and capture **MRC 73 unlocked-MOR referral rewards**.
32
+
33
+ ```bash
34
+ pip install hypnex-staking
35
+ ```
36
+
37
+ ## Why this exists
38
+
39
+ Morpheus's `app.mor.org` UI requires AWS Cognito email signup. The capital pool's on-chain interface is wallet-native and supports referrer attribution, but no Python tooling exists for it. This package fills that gap.
40
+
41
+ The single most under-marketed mechanic: **referral MOR is unlocked, while own-stake MOR is delayed 90 days** (MRC 73 vs MRC 46). Refer once, earn liquid MOR for as long as the referee stays staked.
42
+
43
+ ## Quickstart
44
+
45
+ ### Read-only (no key needed)
46
+
47
+ ```python
48
+ from hypnex_staking import Staker
49
+
50
+ s = Staker() # public RPC, no signer
51
+
52
+ # Inspect the live tier table
53
+ for tier in s.get_referrer_tiers("USDC"):
54
+ print(tier)
55
+
56
+ # Look up an existing position
57
+ print(s.get_position("0xSomeAddress...", "USDC"))
58
+
59
+ # Look up someone's referrer data
60
+ print(s.get_referrer_data("0xReferrer...", "USDC"))
61
+ ```
62
+
63
+ ### With a signer (moves real funds)
64
+
65
+ ```python
66
+ import os
67
+ from hypnex_staking import Staker
68
+
69
+ s = Staker(
70
+ rpc_url=os.environ["ETH_RPC_URL"],
71
+ private_key=os.environ["PRIVATE_KEY"],
72
+ default_referrer="0xYourHypnexLabsAddress", # or set HYPNEX_REFERRER env
73
+ )
74
+
75
+ # Always dry-run first — returns calldata, doesn't broadcast
76
+ print(s.stake("USDC", amount=1000, claim_lock_end=0, dry_run=True))
77
+
78
+ # When ready, drop dry_run for the real tx
79
+ tx = s.stake("USDC", amount=1000, claim_lock_end=0)
80
+ print("submitted:", tx)
81
+ ```
82
+
83
+ ### Claim accumulated MRC 73 unlocked-MOR
84
+
85
+ ```python
86
+ # Per MRC 73, this MOR has no 90-day lockup — claimable immediately.
87
+ tx = s.claim_referrer_rewards("USDC")
88
+ ```
89
+
90
+ ## Verified contracts (Ethereum mainnet)
91
+
92
+ | Contract | Address |
93
+ |---|---|
94
+ | USDC DepositPool | `0x6cCE082851Add4c535352f596662521B4De4750E` |
95
+ | USDT DepositPool | `0x3B51989212BEdaB926794D6bf8e9E991218cf116` |
96
+ | wBTC DepositPool | `0xdE283F8309Fd1AA46c95d299f6B8310716277A42` |
97
+ | wETH DepositPool | `0x9380d72aBbD6e0Cc45095A2Ef8c2CA87d77Cb384` |
98
+ | DistributorV2 | `0xDf1AC1AC255d91F5f4B1E3B4Aef57c5350F64C7A` |
99
+ | ChainLinkDataConsumer | `0xd182263d06FDC463c96190005D6359CC3d3Bbc5e` |
100
+
101
+ Sourced from `MorpheusAIs/SmartContracts` v7 deploy script — verified against the on-chain bytecode by `tests/test_read_only.py`.
102
+
103
+ ## Public API
104
+
105
+ ```
106
+ Staker(w3=..., rpc_url=..., account=..., private_key=..., default_referrer=...)
107
+
108
+ # read (no signer)
109
+ .get_pool_address(asset) -> str
110
+ .get_token_address(asset) -> str
111
+ .get_decimals(asset) -> int
112
+ .get_position(address, asset) -> Position
113
+ .get_referrer_data(referrer, asset) -> ReferrerData
114
+ .get_referrer_tiers(asset) -> list[ReferrerTier]
115
+ .quote_tier(asset, virtual_amount_staked) -> ReferrerTier | None
116
+
117
+ # write (signer required)
118
+ .approve(asset, amount, dry_run=False) -> str (tx hash)
119
+ .stake(asset, amount, claim_lock_end=0, referrer=None, auto_approve=True, dry_run=False) -> str
120
+ .claim_referrer_rewards(asset, receiver=None, layerzero_fee_wei=0, dry_run=False) -> str
121
+ ```
122
+
123
+ `asset` is one of `"USDC" | "USDT" | "WBTC" | "WETH"`.
124
+
125
+ ## Environment variables
126
+
127
+ - `ETH_RPC_URL` — Ethereum mainnet RPC (free public default works for reads)
128
+ - `PRIVATE_KEY` — for write methods only
129
+ - `HYPNEX_REFERRER` — default referrer address (override per-call with `referrer=`)
130
+
131
+ ## Tests
132
+
133
+ ```bash
134
+ pip install -e ".[dev]"
135
+ pytest # read-only mainnet smoke tests, no key needed
136
+ ```
137
+
138
+ For write-method tests, run a local Anvil fork (`anvil --fork-url $ETH_RPC_URL`) and set `ETH_RPC_URL=http://localhost:8545` plus a funded test key. Test recipes are in `tests/test_anvil_fork.py` (unimplemented stub — community contributions welcome).
139
+
140
+ ## Status & affiliation
141
+
142
+ **Hypnex is not affiliated with the Morpheus AI Foundation.** The contracts you sign into are Morpheus's; this is the unofficial Python toolkit for them. Audit your own transactions; the Code4rena audit ([report](https://code4rena.com/reports/2025-08-morpheus)) covers the contracts, not this client.
143
+
144
+ ## License
145
+
146
+ MIT
@@ -0,0 +1,118 @@
1
+ # hypnex-staking (Python)
2
+
3
+ On-chain helpers for the **Morpheus AI capital pool** on Ethereum mainnet. Wraps `DepositPool.stake()` and `claimReferrerTier()` so a Python developer can stake stETH/USDC/USDT/wBTC and capture **MRC 73 unlocked-MOR referral rewards**.
4
+
5
+ ```bash
6
+ pip install hypnex-staking
7
+ ```
8
+
9
+ ## Why this exists
10
+
11
+ Morpheus's `app.mor.org` UI requires AWS Cognito email signup. The capital pool's on-chain interface is wallet-native and supports referrer attribution, but no Python tooling exists for it. This package fills that gap.
12
+
13
+ The single most under-marketed mechanic: **referral MOR is unlocked, while own-stake MOR is delayed 90 days** (MRC 73 vs MRC 46). Refer once, earn liquid MOR for as long as the referee stays staked.
14
+
15
+ ## Quickstart
16
+
17
+ ### Read-only (no key needed)
18
+
19
+ ```python
20
+ from hypnex_staking import Staker
21
+
22
+ s = Staker() # public RPC, no signer
23
+
24
+ # Inspect the live tier table
25
+ for tier in s.get_referrer_tiers("USDC"):
26
+ print(tier)
27
+
28
+ # Look up an existing position
29
+ print(s.get_position("0xSomeAddress...", "USDC"))
30
+
31
+ # Look up someone's referrer data
32
+ print(s.get_referrer_data("0xReferrer...", "USDC"))
33
+ ```
34
+
35
+ ### With a signer (moves real funds)
36
+
37
+ ```python
38
+ import os
39
+ from hypnex_staking import Staker
40
+
41
+ s = Staker(
42
+ rpc_url=os.environ["ETH_RPC_URL"],
43
+ private_key=os.environ["PRIVATE_KEY"],
44
+ default_referrer="0xYourHypnexLabsAddress", # or set HYPNEX_REFERRER env
45
+ )
46
+
47
+ # Always dry-run first — returns calldata, doesn't broadcast
48
+ print(s.stake("USDC", amount=1000, claim_lock_end=0, dry_run=True))
49
+
50
+ # When ready, drop dry_run for the real tx
51
+ tx = s.stake("USDC", amount=1000, claim_lock_end=0)
52
+ print("submitted:", tx)
53
+ ```
54
+
55
+ ### Claim accumulated MRC 73 unlocked-MOR
56
+
57
+ ```python
58
+ # Per MRC 73, this MOR has no 90-day lockup — claimable immediately.
59
+ tx = s.claim_referrer_rewards("USDC")
60
+ ```
61
+
62
+ ## Verified contracts (Ethereum mainnet)
63
+
64
+ | Contract | Address |
65
+ |---|---|
66
+ | USDC DepositPool | `0x6cCE082851Add4c535352f596662521B4De4750E` |
67
+ | USDT DepositPool | `0x3B51989212BEdaB926794D6bf8e9E991218cf116` |
68
+ | wBTC DepositPool | `0xdE283F8309Fd1AA46c95d299f6B8310716277A42` |
69
+ | wETH DepositPool | `0x9380d72aBbD6e0Cc45095A2Ef8c2CA87d77Cb384` |
70
+ | DistributorV2 | `0xDf1AC1AC255d91F5f4B1E3B4Aef57c5350F64C7A` |
71
+ | ChainLinkDataConsumer | `0xd182263d06FDC463c96190005D6359CC3d3Bbc5e` |
72
+
73
+ Sourced from `MorpheusAIs/SmartContracts` v7 deploy script — verified against the on-chain bytecode by `tests/test_read_only.py`.
74
+
75
+ ## Public API
76
+
77
+ ```
78
+ Staker(w3=..., rpc_url=..., account=..., private_key=..., default_referrer=...)
79
+
80
+ # read (no signer)
81
+ .get_pool_address(asset) -> str
82
+ .get_token_address(asset) -> str
83
+ .get_decimals(asset) -> int
84
+ .get_position(address, asset) -> Position
85
+ .get_referrer_data(referrer, asset) -> ReferrerData
86
+ .get_referrer_tiers(asset) -> list[ReferrerTier]
87
+ .quote_tier(asset, virtual_amount_staked) -> ReferrerTier | None
88
+
89
+ # write (signer required)
90
+ .approve(asset, amount, dry_run=False) -> str (tx hash)
91
+ .stake(asset, amount, claim_lock_end=0, referrer=None, auto_approve=True, dry_run=False) -> str
92
+ .claim_referrer_rewards(asset, receiver=None, layerzero_fee_wei=0, dry_run=False) -> str
93
+ ```
94
+
95
+ `asset` is one of `"USDC" | "USDT" | "WBTC" | "WETH"`.
96
+
97
+ ## Environment variables
98
+
99
+ - `ETH_RPC_URL` — Ethereum mainnet RPC (free public default works for reads)
100
+ - `PRIVATE_KEY` — for write methods only
101
+ - `HYPNEX_REFERRER` — default referrer address (override per-call with `referrer=`)
102
+
103
+ ## Tests
104
+
105
+ ```bash
106
+ pip install -e ".[dev]"
107
+ pytest # read-only mainnet smoke tests, no key needed
108
+ ```
109
+
110
+ For write-method tests, run a local Anvil fork (`anvil --fork-url $ETH_RPC_URL`) and set `ETH_RPC_URL=http://localhost:8545` plus a funded test key. Test recipes are in `tests/test_anvil_fork.py` (unimplemented stub — community contributions welcome).
111
+
112
+ ## Status & affiliation
113
+
114
+ **Hypnex is not affiliated with the Morpheus AI Foundation.** The contracts you sign into are Morpheus's; this is the unofficial Python toolkit for them. Audit your own transactions; the Code4rena audit ([report](https://code4rena.com/reports/2025-08-morpheus)) covers the contracts, not this client.
115
+
116
+ ## License
117
+
118
+ MIT
@@ -0,0 +1,30 @@
1
+ """Read your stake position from the Morpheus capital pool.
2
+
3
+ Read-only — no key required.
4
+
5
+ Run: python examples/01_check_position.py 0xYourAddress... USDC
6
+ """
7
+
8
+ import sys
9
+
10
+ from hypnex_staking import Staker
11
+
12
+
13
+ def main() -> int:
14
+ if len(sys.argv) != 3:
15
+ print("usage: python 01_check_position.py <address> <USDC|USDT|WBTC|WETH>")
16
+ return 2
17
+ address, asset = sys.argv[1], sys.argv[2]
18
+ s = Staker()
19
+ p = s.get_position(address, asset)
20
+ decimals = s.get_decimals(asset)
21
+ print(f"Position for {address} in {asset.upper()} pool:")
22
+ print(f" deposited : {p.deposited / 10**decimals:,.6f} {asset.upper()}")
23
+ print(f" pending rewards : {p.pending_rewards / 1e18:,.6f} MOR")
24
+ print(f" claim_lock_end : {p.claim_lock_end} (unix)")
25
+ print(f" referrer : {p.referrer}")
26
+ return 0
27
+
28
+
29
+ if __name__ == "__main__":
30
+ raise SystemExit(main())
@@ -0,0 +1,30 @@
1
+ """Read a referrer's data: amount staked under them, virtual amount, pending unlocked MOR.
2
+
3
+ Read-only.
4
+
5
+ Run: python examples/02_get_referrer_data.py 0xReferrerAddress... USDC
6
+ """
7
+
8
+ import sys
9
+
10
+ from hypnex_staking import Staker
11
+
12
+
13
+ def main() -> int:
14
+ if len(sys.argv) != 3:
15
+ print("usage: python 02_get_referrer_data.py <referrer> <USDC|USDT|WBTC|WETH>")
16
+ return 2
17
+ referrer, asset = sys.argv[1], sys.argv[2]
18
+ s = Staker()
19
+ d = s.get_referrer_data(referrer, asset)
20
+ decimals = s.get_decimals(asset)
21
+ print(f"Referrer data for {referrer} in {asset.upper()} pool:")
22
+ print(f" amount staked under referrer : {d.amount_staked / 10**decimals:,.6f} {asset.upper()}")
23
+ print(f" virtual amount (after tier) : {d.virtual_amount_staked / 10**decimals:,.6f}")
24
+ print(f" pending unlocked MOR rewards : {d.pending_rewards / 1e18:,.6f} MOR (MRC 73 — claim anytime)")
25
+ print(f" last claim : {d.last_claim} (unix)")
26
+ return 0
27
+
28
+
29
+ if __name__ == "__main__":
30
+ raise SystemExit(main())
@@ -0,0 +1,37 @@
1
+ """Read the live referrer-tier table for each pool and quote which tier a given
2
+ virtual stake amount falls in.
3
+
4
+ Read-only.
5
+
6
+ Run: python examples/03_quote_tier.py
7
+ """
8
+
9
+ from hypnex_staking import Staker
10
+
11
+
12
+ def main() -> None:
13
+ s = Staker()
14
+
15
+ for asset in ("USDC", "USDT", "WBTC", "WETH"):
16
+ decimals = s.get_decimals(asset)
17
+ print(f"\n{asset} pool — referrer tiers:")
18
+ tiers = s.get_referrer_tiers(asset)
19
+ if not tiers:
20
+ print(" (no tiers configured on-chain — fall through to base 1% referee bonus)")
21
+ continue
22
+ for i, t in enumerate(tiers):
23
+ # multiplier is PRECISION-scaled (1e25 == 1.0×); convert to bonus %
24
+ multiplier_x = t.multiplier / 1e25
25
+ bonus_pct = (multiplier_x - 1.0) * 100
26
+ print(
27
+ f" tier {i}: ≥ {t.amount_threshold / 10**decimals:>12,.4f} {asset} "
28
+ f"→ {multiplier_x:.4f}× ({bonus_pct:+.1f}%)"
29
+ )
30
+
31
+ print("\nNote: tier thresholds are denominated in the *virtual amount* — i.e. the\n"
32
+ "amount-staked × the referee's claim-lock-time multiplier. Long locks count\n"
33
+ "for more virtual stake, which can push a referrer up a tier.")
34
+
35
+
36
+ if __name__ == "__main__":
37
+ main()
@@ -0,0 +1,67 @@
1
+ """WRITES A REAL TRANSACTION on Ethereum mainnet — moves real funds.
2
+
3
+ Stake `amount` of `asset` into the Morpheus DepositPool with Hypnex Labs as
4
+ the on-chain referrer. The default-referrer override happens via the
5
+ HYPNEX_REFERRER env var or the Staker(default_referrer=...) constructor arg.
6
+
7
+ Always run with --dry-run first. Test against Anvil fork before live.
8
+
9
+ Run:
10
+ ETH_RPC_URL=https://... \\
11
+ PRIVATE_KEY=0x... \\
12
+ python examples/04_stake.py USDC 100 --dry-run
13
+
14
+ To broadcast for real, drop the --dry-run flag.
15
+ """
16
+
17
+ import argparse
18
+ import os
19
+
20
+ from hypnex_staking import Staker
21
+
22
+
23
+ def main() -> int:
24
+ p = argparse.ArgumentParser()
25
+ p.add_argument("asset", choices=["USDC", "USDT", "WBTC", "WETH"])
26
+ p.add_argument("amount", type=float)
27
+ p.add_argument("--claim-lock-end", type=int, default=0,
28
+ help="Unix timestamp for voluntary additional claim lock; 0 = no extra lock")
29
+ p.add_argument("--referrer", type=str, default=None,
30
+ help="Override default referrer (HYPNEX_REFERRER env / Staker default)")
31
+ p.add_argument("--dry-run", action="store_true",
32
+ help="Build but do NOT broadcast — print calldata only")
33
+ args = p.parse_args()
34
+
35
+ rpc = os.environ.get("ETH_RPC_URL")
36
+ pk = os.environ.get("PRIVATE_KEY")
37
+ if not rpc or not pk:
38
+ print("error: set ETH_RPC_URL and PRIVATE_KEY")
39
+ return 2
40
+
41
+ s = Staker(rpc_url=rpc, private_key=pk)
42
+
43
+ print(f" asset : {args.asset}")
44
+ print(f" amount : {args.amount}")
45
+ print(f" claim_lock_end : {args.claim_lock_end}")
46
+ print(f" referrer : {args.referrer or s.default_referrer}")
47
+ print(f" signer : {s.account.address}")
48
+ print(f" pool : {s.get_pool_address(args.asset)}")
49
+ print(f" dry_run : {args.dry_run}")
50
+ print()
51
+
52
+ out = s.stake(
53
+ asset=args.asset,
54
+ amount=args.amount,
55
+ claim_lock_end=args.claim_lock_end,
56
+ referrer=args.referrer,
57
+ dry_run=args.dry_run,
58
+ )
59
+ if args.dry_run:
60
+ print(f" encoded calldata : {out}")
61
+ else:
62
+ print(f" tx hash : {out}")
63
+ return 0
64
+
65
+
66
+ if __name__ == "__main__":
67
+ raise SystemExit(main())
@@ -0,0 +1,43 @@
1
+ """WRITES A REAL TRANSACTION — claims your accumulated MRC 73 unlocked-MOR rewards.
2
+
3
+ Per MRC 73, referrer MOR is unlocked the moment it accrues — no 90-day delay
4
+ that capital contributors face under MRC 46. This is the lowest-friction MOR
5
+ yield path on the network.
6
+
7
+ Run:
8
+ ETH_RPC_URL=... PRIVATE_KEY=... \\
9
+ python examples/05_claim_referrer_rewards.py USDC --dry-run
10
+ """
11
+
12
+ import argparse
13
+ import os
14
+
15
+ from hypnex_staking import Staker
16
+
17
+
18
+ def main() -> int:
19
+ p = argparse.ArgumentParser()
20
+ p.add_argument("asset", choices=["USDC", "USDT", "WBTC", "WETH"])
21
+ p.add_argument("--receiver", type=str, default=None,
22
+ help="Address to receive the MOR (defaults to signer)")
23
+ p.add_argument("--lz-fee-wei", type=int, default=0,
24
+ help="LayerZero messaging fee if cross-chain forwarding (default 0)")
25
+ p.add_argument("--dry-run", action="store_true")
26
+ args = p.parse_args()
27
+
28
+ rpc = os.environ["ETH_RPC_URL"]
29
+ pk = os.environ["PRIVATE_KEY"]
30
+ s = Staker(rpc_url=rpc, private_key=pk)
31
+
32
+ out = s.claim_referrer_rewards(
33
+ asset=args.asset,
34
+ receiver=args.receiver,
35
+ layerzero_fee_wei=args.lz_fee_wei,
36
+ dry_run=args.dry_run,
37
+ )
38
+ print(f"{'calldata' if args.dry_run else 'tx hash'}: {out}")
39
+ return 0
40
+
41
+
42
+ if __name__ == "__main__":
43
+ raise SystemExit(main())