clodds 1.2.9 → 1.3.0
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.
- package/dist/skills/bundled/acp/SKILL.md +188 -0
- package/dist/skills/bundled/acp/index.d.ts +0 -3
- package/dist/skills/bundled/acp/index.js +1 -1
- package/dist/skills/bundled/acp/index.js.map +1 -1
- package/dist/skills/bundled/agentbets/SKILL.md +19 -0
- package/dist/skills/bundled/ai-strategy/SKILL.md +111 -0
- package/dist/skills/bundled/ai-strategy/index.js +1 -1
- package/dist/skills/bundled/ai-strategy/index.js.map +1 -1
- package/dist/skills/bundled/alerts/SKILL.md +87 -0
- package/dist/skills/bundled/analytics/SKILL.md +252 -0
- package/dist/skills/bundled/analytics/index.js +2 -2
- package/dist/skills/bundled/analytics/index.js.map +1 -1
- package/dist/skills/bundled/arbitrage/SKILL.md +287 -0
- package/dist/skills/bundled/auto-reply/SKILL.md +285 -0
- package/dist/skills/bundled/auto-reply/index.js +2 -2
- package/dist/skills/bundled/auto-reply/index.js.map +1 -1
- package/dist/skills/bundled/automation/SKILL.md +242 -0
- package/dist/skills/bundled/automation/index.js +2 -2
- package/dist/skills/bundled/automation/index.js.map +1 -1
- package/dist/skills/bundled/backtest/SKILL.md +225 -0
- package/dist/skills/bundled/bags/SKILL.md +131 -0
- package/dist/skills/bundled/bankr/SKILL.md +114 -0
- package/dist/skills/bundled/betfair/SKILL.md +113 -0
- package/dist/skills/bundled/binance-futures/SKILL.md +84 -0
- package/dist/skills/bundled/binance-futures/index.d.ts +0 -3
- package/dist/skills/bundled/binance-futures/index.js +1 -2
- package/dist/skills/bundled/binance-futures/index.js.map +1 -1
- package/dist/skills/bundled/botchan/SKILL.md +66 -0
- package/dist/skills/bundled/botchan/index.d.ts +0 -3
- package/dist/skills/bundled/botchan/index.js +0 -1
- package/dist/skills/bundled/botchan/index.js.map +1 -1
- package/dist/skills/bundled/bridge/SKILL.md +215 -0
- package/dist/skills/bundled/bybit-futures/SKILL.md +84 -0
- package/dist/skills/bundled/bybit-futures/index.d.ts +0 -3
- package/dist/skills/bundled/bybit-futures/index.js +0 -1
- package/dist/skills/bundled/bybit-futures/index.js.map +1 -1
- package/dist/skills/bundled/clanker/SKILL.md +125 -0
- package/dist/skills/bundled/clanker/index.d.ts +0 -3
- package/dist/skills/bundled/clanker/index.js +0 -1
- package/dist/skills/bundled/clanker/index.js.map +1 -1
- package/dist/skills/bundled/copy-trading/SKILL.md +285 -0
- package/dist/skills/bundled/copy-trading/index.js +2 -2
- package/dist/skills/bundled/copy-trading/index.js.map +1 -1
- package/dist/skills/bundled/copy-trading-solana/SKILL.md +66 -0
- package/dist/skills/bundled/credentials/SKILL.md +261 -0
- package/dist/skills/bundled/crypto-hft/SKILL.md +121 -0
- package/dist/skills/bundled/dca/SKILL.md +27 -0
- package/dist/skills/bundled/dex/SKILL.md +87 -0
- package/dist/skills/bundled/divergence/SKILL.md +83 -0
- package/dist/skills/bundled/doctor/SKILL.md +267 -0
- package/dist/skills/bundled/doctor/index.js +2 -8
- package/dist/skills/bundled/doctor/index.js.map +1 -1
- package/dist/skills/bundled/drift/SKILL.md +53 -0
- package/dist/skills/bundled/drift-sdk/SKILL.md +103 -0
- package/dist/skills/bundled/drift-sdk/index.d.ts +0 -3
- package/dist/skills/bundled/drift-sdk/index.js +0 -1
- package/dist/skills/bundled/drift-sdk/index.js.map +1 -1
- package/dist/skills/bundled/edge/SKILL.md +84 -0
- package/dist/skills/bundled/embeddings/SKILL.md +244 -0
- package/dist/skills/bundled/endaoment/SKILL.md +65 -0
- package/dist/skills/bundled/endaoment/index.d.ts +0 -3
- package/dist/skills/bundled/endaoment/index.js +0 -1
- package/dist/skills/bundled/endaoment/index.js.map +1 -1
- package/dist/skills/bundled/ens/SKILL.md +63 -0
- package/dist/skills/bundled/ens/index.d.ts +0 -3
- package/dist/skills/bundled/ens/index.js +0 -1
- package/dist/skills/bundled/ens/index.js.map +1 -1
- package/dist/skills/bundled/erc8004/SKILL.md +79 -0
- package/dist/skills/bundled/erc8004/index.d.ts +0 -3
- package/dist/skills/bundled/erc8004/index.js +0 -1
- package/dist/skills/bundled/erc8004/index.js.map +1 -1
- package/dist/skills/bundled/execution/SKILL.md +278 -0
- package/dist/skills/bundled/farcaster/SKILL.md +80 -0
- package/dist/skills/bundled/features/SKILL.md +20 -0
- package/dist/skills/bundled/feeds/SKILL.md +288 -0
- package/dist/skills/bundled/harden/SKILL.md +74 -0
- package/dist/skills/bundled/history/SKILL.md +257 -0
- package/dist/skills/bundled/hyperliquid/SKILL.md +200 -0
- package/dist/skills/bundled/hyperliquid/index.d.ts +0 -3
- package/dist/skills/bundled/hyperliquid/index.js +0 -1
- package/dist/skills/bundled/hyperliquid/index.js.map +1 -1
- package/dist/skills/bundled/identity/SKILL.md +228 -0
- package/dist/skills/bundled/identity/index.js +2 -2
- package/dist/skills/bundled/identity/index.js.map +1 -1
- package/dist/skills/bundled/integrations/SKILL.md +321 -0
- package/dist/skills/bundled/integrations/index.js +2 -2
- package/dist/skills/bundled/integrations/index.js.map +1 -1
- package/dist/skills/bundled/jupiter/SKILL.md +163 -0
- package/dist/skills/bundled/kamino/SKILL.md +69 -0
- package/dist/skills/bundled/ledger/SKILL.md +20 -0
- package/dist/skills/bundled/lighter/SKILL.md +83 -0
- package/dist/skills/bundled/lighter/index.d.ts +0 -3
- package/dist/skills/bundled/lighter/index.js +0 -1
- package/dist/skills/bundled/lighter/index.js.map +1 -1
- package/dist/skills/bundled/marginfi/SKILL.md +62 -0
- package/dist/skills/bundled/market-index/SKILL.md +242 -0
- package/dist/skills/bundled/market-index/index.js +1 -3
- package/dist/skills/bundled/market-index/index.js.map +1 -1
- package/dist/skills/bundled/markets/SKILL.md +49 -0
- package/dist/skills/bundled/mcp/SKILL.md +235 -0
- package/dist/skills/bundled/mcp/index.js +1 -3
- package/dist/skills/bundled/mcp/index.js.map +1 -1
- package/dist/skills/bundled/memory/SKILL.md +209 -0
- package/dist/skills/bundled/metaculus/SKILL.md +62 -0
- package/dist/skills/bundled/meteora/SKILL.md +28 -0
- package/dist/skills/bundled/meteora-dbc/SKILL.md +25 -0
- package/dist/skills/bundled/metrics/SKILL.md +338 -0
- package/dist/skills/bundled/mev/SKILL.md +239 -0
- package/dist/skills/bundled/mev/index.js +2 -2
- package/dist/skills/bundled/mev/index.js.map +1 -1
- package/dist/skills/bundled/mexc-futures/SKILL.md +86 -0
- package/dist/skills/bundled/mexc-futures/index.d.ts +0 -3
- package/dist/skills/bundled/mexc-futures/index.js +0 -1
- package/dist/skills/bundled/mexc-futures/index.js.map +1 -1
- package/dist/skills/bundled/mm/SKILL.md +142 -0
- package/dist/skills/bundled/monitoring/SKILL.md +249 -0
- package/dist/skills/bundled/news/SKILL.md +95 -0
- package/dist/skills/bundled/onchainkit/SKILL.md +83 -0
- package/dist/skills/bundled/opinion/SKILL.md +87 -0
- package/dist/skills/bundled/opportunity/SKILL.md +308 -0
- package/dist/skills/bundled/orca/SKILL.md +28 -0
- package/dist/skills/bundled/pairing/SKILL.md +275 -0
- package/dist/skills/bundled/pancakeswap/SKILL.md +93 -0
- package/dist/skills/bundled/pancakeswap/index.d.ts +0 -3
- package/dist/skills/bundled/pancakeswap/index.js +0 -1
- package/dist/skills/bundled/pancakeswap/index.js.map +1 -1
- package/dist/skills/bundled/percolator/SKILL.md +22 -0
- package/dist/skills/bundled/permissions/SKILL.md +269 -0
- package/dist/skills/bundled/permissions/index.js +2 -2
- package/dist/skills/bundled/permissions/index.js.map +1 -1
- package/dist/skills/bundled/plugins/SKILL.md +263 -0
- package/dist/skills/bundled/plugins/index.js +2 -2
- package/dist/skills/bundled/plugins/index.js.map +1 -1
- package/dist/skills/bundled/portfolio/SKILL.md +161 -0
- package/dist/skills/bundled/portfolio/index.js +1 -1
- package/dist/skills/bundled/portfolio/index.js.map +1 -1
- package/dist/skills/bundled/portfolio-sync/SKILL.md +466 -0
- package/dist/skills/bundled/positions/SKILL.md +262 -0
- package/dist/skills/bundled/predictfun/SKILL.md +109 -0
- package/dist/skills/bundled/predictfun/index.js +1 -1
- package/dist/skills/bundled/predictfun/index.js.map +1 -1
- package/dist/skills/bundled/predictit/SKILL.md +66 -0
- package/dist/skills/bundled/presence/SKILL.md +217 -0
- package/dist/skills/bundled/presence/index.js +2 -2
- package/dist/skills/bundled/presence/index.js.map +1 -1
- package/dist/skills/bundled/processes/SKILL.md +254 -0
- package/dist/skills/bundled/pump-swarm/SKILL.md +309 -0
- package/dist/skills/bundled/pumpfun/SKILL.md +145 -0
- package/dist/skills/bundled/qmd/SKILL.md +129 -0
- package/dist/skills/bundled/qrcoin/SKILL.md +60 -0
- package/dist/skills/bundled/qrcoin/index.d.ts +0 -3
- package/dist/skills/bundled/qrcoin/index.js +0 -1
- package/dist/skills/bundled/qrcoin/index.js.map +1 -1
- package/dist/skills/bundled/raydium/SKILL.md +198 -0
- package/dist/skills/bundled/remote/SKILL.md +201 -0
- package/dist/skills/bundled/research/SKILL.md +83 -0
- package/dist/skills/bundled/research/index.js +2 -2
- package/dist/skills/bundled/research/index.js.map +1 -1
- package/dist/skills/bundled/risk/SKILL.md +323 -0
- package/dist/skills/bundled/router/SKILL.md +233 -0
- package/dist/skills/bundled/routing/SKILL.md +258 -0
- package/dist/skills/bundled/sandbox/SKILL.md +257 -0
- package/dist/skills/bundled/search-config/SKILL.md +257 -0
- package/dist/skills/bundled/search-config/index.js +2 -2
- package/dist/skills/bundled/search-config/index.js.map +1 -1
- package/dist/skills/bundled/sessions/SKILL.md +251 -0
- package/dist/skills/bundled/sessions/index.js +1 -1
- package/dist/skills/bundled/sessions/index.js.map +1 -1
- package/dist/skills/bundled/setup/SKILL.md +53 -0
- package/dist/skills/bundled/shield/SKILL.md +21 -0
- package/dist/skills/bundled/signals/SKILL.md +106 -0
- package/dist/skills/bundled/signals/index.d.ts +0 -3
- package/dist/skills/bundled/signals/index.js +3 -4
- package/dist/skills/bundled/signals/index.js.map +1 -1
- package/dist/skills/bundled/sizing/SKILL.md +238 -0
- package/dist/skills/bundled/slippage/SKILL.md +306 -0
- package/dist/skills/bundled/smarkets/SKILL.md +107 -0
- package/dist/skills/bundled/solend/SKILL.md +63 -0
- package/dist/skills/bundled/strategy/SKILL.md +266 -0
- package/dist/skills/bundled/streaming/SKILL.md +150 -0
- package/dist/skills/bundled/streaming/index.js +2 -2
- package/dist/skills/bundled/streaming/index.js.map +1 -1
- package/dist/skills/bundled/tailscale/SKILL.md +249 -0
- package/dist/skills/bundled/tailscale/index.js +2 -2
- package/dist/skills/bundled/tailscale/index.js.map +1 -1
- package/dist/skills/bundled/ticks/SKILL.md +61 -0
- package/dist/skills/bundled/token-security/SKILL.md +18 -0
- package/dist/skills/bundled/trading-evm/SKILL.md +329 -0
- package/dist/skills/bundled/trading-futures/SKILL.md +865 -0
- package/dist/skills/bundled/trading-kalshi/SKILL.md +629 -0
- package/dist/skills/bundled/trading-manifold/SKILL.md +387 -0
- package/dist/skills/bundled/trading-polymarket/SKILL.md +1080 -0
- package/dist/skills/bundled/trading-solana/SKILL.md +418 -0
- package/dist/skills/bundled/trading-system/SKILL.md +290 -0
- package/dist/skills/bundled/triggers/SKILL.md +433 -0
- package/dist/skills/bundled/tts/SKILL.md +220 -0
- package/dist/skills/bundled/tweet-ideas/SKILL.md +77 -0
- package/dist/skills/bundled/usage/SKILL.md +239 -0
- package/dist/skills/bundled/usage/index.js +2 -2
- package/dist/skills/bundled/usage/index.js.map +1 -1
- package/dist/skills/bundled/veil/SKILL.md +76 -0
- package/dist/skills/bundled/veil/index.d.ts +0 -3
- package/dist/skills/bundled/veil/index.js +0 -1
- package/dist/skills/bundled/veil/index.js.map +1 -1
- package/dist/skills/bundled/verify/SKILL.md +199 -0
- package/dist/skills/bundled/verify/index.d.ts +0 -3
- package/dist/skills/bundled/verify/index.js +0 -1
- package/dist/skills/bundled/verify/index.js.map +1 -1
- package/dist/skills/bundled/virtuals/SKILL.md +82 -0
- package/dist/skills/bundled/voice/SKILL.md +217 -0
- package/dist/skills/bundled/voice/index.js +2 -2
- package/dist/skills/bundled/voice/index.js.map +1 -1
- package/dist/skills/bundled/weather/SKILL.md +80 -0
- package/dist/skills/bundled/webhooks/SKILL.md +297 -0
- package/dist/skills/bundled/webhooks/index.js +2 -2
- package/dist/skills/bundled/webhooks/index.js.map +1 -1
- package/dist/skills/bundled/whale-tracking/SKILL.md +287 -0
- package/dist/skills/bundled/whale-tracking/index.js +2 -2
- package/dist/skills/bundled/whale-tracking/index.js.map +1 -1
- package/dist/skills/bundled/yoink/SKILL.md +54 -0
- package/dist/skills/bundled/yoink/index.d.ts +0 -3
- package/dist/skills/bundled/yoink/index.js +0 -1
- package/dist/skills/bundled/yoink/index.js.map +1 -1
- package/dist/skills/executor.js +5 -3
- package/dist/skills/executor.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opinion
|
|
3
|
+
description: Opinion.trade prediction market (BNB Chain CLOB)
|
|
4
|
+
emoji: "🗳️"
|
|
5
|
+
commands:
|
|
6
|
+
- /op
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Opinion.trade
|
|
10
|
+
|
|
11
|
+
Full integration with Opinion.trade, a BNB Chain prediction market with on-chain CLOB (Central Limit Order Book).
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Set credentials
|
|
17
|
+
export OPINION_API_KEY="your-api-key"
|
|
18
|
+
export OPINION_PRIVATE_KEY="0x..."
|
|
19
|
+
|
|
20
|
+
# Search markets
|
|
21
|
+
/op markets trump
|
|
22
|
+
|
|
23
|
+
# Get price
|
|
24
|
+
/op price 813
|
|
25
|
+
|
|
26
|
+
# Place order
|
|
27
|
+
/op buy 813 YES 0.55 100
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
### Market Data
|
|
33
|
+
|
|
34
|
+
| Command | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| `/op markets [query]` | Search markets |
|
|
37
|
+
| `/op market <id>` | Get market details |
|
|
38
|
+
| `/op price <id>` | Current prices |
|
|
39
|
+
| `/op book <tokenId>` | Show orderbook |
|
|
40
|
+
|
|
41
|
+
### Trading
|
|
42
|
+
|
|
43
|
+
| Command | Description |
|
|
44
|
+
|---------|-------------|
|
|
45
|
+
| `/op buy <marketId> <outcome> <price> <size>` | Place buy order |
|
|
46
|
+
| `/op sell <marketId> <outcome> <price> <size>` | Place sell order |
|
|
47
|
+
| `/op cancel <orderId>` | Cancel order |
|
|
48
|
+
| `/op cancelall` | Cancel all orders |
|
|
49
|
+
| `/op orders` | List open orders |
|
|
50
|
+
|
|
51
|
+
**Examples:**
|
|
52
|
+
```bash
|
|
53
|
+
/op buy 813 YES 0.55 100 # Buy YES at 55c, 100 shares
|
|
54
|
+
/op sell 813 NO 0.40 50 # Sell NO at 40c, 50 shares
|
|
55
|
+
/op cancel abc123 # Cancel specific order
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Account
|
|
59
|
+
|
|
60
|
+
| Command | Description |
|
|
61
|
+
|---------|-------------|
|
|
62
|
+
| `/op balance` | Check USDT balance |
|
|
63
|
+
| `/op positions` | View open positions |
|
|
64
|
+
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Required for market data
|
|
69
|
+
export OPINION_API_KEY="your-api-key"
|
|
70
|
+
|
|
71
|
+
# Required for trading
|
|
72
|
+
export OPINION_PRIVATE_KEY="0x..."
|
|
73
|
+
export OPINION_MULTISIG_ADDRESS="0x..." # Vault/funder address
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Features
|
|
77
|
+
|
|
78
|
+
- **BNB Chain** - Fast, low-cost transactions
|
|
79
|
+
- **On-chain CLOB** - Fully decentralized orderbook
|
|
80
|
+
- **Prediction Markets** - Politics, crypto, sports, and more
|
|
81
|
+
- **Real-time WebSocket** - Live price updates
|
|
82
|
+
- **EIP-712 Signing** - Secure order authentication
|
|
83
|
+
|
|
84
|
+
## Resources
|
|
85
|
+
|
|
86
|
+
- [Opinion.trade App](https://opinion.trade)
|
|
87
|
+
- [API Documentation](https://docs.opinion.trade)
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opportunity
|
|
3
|
+
description: "Find and execute cross-platform arbitrage opportunities across prediction markets"
|
|
4
|
+
emoji: "🎯"
|
|
5
|
+
gates:
|
|
6
|
+
envs:
|
|
7
|
+
anyOf:
|
|
8
|
+
- POLY_API_KEY
|
|
9
|
+
- KALSHI_API_KEY
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Opportunity Finder - Complete API Reference
|
|
13
|
+
|
|
14
|
+
Discover and execute cross-platform arbitrage opportunities across Polymarket, Kalshi, Betfair, Smarkets, Manifold, Metaculus, PredictIt, and Drift.
|
|
15
|
+
|
|
16
|
+
Based on [arXiv:2508.03474](https://arxiv.org/abs/2508.03474) which found **$40M+ in realized arbitrage** on Polymarket.
|
|
17
|
+
|
|
18
|
+
## Opportunity Types
|
|
19
|
+
|
|
20
|
+
| Type | Description | Example |
|
|
21
|
+
|------|-------------|---------|
|
|
22
|
+
| **Internal** | YES + NO < $1 on same platform | Buy both for guaranteed profit |
|
|
23
|
+
| **Cross-Platform** | Same market priced differently | Buy low on A, sell high on B |
|
|
24
|
+
| **Combinatorial** | Logical violations (P(A) > P(B) when A implies B) | Trump > Republican |
|
|
25
|
+
| **Edge** | Market vs external model (538, polls) | Market 45%, model 52% |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Chat Commands
|
|
30
|
+
|
|
31
|
+
### Scanning
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
/opportunities scan # Scan all platforms for opportunities
|
|
35
|
+
/opportunities scan "trump" # Scan with keyword filter
|
|
36
|
+
/opportunities scan --min-edge 2 # Min 2% edge
|
|
37
|
+
/opportunities scan --min-liquidity 1000 # Min $1000 liquidity
|
|
38
|
+
|
|
39
|
+
/opportunities active # View active opportunities
|
|
40
|
+
/opportunities active --sort edge # Sort by edge size
|
|
41
|
+
/opportunities active --sort liquidity # Sort by liquidity
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Real-Time Monitoring
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
/opportunities realtime start # Start continuous scanning
|
|
48
|
+
/opportunities realtime stop # Stop scanning
|
|
49
|
+
/opportunities realtime status # Check monitoring status
|
|
50
|
+
/opportunities realtime config --interval 30 # Set scan interval (seconds)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Market Linking
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
/opportunities link <market-a> <market-b> # Manually link equivalent markets
|
|
57
|
+
/opportunities unlink <market-a> <market-b> # Remove link
|
|
58
|
+
/opportunities links # View all linked markets
|
|
59
|
+
/opportunities auto-match # Run auto-matching algorithm
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Execution
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
/opportunities execute <id> # Execute an opportunity
|
|
66
|
+
/opportunities execute <id> --size 100 # Execute with $100 size
|
|
67
|
+
/opportunities mark-taken <id> # Mark as taken (manual)
|
|
68
|
+
/opportunities record-outcome <id> <pnl> # Record P&L outcome
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Analytics
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
/opportunities stats # Performance statistics
|
|
75
|
+
/opportunities stats --period 7d # Last 7 days
|
|
76
|
+
/opportunities history # Past opportunities
|
|
77
|
+
/opportunities by-platform # Stats by platform pair
|
|
78
|
+
/opportunities by-type # Stats by opportunity type
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Risk Modeling
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
/opportunities risk <id> # Model execution risk
|
|
85
|
+
/opportunities estimate <id> # Estimate execution costs
|
|
86
|
+
/opportunities kelly <id> # Calculate Kelly fraction
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## TypeScript API Reference
|
|
92
|
+
|
|
93
|
+
### Create Opportunity Finder
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { createOpportunityFinder } from 'clodds/opportunity';
|
|
97
|
+
|
|
98
|
+
const finder = createOpportunityFinder({
|
|
99
|
+
platforms: ['polymarket', 'kalshi', 'betfair', 'manifold'],
|
|
100
|
+
|
|
101
|
+
// Filtering
|
|
102
|
+
minEdge: 0.5, // 0.5% minimum edge
|
|
103
|
+
minLiquidity: 500, // $500 minimum liquidity
|
|
104
|
+
minConfidence: 0.7, // 70% match confidence
|
|
105
|
+
|
|
106
|
+
// Real-time
|
|
107
|
+
enableRealtime: true,
|
|
108
|
+
scanIntervalMs: 30000, // 30 second intervals
|
|
109
|
+
|
|
110
|
+
// Credentials
|
|
111
|
+
polymarket: { apiKey, apiSecret, passphrase, privateKey },
|
|
112
|
+
kalshi: { apiKey, privateKey },
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Scan for Opportunities
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// One-time scan
|
|
120
|
+
const opportunities = await finder.scan({
|
|
121
|
+
query: 'election', // Optional keyword
|
|
122
|
+
minEdge: 1, // 1% minimum
|
|
123
|
+
minLiquidity: 1000, // $1000 minimum
|
|
124
|
+
platforms: ['polymarket', 'kalshi'],
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
for (const opp of opportunities) {
|
|
128
|
+
console.log(`${opp.type}: ${opp.description}`);
|
|
129
|
+
console.log(` Edge: ${opp.edge.toFixed(2)}%`);
|
|
130
|
+
console.log(` Liquidity: $${opp.liquidity.toLocaleString()}`);
|
|
131
|
+
console.log(` Confidence: ${(opp.confidence * 100).toFixed(0)}%`);
|
|
132
|
+
console.log(` Score: ${opp.score}/100`);
|
|
133
|
+
console.log(` Platforms: ${opp.platforms.join(' ↔ ')}`);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Real-Time Monitoring
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Start real-time scanning
|
|
141
|
+
await finder.startRealtime();
|
|
142
|
+
|
|
143
|
+
// Event handlers
|
|
144
|
+
finder.on('opportunity', (opp) => {
|
|
145
|
+
console.log(`🎯 New opportunity: ${opp.description}`);
|
|
146
|
+
console.log(` Edge: ${opp.edge.toFixed(2)}%`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
finder.on('opportunityExpired', (opp) => {
|
|
150
|
+
console.log(`❌ Opportunity expired: ${opp.id}`);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
finder.on('opportunityUpdated', (opp) => {
|
|
154
|
+
console.log(`📊 Updated: ${opp.id} - Edge now ${opp.edge.toFixed(2)}%`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Get active opportunities
|
|
158
|
+
const active = await finder.getActive();
|
|
159
|
+
|
|
160
|
+
// Stop monitoring
|
|
161
|
+
await finder.stopRealtime();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Market Linking
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Manually link equivalent markets
|
|
168
|
+
await finder.linkMarkets(
|
|
169
|
+
{ platform: 'polymarket', id: 'market-123' },
|
|
170
|
+
{ platform: 'kalshi', id: 'TRUMP-WIN' }
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Auto-match using semantic similarity
|
|
174
|
+
const matches = await finder.autoMatchMarkets({
|
|
175
|
+
minSimilarity: 0.85,
|
|
176
|
+
platforms: ['polymarket', 'kalshi'],
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
console.log(`Found ${matches.length} potential matches`);
|
|
180
|
+
for (const match of matches) {
|
|
181
|
+
console.log(`${match.marketA.question}`);
|
|
182
|
+
console.log(` ↔ ${match.marketB.question}`);
|
|
183
|
+
console.log(` Similarity: ${(match.similarity * 100).toFixed(0)}%`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Get all links
|
|
187
|
+
const links = await finder.getLinks();
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Execute Opportunity
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Execute an opportunity
|
|
194
|
+
const result = await finder.execute(opportunityId, {
|
|
195
|
+
size: 100, // $100 position
|
|
196
|
+
maxSlippage: 0.5, // 0.5% max slippage
|
|
197
|
+
useProtectedOrders: true,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
console.log(`Executed: ${result.status}`);
|
|
201
|
+
console.log(` Filled: $${result.filledSize}`);
|
|
202
|
+
console.log(` Avg price: ${result.avgPrice}`);
|
|
203
|
+
console.log(` Fees: $${result.fees}`);
|
|
204
|
+
|
|
205
|
+
// Mark as taken manually
|
|
206
|
+
await finder.markTaken(opportunityId);
|
|
207
|
+
|
|
208
|
+
// Record outcome
|
|
209
|
+
await finder.recordOutcome(opportunityId, {
|
|
210
|
+
pnl: 25.50,
|
|
211
|
+
exitPrice: 0.55,
|
|
212
|
+
exitTimestamp: Date.now(),
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Analytics
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// Get statistics
|
|
220
|
+
const stats = await finder.getAnalytics({
|
|
221
|
+
period: '30d',
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
console.log(`Total opportunities: ${stats.total}`);
|
|
225
|
+
console.log(`Taken: ${stats.taken}`);
|
|
226
|
+
console.log(`Win rate: ${(stats.winRate * 100).toFixed(1)}%`);
|
|
227
|
+
console.log(`Total P&L: $${stats.totalPnl.toLocaleString()}`);
|
|
228
|
+
console.log(`Avg edge: ${stats.avgEdge.toFixed(2)}%`);
|
|
229
|
+
console.log(`By platform pair:`);
|
|
230
|
+
for (const [pair, data] of Object.entries(stats.byPlatformPair)) {
|
|
231
|
+
console.log(` ${pair}: ${data.count} opps, $${data.pnl} P&L`);
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Risk Modeling
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
// Model execution risk
|
|
239
|
+
const risk = await finder.modelRisk(opportunityId);
|
|
240
|
+
|
|
241
|
+
console.log(`Execution risk:`);
|
|
242
|
+
console.log(` Fill probability: ${(risk.fillProbability * 100).toFixed(0)}%`);
|
|
243
|
+
console.log(` Expected slippage: ${risk.expectedSlippage.toFixed(2)}%`);
|
|
244
|
+
console.log(` Time to fill: ${risk.estimatedTimeToFill}s`);
|
|
245
|
+
console.log(` Counterparty risk: ${risk.counterpartyRisk}`);
|
|
246
|
+
|
|
247
|
+
// Estimate execution
|
|
248
|
+
const estimate = await finder.estimateExecution(opportunityId, {
|
|
249
|
+
size: 500,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
console.log(`Execution estimate for $500:`);
|
|
253
|
+
console.log(` Expected fill: $${estimate.expectedFill}`);
|
|
254
|
+
console.log(` Expected cost: $${estimate.expectedCost}`);
|
|
255
|
+
console.log(` Net edge after costs: ${estimate.netEdge.toFixed(2)}%`);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Opportunity Scoring
|
|
261
|
+
|
|
262
|
+
Opportunities are scored 0-100 based on:
|
|
263
|
+
|
|
264
|
+
| Factor | Weight | Description |
|
|
265
|
+
|--------|--------|-------------|
|
|
266
|
+
| Edge % | 35% | Raw arbitrage spread |
|
|
267
|
+
| Liquidity | 25% | Available volume |
|
|
268
|
+
| Confidence | 25% | Match quality |
|
|
269
|
+
| Execution | 15% | Platform reliability |
|
|
270
|
+
|
|
271
|
+
### Penalties
|
|
272
|
+
|
|
273
|
+
- Low liquidity (<$1000): -5 points
|
|
274
|
+
- Cross-platform complexity: -3 per platform
|
|
275
|
+
- High slippage (>2%): -5 points
|
|
276
|
+
- Low confidence (<70%): -5 points
|
|
277
|
+
- Near expiry (<24h): -3 points
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Semantic Matching
|
|
282
|
+
|
|
283
|
+
Markets are matched using:
|
|
284
|
+
|
|
285
|
+
1. **Exact slug match** - Platform-specific IDs
|
|
286
|
+
2. **Text similarity** - Jaccard coefficient
|
|
287
|
+
3. **Vector embeddings** - Semantic similarity
|
|
288
|
+
4. **Manual links** - User-defined
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// Configure matching
|
|
292
|
+
finder.setMatchingConfig({
|
|
293
|
+
minTextSimilarity: 0.8,
|
|
294
|
+
minEmbeddingSimilarity: 0.85,
|
|
295
|
+
useManualLinksFirst: true,
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Best Practices
|
|
302
|
+
|
|
303
|
+
1. **Start with high-confidence matches** - 85%+ similarity
|
|
304
|
+
2. **Check liquidity** - Ensure enough volume to execute
|
|
305
|
+
3. **Account for fees** - Factor in platform fees
|
|
306
|
+
4. **Use protected orders** - Avoid slippage
|
|
307
|
+
5. **Monitor in real-time** - Opportunities disappear fast
|
|
308
|
+
6. **Track outcomes** - Build performance history
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: orca
|
|
3
|
+
description: "Orca Whirlpools - concentrated liquidity on Solana"
|
|
4
|
+
command: orca
|
|
5
|
+
emoji: "🐋"
|
|
6
|
+
gates:
|
|
7
|
+
envs:
|
|
8
|
+
- SOLANA_PRIVATE_KEY
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Orca Whirlpools
|
|
12
|
+
|
|
13
|
+
Orca is a Solana DEX with concentrated liquidity pools (Whirlpools).
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/orca swap <amount> <from> to <to> Execute swap
|
|
19
|
+
/orca quote <amount> <from> to <to> Get quote
|
|
20
|
+
/orca pools <token> List Whirlpools
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/orca swap 1 SOL to USDC
|
|
27
|
+
/orca pools ORCA
|
|
28
|
+
```
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pairing
|
|
3
|
+
description: "User pairing, authentication, and trust management"
|
|
4
|
+
emoji: "🔗"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Pairing - Complete API Reference
|
|
8
|
+
|
|
9
|
+
Pair new users to Clodds, manage trust levels, and control access across channels.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Chat Commands
|
|
14
|
+
|
|
15
|
+
### Pairing (New Users)
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/pair Request pairing (generates code)
|
|
19
|
+
/pair-code ABC123 Enter pairing code
|
|
20
|
+
/unpair Remove your pairing
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Admin Commands
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/pairing list List pending requests
|
|
27
|
+
/pairing approve <code> Approve pairing request
|
|
28
|
+
/pairing reject <code> Reject pairing request
|
|
29
|
+
/pairing users List paired users
|
|
30
|
+
/pairing remove <user> Remove user pairing
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Trust Management
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
/trust <user> owner Grant owner trust
|
|
37
|
+
/trust <user> paired Standard trust
|
|
38
|
+
/trust list List trust levels
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## TypeScript API Reference
|
|
44
|
+
|
|
45
|
+
### Create Pairing Service
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createPairingService } from 'clodds/pairing';
|
|
49
|
+
|
|
50
|
+
const pairing = createPairingService({
|
|
51
|
+
// Code settings
|
|
52
|
+
codeLength: 8,
|
|
53
|
+
codeExpiryMinutes: 60,
|
|
54
|
+
maxPendingPerChannel: 3,
|
|
55
|
+
|
|
56
|
+
// Auto-approve settings
|
|
57
|
+
autoApproveLocal: true, // Auto-approve localhost
|
|
58
|
+
autoApproveTailscale: true, // Auto-approve Tailscale IPs
|
|
59
|
+
autoApproveOwners: true, // Owners auto-approve their requests
|
|
60
|
+
|
|
61
|
+
// Storage
|
|
62
|
+
storage: 'sqlite',
|
|
63
|
+
dbPath: './pairing.db',
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Create Pairing Request
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// User requests pairing
|
|
71
|
+
const request = await pairing.createPairingRequest({
|
|
72
|
+
channelId: 'telegram-123',
|
|
73
|
+
userId: 'telegram-user-456',
|
|
74
|
+
username: 'johndoe',
|
|
75
|
+
displayName: 'John Doe',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log(`Pairing code: ${request.code}`);
|
|
79
|
+
console.log(`Expires: ${request.expiresAt}`);
|
|
80
|
+
console.log(`Share this code with an admin to get approved`);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Validate Code
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Check if code is valid
|
|
87
|
+
const valid = await pairing.validateCode({
|
|
88
|
+
code: 'ABC123XY',
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
if (valid) {
|
|
92
|
+
console.log(`Valid code for user: ${valid.username}`);
|
|
93
|
+
console.log(`Channel: ${valid.channelId}`);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Approve Request
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// Admin approves pairing
|
|
101
|
+
await pairing.approveRequest({
|
|
102
|
+
code: 'ABC123XY',
|
|
103
|
+
approvedBy: 'admin-user-id',
|
|
104
|
+
trustLevel: 'paired',
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Reject Request
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// Admin rejects pairing
|
|
112
|
+
await pairing.rejectRequest({
|
|
113
|
+
code: 'ABC123XY',
|
|
114
|
+
rejectedBy: 'admin-user-id',
|
|
115
|
+
reason: 'Unknown user',
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Check Pairing Status
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// Check if user is paired
|
|
123
|
+
const isPaired = await pairing.isPaired({
|
|
124
|
+
channelId: 'telegram-123',
|
|
125
|
+
userId: 'telegram-user-456',
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (isPaired) {
|
|
129
|
+
console.log('User is paired and can use Clodds');
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Get Trust Level
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const trust = await pairing.getTrustLevel({
|
|
137
|
+
channelId: 'telegram-123',
|
|
138
|
+
userId: 'telegram-user-456',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
console.log(`Trust level: ${trust}`);
|
|
142
|
+
// 'owner' | 'paired' | 'stranger'
|
|
143
|
+
|
|
144
|
+
// Check specific permission
|
|
145
|
+
if (trust === 'owner') {
|
|
146
|
+
console.log('Full admin access');
|
|
147
|
+
} else if (trust === 'paired') {
|
|
148
|
+
console.log('Standard trading access');
|
|
149
|
+
} else {
|
|
150
|
+
console.log('No access - must pair first');
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### List Pending Requests
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const pending = await pairing.listPendingRequests({
|
|
158
|
+
channelId: 'telegram-123', // Optional: filter by channel
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
for (const req of pending) {
|
|
162
|
+
console.log(`Code: ${req.code}`);
|
|
163
|
+
console.log(`User: ${req.username} (${req.displayName})`);
|
|
164
|
+
console.log(`Requested: ${req.createdAt}`);
|
|
165
|
+
console.log(`Expires: ${req.expiresAt}`);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### List Paired Users
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
const users = await pairing.listPairedUsers({
|
|
173
|
+
channelId: 'telegram-123', // Optional: filter by channel
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
for (const user of users) {
|
|
177
|
+
console.log(`${user.username}: ${user.trustLevel}`);
|
|
178
|
+
console.log(` Paired: ${user.pairedAt}`);
|
|
179
|
+
console.log(` Approved by: ${user.approvedBy}`);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Check Owner Status
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const isOwner = await pairing.isOwner({
|
|
187
|
+
channelId: 'telegram-123',
|
|
188
|
+
userId: 'telegram-user-456',
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
if (isOwner) {
|
|
192
|
+
console.log('User has owner privileges');
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Remove Pairing
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Remove user's pairing
|
|
200
|
+
await pairing.removePairing({
|
|
201
|
+
channelId: 'telegram-123',
|
|
202
|
+
userId: 'telegram-user-456',
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Trust Levels
|
|
209
|
+
|
|
210
|
+
| Level | Access |
|
|
211
|
+
|-------|--------|
|
|
212
|
+
| **owner** | Full admin: approve users, manage settings, trading |
|
|
213
|
+
| **paired** | Standard: trading, portfolio, queries |
|
|
214
|
+
| **stranger** | None: must pair first |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Pairing Code Format
|
|
219
|
+
|
|
220
|
+
- **Length**: 8 characters
|
|
221
|
+
- **Characters**: Uppercase letters + numbers
|
|
222
|
+
- **Excludes**: 0, O, 1, I, L (avoid confusion)
|
|
223
|
+
- **Example**: `ABC234XY`
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Auto-Approve Rules
|
|
228
|
+
|
|
229
|
+
| Condition | Behavior |
|
|
230
|
+
|-----------|----------|
|
|
231
|
+
| Localhost | Auto-approve with owner trust |
|
|
232
|
+
| Tailscale IP | Auto-approve with owner trust |
|
|
233
|
+
| Owner request | Auto-approve their other channels |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Security Features
|
|
238
|
+
|
|
239
|
+
| Feature | Description |
|
|
240
|
+
|---------|-------------|
|
|
241
|
+
| **Code expiry** | Codes expire after 1 hour |
|
|
242
|
+
| **Rate limiting** | Max 3 pending per channel |
|
|
243
|
+
| **Unambiguous codes** | No confusable characters |
|
|
244
|
+
| **Audit trail** | Who approved/rejected when |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## CLI Admin Commands
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
# List pending pairing requests
|
|
252
|
+
clodds pairing list telegram
|
|
253
|
+
|
|
254
|
+
# Approve a request
|
|
255
|
+
clodds pairing approve ABC234XY
|
|
256
|
+
|
|
257
|
+
# List paired users
|
|
258
|
+
clodds pairing users telegram
|
|
259
|
+
|
|
260
|
+
# Add user directly (bypass code)
|
|
261
|
+
clodds pairing add telegram user-123
|
|
262
|
+
|
|
263
|
+
# Remove user
|
|
264
|
+
clodds pairing remove telegram user-123
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Best Practices
|
|
270
|
+
|
|
271
|
+
1. **Share codes securely** — Don't post in public channels
|
|
272
|
+
2. **Set expiry appropriately** — Shorter for sensitive systems
|
|
273
|
+
3. **Review pending regularly** — Don't let requests pile up
|
|
274
|
+
4. **Use owner sparingly** — Most users only need 'paired'
|
|
275
|
+
5. **Audit periodically** — Review who has access
|