@slvr-labs/sdk 0.1.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.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +849 -0
  3. package/dist/connect.d.ts +47 -0
  4. package/dist/connect.d.ts.map +1 -0
  5. package/dist/connect.js +56 -0
  6. package/dist/connect.js.map +1 -0
  7. package/dist/contracts/autoCommit.d.ts +151 -0
  8. package/dist/contracts/autoCommit.d.ts.map +1 -0
  9. package/dist/contracts/autoCommit.js +426 -0
  10. package/dist/contracts/autoCommit.js.map +1 -0
  11. package/dist/contracts/hub.d.ts +50 -0
  12. package/dist/contracts/hub.d.ts.map +1 -0
  13. package/dist/contracts/hub.js +118 -0
  14. package/dist/contracts/hub.js.map +1 -0
  15. package/dist/contracts/index.d.ts +8 -0
  16. package/dist/contracts/index.d.ts.map +1 -0
  17. package/dist/contracts/index.js +18 -0
  18. package/dist/contracts/index.js.map +1 -0
  19. package/dist/contracts/jackpot.d.ts +21 -0
  20. package/dist/contracts/jackpot.d.ts.map +1 -0
  21. package/dist/contracts/jackpot.js +44 -0
  22. package/dist/contracts/jackpot.js.map +1 -0
  23. package/dist/contracts/lottery.d.ts +256 -0
  24. package/dist/contracts/lottery.d.ts.map +1 -0
  25. package/dist/contracts/lottery.js +767 -0
  26. package/dist/contracts/lottery.js.map +1 -0
  27. package/dist/contracts/registry.d.ts +53 -0
  28. package/dist/contracts/registry.d.ts.map +1 -0
  29. package/dist/contracts/registry.js +143 -0
  30. package/dist/contracts/registry.js.map +1 -0
  31. package/dist/contracts/staking.d.ts +101 -0
  32. package/dist/contracts/staking.d.ts.map +1 -0
  33. package/dist/contracts/staking.js +306 -0
  34. package/dist/contracts/staking.js.map +1 -0
  35. package/dist/contracts/token.d.ts +95 -0
  36. package/dist/contracts/token.d.ts.map +1 -0
  37. package/dist/contracts/token.js +273 -0
  38. package/dist/contracts/token.js.map +1 -0
  39. package/dist/deployments.d.ts +117 -0
  40. package/dist/deployments.d.ts.map +1 -0
  41. package/dist/deployments.js +74 -0
  42. package/dist/deployments.js.map +1 -0
  43. package/dist/errors.d.ts +39 -0
  44. package/dist/errors.d.ts.map +1 -0
  45. package/dist/errors.js +67 -0
  46. package/dist/errors.js.map +1 -0
  47. package/dist/ev.d.ts +123 -0
  48. package/dist/ev.d.ts.map +1 -0
  49. package/dist/ev.js +111 -0
  50. package/dist/ev.js.map +1 -0
  51. package/dist/events.d.ts +418 -0
  52. package/dist/events.d.ts.map +1 -0
  53. package/dist/events.js +87 -0
  54. package/dist/events.js.map +1 -0
  55. package/dist/index.d.ts +248 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +436 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/oracle.d.ts +48 -0
  60. package/dist/oracle.d.ts.map +1 -0
  61. package/dist/oracle.js +77 -0
  62. package/dist/oracle.js.map +1 -0
  63. package/dist/price.d.ts +52 -0
  64. package/dist/price.d.ts.map +1 -0
  65. package/dist/price.js +78 -0
  66. package/dist/price.js.map +1 -0
  67. package/dist/transaction.d.ts +54 -0
  68. package/dist/transaction.d.ts.map +1 -0
  69. package/dist/transaction.js +105 -0
  70. package/dist/transaction.js.map +1 -0
  71. package/dist/types.d.ts +162 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +23 -0
  74. package/dist/types.js.map +1 -0
  75. package/dist/utils.d.ts +58 -0
  76. package/dist/utils.d.ts.map +1 -0
  77. package/dist/utils.js +110 -0
  78. package/dist/utils.js.map +1 -0
  79. package/examples/.env.example +22 -0
  80. package/examples/README.md +417 -0
  81. package/examples/automated-betting.ts +232 -0
  82. package/examples/combined-strategy.ts +227 -0
  83. package/examples/constants.ts +35 -0
  84. package/examples/custom-strategy-example.ts +231 -0
  85. package/examples/expected-value-strategy.ts +255 -0
  86. package/examples/fixed-squares-strategy.ts +176 -0
  87. package/examples/index.ts +30 -0
  88. package/examples/least-allocated-strategy.ts +224 -0
  89. package/examples/local-test.ts +172 -0
  90. package/examples/quickstart-bet.ts +72 -0
  91. package/examples/quickstart-read.ts +87 -0
  92. package/examples/simple-example.ts +122 -0
  93. package/examples/strategy-base.ts +283 -0
  94. package/package.json +71 -0
  95. package/skills/slvr-bot/SKILL.md +193 -0
  96. package/skills/slvr-bot/references/api.md +117 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Example SDK usage against local Anvil instance
3
+ *
4
+ * Usage:
5
+ * 1. Start local environment: ./scripts/start-local.sh
6
+ * 2. Update contract addresses below
7
+ * 3. Run: npx tsx examples/local-test.ts
8
+ */
9
+
10
+ import { createPublicClient, createWalletClient, http, parseEther } from 'viem';
11
+ import { privateKeyToAccount } from 'viem/accounts';
12
+ import { SlvrSDK } from '../src/index';
13
+
14
+ // Local Anvil configuration
15
+ const RPC_URL = process.env.RPC_URL || 'http://localhost:8545';
16
+ const CHAIN_ID = 31337;
17
+
18
+ // Update these addresses after deployment (from script/deployments/localhost.json)
19
+ const CONTRACT_ADDRESSES = {
20
+ lottery: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Update this
21
+ staking: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Update this (SlvrVoteEscrowStaking)
22
+ token: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Update this
23
+ autoCommit: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Optional
24
+ hub: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Optional: SlvrHub
25
+ registry: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Optional: SlvrGameRegistry
26
+ jackpot: '0x0000000000000000000000000000000000000000' as `0x${string}`, // Optional: SlvrJackpot
27
+ };
28
+
29
+ // The veNFT tokenId to inspect for staking (update after staking a token)
30
+ const STAKING_TOKEN_ID = 1n;
31
+
32
+ // Use Anvil's first account (or set your own private key)
33
+ const PRIVATE_KEY = process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
34
+
35
+ // Define localhost chain
36
+ const localhostChain = {
37
+ id: CHAIN_ID,
38
+ name: 'Localhost',
39
+ nativeCurrency: {
40
+ decimals: 18,
41
+ name: 'Ether',
42
+ symbol: 'ETH',
43
+ },
44
+ rpcUrls: {
45
+ default: {
46
+ http: [RPC_URL],
47
+ },
48
+ },
49
+ } as const;
50
+
51
+ async function main() {
52
+ console.log('🚀 Testing SLVR SDK against local Anvil instance\n');
53
+ console.log(`RPC URL: ${RPC_URL}`);
54
+ console.log(`Chain ID: ${CHAIN_ID}\n`);
55
+
56
+ // Create clients
57
+ const publicClient = createPublicClient({
58
+ chain: localhostChain,
59
+ transport: http(RPC_URL),
60
+ });
61
+
62
+ const account = privateKeyToAccount(PRIVATE_KEY as `0x${string}`);
63
+ const walletClient = createWalletClient({
64
+ chain: localhostChain,
65
+ transport: http(RPC_URL),
66
+ account,
67
+ });
68
+
69
+ console.log(`Using account: ${account.address}\n`);
70
+
71
+ // Initialize SDK
72
+ const sdk = new SlvrSDK({
73
+ publicClient,
74
+ walletClient,
75
+ addresses: CONTRACT_ADDRESSES,
76
+ });
77
+
78
+ try {
79
+ // Test 1: Get current round
80
+ console.log('📊 Test 1: Get current round');
81
+ const currentRoundId = await sdk.lottery.currentRoundId();
82
+ console.log(` Current round ID: ${currentRoundId}\n`);
83
+
84
+ // Test 2: Get round info
85
+ console.log('📊 Test 2: Get round info');
86
+ const roundInfo = await sdk.lottery.getRound(currentRoundId);
87
+ console.log(` Round ${currentRoundId}:`, {
88
+ totalWager: roundInfo.totalWager.toString(),
89
+ resolved: roundInfo.resolved,
90
+ winningSquare: roundInfo.winningSquare,
91
+ });
92
+ console.log('');
93
+
94
+ // Test 3: Get token balance
95
+ console.log('📊 Test 3: Get token balance');
96
+ const tokenBalance = await sdk.token.balanceOf(account.address);
97
+ console.log(` SLVR balance: ${SlvrSDK.formatToken(tokenBalance)}\n`);
98
+
99
+ // Test 4: Get staking info (veNFT staker, keyed by tokenId)
100
+ console.log('📊 Test 4: Get staking info');
101
+ const stakingInfo = await sdk.staking.getStakingInfo(STAKING_TOKEN_ID);
102
+ console.log(` Token ${STAKING_TOKEN_ID} weight: ${SlvrSDK.formatToken(stakingInfo.balance)}`);
103
+ console.log(` Total weight: ${SlvrSDK.formatToken(stakingInfo.totalWeight)}`);
104
+ console.log(` Claimable rewards: ${SlvrSDK.formatToken(stakingInfo.rewards)}\n`);
105
+
106
+ // Test 5: Place a bet (if you have ETH)
107
+ console.log('📊 Test 5: Place a bet');
108
+ const betAmount = parseEther('0.1');
109
+ const squares = [5, 10, 15];
110
+ const amounts = [
111
+ betAmount / 3n,
112
+ betAmount / 3n,
113
+ betAmount / 3n + (betAmount % 3n), // Handle remainder
114
+ ];
115
+
116
+ console.log(` Placing bet on squares ${squares.join(', ')}`);
117
+ console.log(` Total amount: ${SlvrSDK.formatToken(betAmount)} ETH`);
118
+
119
+ // Uncomment to actually place the bet:
120
+ // const txHash = await sdk.lottery.bet({
121
+ // roundId: currentRoundId,
122
+ // squares,
123
+ // amounts,
124
+ // });
125
+ // console.log(` Transaction: ${txHash}`);
126
+ // console.log(' Waiting for confirmation...');
127
+ // await publicClient.waitForTransactionReceipt({ hash: txHash });
128
+ // console.log(' ✅ Bet placed!\n');
129
+
130
+ console.log(' (Skipped - uncomment in code to execute)\n');
131
+
132
+ // Test 6: Emission / registry / jackpot stats (optional bindings)
133
+ console.log('📊 Test 6: Emission / registry / jackpot stats');
134
+ if (sdk.hub) {
135
+ const rate = await sdk.hub.emissionRatePerSec();
136
+ const target = await sdk.hub.targetSupply();
137
+ console.log(` Emission rate/sec: ${SlvrSDK.formatToken(rate)}`);
138
+ console.log(` Target supply: ${SlvrSDK.formatToken(target)}`);
139
+ }
140
+ if (sdk.registry) {
141
+ const gameId = await sdk.registry.gameIdOf(CONTRACT_ADDRESSES.lottery);
142
+ const totalWeight = await sdk.registry.totalActiveWeight();
143
+ console.log(` Lottery gameId: ${gameId}`);
144
+ console.log(` Total active weight: ${totalWeight}`);
145
+ // Combined helper: game's weighted SLVR/sec share (requires hub + registry)
146
+ if (sdk.hub && gameId > 0n) {
147
+ const effRate = await sdk.effectiveEmissionRate(gameId);
148
+ const pending = await sdk.pendingEmission(gameId);
149
+ console.log(` Effective emission rate: ${SlvrSDK.formatToken(effRate)}/sec`);
150
+ console.log(` Pending emission: ${SlvrSDK.formatToken(pending)}`);
151
+ }
152
+ }
153
+ if (sdk.jackpot) {
154
+ const ethPool = await sdk.jackpot.jackpotPool();
155
+ const slvrPool = await sdk.jackpot.jackpotSlvrPool();
156
+ console.log(` Jackpot ETH pool: ${SlvrSDK.formatToken(ethPool)}`);
157
+ console.log(` Jackpot SLVR pool: ${SlvrSDK.formatToken(slvrPool)}`);
158
+ }
159
+ if (!sdk.hub && !sdk.registry && !sdk.jackpot) {
160
+ console.log(' (No hub/registry/jackpot addresses configured - skipped)');
161
+ }
162
+ console.log('');
163
+
164
+ console.log('✅ All tests completed!');
165
+ } catch (error) {
166
+ console.error('❌ Error:', error);
167
+ process.exit(1);
168
+ }
169
+ }
170
+
171
+ main();
172
+
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Quickstart 2 — place a bet with a wallet
3
+ * ========================================
4
+ *
5
+ * The minimal write path: build a wallet-backed SDK, sanity-check the round's
6
+ * expected value, place one small bet, and print how to claim once the round
7
+ * resolves. Bets are paid in native ETH (no token approval needed).
8
+ *
9
+ * Run it (uses a tiny stake by default — start on a testnet / small amount):
10
+ * PRIVATE_KEY=0xabc... npx ts-node quickstart-bet.ts
11
+ *
12
+ * To use this in your own project, change the `../src` import to `@slvr-labs/sdk`.
13
+ */
14
+
15
+ import { createPublicClient, createWalletClient, http, parseEther, formatEther } from 'viem';
16
+ import { privateKeyToAccount } from 'viem/accounts';
17
+ import { SlvrSDK, robinhoodChain, deployments } from '../src';
18
+
19
+ // How much to bet, total, and which squares to spread it across (indices 0–24).
20
+ const STAKE_ETH = '0.002';
21
+ const SQUARES = [0, 12, 24];
22
+
23
+ async function main() {
24
+ const privateKey = process.env.PRIVATE_KEY as `0x${string}` | undefined;
25
+ if (!privateKey) throw new Error('Set PRIVATE_KEY to a funded key on Robinhood Chain');
26
+
27
+ // 1. Wallet-backed SDK from the shipped chain + addresses.
28
+ const account = privateKeyToAccount(privateKey);
29
+ const publicClient = createPublicClient({ chain: robinhoodChain, transport: http() });
30
+ const walletClient = createWalletClient({ chain: robinhoodChain, transport: http(), account });
31
+ const sdk = new SlvrSDK({ publicClient, walletClient, addresses: deployments.robinhood.addresses });
32
+
33
+ console.log(`Account: ${account.address}`);
34
+ const ethBalance = await publicClient.getBalance({ address: account.address });
35
+ console.log(`ETH balance: ${formatEther(ethBalance)}\n`);
36
+
37
+ // 2. Pick the current round and make sure it's open.
38
+ const roundId = await sdk.lottery.currentRoundId();
39
+ if (!(await sdk.lottery.roundOpen(roundId))) {
40
+ console.log(`Round #${roundId} is closed for betting — try again next round.`);
41
+ return;
42
+ }
43
+
44
+ // 3. Optional sanity check: is mining this round +EV right now?
45
+ // (Informational — we bet regardless in this demo.)
46
+ const ev = await sdk.estimateRoundEv({ stake: Number(STAKE_ETH) });
47
+ console.log(
48
+ `Round #${roundId} EV @ ${STAKE_ETH} ETH: ` +
49
+ `${ev.netEth >= 0 ? '+' : ''}${ev.netEth.toFixed(6)} ETH/round ` +
50
+ `(${ev.profitable ? 'profitable' : 'not profitable'}; break-even pot ${ev.breakEvenPot.toFixed(4)} ETH)`
51
+ );
52
+
53
+ // 4. Split the stake evenly across the chosen squares and bet.
54
+ const stakeWei = parseEther(STAKE_ETH);
55
+ const per = stakeWei / BigInt(SQUARES.length);
56
+ const amounts = SQUARES.map((_, i) => (i === 0 ? per + (stakeWei - per * BigInt(SQUARES.length)) : per));
57
+
58
+ console.log(`\nBetting ${STAKE_ETH} ETH on squares ${SQUARES.join(', ')}…`);
59
+ const txHash = await sdk.lottery.bet({ roundId, squares: SQUARES, amounts });
60
+ console.log(`✅ Bet placed: ${txHash}`);
61
+
62
+ // 5. How to collect. Rounds resolve after betting closes; you can only claim a
63
+ // round you won (held the winning square) and haven't claimed yet.
64
+ console.log(`\nTo claim after the round resolves:`);
65
+ console.log(` const canClaim = await sdk.canClaim(${roundId}n, "${account.address}");`);
66
+ console.log(` if (canClaim) await sdk.lottery.claim({ roundId: ${roundId}n });`);
67
+ }
68
+
69
+ main().catch((err) => {
70
+ console.error(err);
71
+ process.exit(1);
72
+ });
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Quickstart 1 — read-only tour (no wallet needed)
3
+ * ================================================
4
+ *
5
+ * The fastest way to confirm the SDK works. It needs nothing but an RPC — no
6
+ * private key — and prints a snapshot of the live game: the current round, the
7
+ * pot, and the SLVR price in both ETH and USD.
8
+ *
9
+ * Run it:
10
+ * npx ts-node quickstart-read.ts
11
+ * npx ts-node quickstart-read.ts 0xYourAddress # also show that address's balance/bets
12
+ *
13
+ * To use this in your own project, change the `../src` import to `@slvr-labs/sdk`.
14
+ */
15
+
16
+ import { createPublicClient, http, formatEther, isAddress, type Address } from 'viem';
17
+ import { SlvrSDK, robinhoodChain, deployments } from '../src';
18
+
19
+ async function main() {
20
+ // 1. A read-only SDK: just a public client + the shipped mainnet addresses.
21
+ // No walletClient means write calls are disabled — reads are all we need here.
22
+ const publicClient = createPublicClient({ chain: robinhoodChain, transport: http() });
23
+ const sdk = new SlvrSDK({
24
+ publicClient,
25
+ addresses: deployments.robinhood.addresses,
26
+ });
27
+
28
+ console.log(`Connected to ${robinhoodChain.name} (chain ${robinhoodChain.id})\n`);
29
+
30
+ // 2. Current round + whether it's still open for betting.
31
+ const roundId = await sdk.lottery.currentRoundId();
32
+ const [isOpen, bettingEnd, squares] = await Promise.all([
33
+ sdk.lottery.roundOpen(roundId),
34
+ sdk.lottery.bettingEnd(roundId),
35
+ sdk.lottery.getRoundSquares(roundId),
36
+ ]);
37
+
38
+ const pot = squares.reduce((sum, s) => sum + s.total, 0n);
39
+ const totalBettors = squares.reduce((sum, s) => sum + s.bettors, 0n);
40
+ const secondsLeft = Number(bettingEnd) - Math.floor(Date.now() / 1000);
41
+
42
+ console.log(`Round #${roundId}`);
43
+ console.log(` status: ${isOpen ? 'OPEN for betting' : 'closed'}`);
44
+ console.log(` betting ends: ${secondsLeft > 0 ? `in ~${secondsLeft}s` : 'passed'}`);
45
+ console.log(` pot: ${formatEther(pot)} ETH across ${squares.length} squares`);
46
+ console.log(` bettors: ${totalBettors}`);
47
+
48
+ // 3. Prices — SLVR in ETH (from the UniswapV2 pair) and USD (via the Chainlink feed).
49
+ const [slvr, ethUsd] = await Promise.all([sdk.getSlvrPrice(), sdk.getEthPriceUsd()]);
50
+ console.log(`\nPrices`);
51
+ console.log(` ETH: $${ethUsd.toFixed(2)}`);
52
+ console.log(
53
+ ` SLVR: ${slvr.eth.toExponential(4)} ETH` +
54
+ (slvr.usd !== null ? ` · $${slvr.usd.toFixed(4)}` : ' · (USD unavailable)')
55
+ );
56
+
57
+ // 4. Token supply, for context.
58
+ const [supply, maxSupply] = await Promise.all([
59
+ sdk.token.totalSupply(),
60
+ sdk.token.maxSupply(),
61
+ ]);
62
+ console.log(`\nSLVR supply: ${formatEther(supply)} / ${formatEther(maxSupply)} max`);
63
+
64
+ // 5. Optional: pass an address to see its SLVR balance and bets this round.
65
+ const who = process.argv[2];
66
+ if (who && isAddress(who)) {
67
+ const addr = who as Address;
68
+ const [bal, bets] = await Promise.all([
69
+ sdk.token.balanceOf(addr),
70
+ sdk.lottery.getUserBets(roundId, addr),
71
+ ]);
72
+ console.log(`\n${addr}`);
73
+ console.log(` SLVR balance: ${formatEther(bal)}`);
74
+ console.log(
75
+ ` bets this round: ${
76
+ bets.length ? bets.map((b) => `#${b.square}=${formatEther(b.amount)}ETH`).join(', ') : 'none'
77
+ }`
78
+ );
79
+ } else if (who) {
80
+ console.log(`\n(ignoring "${who}" — not a valid address)`);
81
+ }
82
+ }
83
+
84
+ main().catch((err) => {
85
+ console.error(err);
86
+ process.exit(1);
87
+ });
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Simple example: Basic usage of the Slvr SDK
3
+ *
4
+ * This is a minimal example showing how to:
5
+ * 1. Initialize the SDK
6
+ * 2. Get current round information
7
+ * 3. Place a simple bet
8
+ *
9
+ * Set PRIVATE_KEY environment variable to use wallet operations
10
+ */
11
+
12
+ import { SlvrSDK } from '../src';
13
+ import { createPublicClient, createWalletClient, http, parseEther } from 'viem';
14
+ import { defineChain } from 'viem';
15
+ import { privateKeyToAccount } from 'viem/accounts';
16
+ import { CONTRACTS, ROBINHOOD_CHAIN } from './constants';
17
+
18
+ /**
19
+ * Simple example function
20
+ */
21
+ export async function simpleExample() {
22
+ // 1. Define the Robinhood chain
23
+ const robinhood = defineChain(ROBINHOOD_CHAIN);
24
+
25
+ // 2. Create public client for read operations
26
+ const publicClient = createPublicClient({
27
+ chain: robinhood,
28
+ transport: http(),
29
+ });
30
+
31
+ // 3. Create wallet client for write operations (if private key is provided)
32
+ let walletClient: ReturnType<typeof createWalletClient> | undefined;
33
+ const privateKey = process.env.PRIVATE_KEY;
34
+
35
+ if (privateKey) {
36
+ const account = privateKeyToAccount(privateKey as `0x${string}`);
37
+ walletClient = createWalletClient({
38
+ chain: robinhood,
39
+ transport: http(),
40
+ account,
41
+ });
42
+ console.log(`Using account: ${account.address}`);
43
+ } else {
44
+ console.log('No PRIVATE_KEY found in environment - wallet operations disabled');
45
+ }
46
+
47
+ // 4. Initialize SDK
48
+ const sdk = new SlvrSDK({
49
+ publicClient,
50
+ walletClient,
51
+ addresses: {
52
+ lottery: CONTRACTS.LOTTERY,
53
+ staking: CONTRACTS.STAKING,
54
+ token: CONTRACTS.TOKEN,
55
+ autoCommit: CONTRACTS.AUTO_COMMIT !== '0x...' ? CONTRACTS.AUTO_COMMIT : undefined,
56
+ },
57
+ });
58
+
59
+ // 4. Get current round
60
+ const roundId = await sdk.lottery.currentRoundId();
61
+ console.log(`Current round: ${roundId}`);
62
+
63
+ // 5. Get round information
64
+ const round = await sdk.lottery.getRound(roundId);
65
+ console.log(`Round ${roundId}:`, {
66
+ resolved: round.resolved,
67
+ totalWager: SlvrSDK.formatToken(round.totalWager),
68
+ winningSquare: round.winningSquare,
69
+ });
70
+
71
+ // 6. Check if round is open
72
+ const isOpen = await sdk.lottery.roundOpen(roundId);
73
+ console.log(`Round ${roundId} is ${isOpen ? 'open' : 'closed'} for betting`);
74
+
75
+ // 7. Get squares data
76
+ const squares = await sdk.lottery.getRoundSquares(roundId);
77
+ console.log(`Square allocations:`, squares.map(sq => ({
78
+ square: sq.square,
79
+ total: SlvrSDK.formatToken(sq.total),
80
+ bettors: Number(sq.bettors),
81
+ })));
82
+
83
+ // 8. Place a bet (requires wallet client)
84
+ if (isOpen && walletClient) {
85
+ const squaresToBet = [0, 1, 2]; // Square indices (0-24)
86
+ const amounts = [
87
+ parseEther('1'), // 1 ETH on square 0
88
+ parseEther('1'), // 1 ETH on square 1
89
+ parseEther('1'), // 1 ETH on square 2
90
+ ];
91
+
92
+ const txHash = await sdk.lottery.bet({
93
+ roundId,
94
+ squares: squaresToBet,
95
+ amounts,
96
+ });
97
+
98
+ console.log(`Bet placed! Transaction: ${txHash}`);
99
+ } else if (isOpen && !walletClient) {
100
+ console.log('Cannot place bet - wallet client not available (set PRIVATE_KEY env var)');
101
+ }
102
+
103
+ // 9. Get user's bets (if wallet client is available)
104
+ if (walletClient?.account) {
105
+ const userAddress = walletClient.account.address;
106
+ const userBets = await sdk.lottery.getUserBets(roundId, userAddress);
107
+ console.log(`Your bets:`, userBets.map(bet => ({
108
+ square: bet.square,
109
+ amount: SlvrSDK.formatToken(bet.amount),
110
+ })));
111
+
112
+ // 10. Check if you can claim
113
+ const canClaim = await sdk.canClaim(roundId, userAddress);
114
+ if (canClaim) {
115
+ console.log(`You can claim rewards for round ${roundId}`);
116
+ // Uncomment to actually claim:
117
+ // const txHash = await sdk.lottery.claim({ roundId });
118
+ // console.log(`Claimed! Transaction: ${txHash}`);
119
+ }
120
+ }
121
+ }
122
+