@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.
- package/LICENSE +21 -0
- package/README.md +849 -0
- package/dist/connect.d.ts +47 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +56 -0
- package/dist/connect.js.map +1 -0
- package/dist/contracts/autoCommit.d.ts +151 -0
- package/dist/contracts/autoCommit.d.ts.map +1 -0
- package/dist/contracts/autoCommit.js +426 -0
- package/dist/contracts/autoCommit.js.map +1 -0
- package/dist/contracts/hub.d.ts +50 -0
- package/dist/contracts/hub.d.ts.map +1 -0
- package/dist/contracts/hub.js +118 -0
- package/dist/contracts/hub.js.map +1 -0
- package/dist/contracts/index.d.ts +8 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +18 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/jackpot.d.ts +21 -0
- package/dist/contracts/jackpot.d.ts.map +1 -0
- package/dist/contracts/jackpot.js +44 -0
- package/dist/contracts/jackpot.js.map +1 -0
- package/dist/contracts/lottery.d.ts +256 -0
- package/dist/contracts/lottery.d.ts.map +1 -0
- package/dist/contracts/lottery.js +767 -0
- package/dist/contracts/lottery.js.map +1 -0
- package/dist/contracts/registry.d.ts +53 -0
- package/dist/contracts/registry.d.ts.map +1 -0
- package/dist/contracts/registry.js +143 -0
- package/dist/contracts/registry.js.map +1 -0
- package/dist/contracts/staking.d.ts +101 -0
- package/dist/contracts/staking.d.ts.map +1 -0
- package/dist/contracts/staking.js +306 -0
- package/dist/contracts/staking.js.map +1 -0
- package/dist/contracts/token.d.ts +95 -0
- package/dist/contracts/token.d.ts.map +1 -0
- package/dist/contracts/token.js +273 -0
- package/dist/contracts/token.js.map +1 -0
- package/dist/deployments.d.ts +117 -0
- package/dist/deployments.d.ts.map +1 -0
- package/dist/deployments.js +74 -0
- package/dist/deployments.js.map +1 -0
- package/dist/errors.d.ts +39 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +67 -0
- package/dist/errors.js.map +1 -0
- package/dist/ev.d.ts +123 -0
- package/dist/ev.d.ts.map +1 -0
- package/dist/ev.js +111 -0
- package/dist/ev.js.map +1 -0
- package/dist/events.d.ts +418 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +87 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +248 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +436 -0
- package/dist/index.js.map +1 -0
- package/dist/oracle.d.ts +48 -0
- package/dist/oracle.d.ts.map +1 -0
- package/dist/oracle.js +77 -0
- package/dist/oracle.js.map +1 -0
- package/dist/price.d.ts +52 -0
- package/dist/price.d.ts.map +1 -0
- package/dist/price.js +78 -0
- package/dist/price.js.map +1 -0
- package/dist/transaction.d.ts +54 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +105 -0
- package/dist/transaction.js.map +1 -0
- package/dist/types.d.ts +162 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +58 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +110 -0
- package/dist/utils.js.map +1 -0
- package/examples/.env.example +22 -0
- package/examples/README.md +417 -0
- package/examples/automated-betting.ts +232 -0
- package/examples/combined-strategy.ts +227 -0
- package/examples/constants.ts +35 -0
- package/examples/custom-strategy-example.ts +231 -0
- package/examples/expected-value-strategy.ts +255 -0
- package/examples/fixed-squares-strategy.ts +176 -0
- package/examples/index.ts +30 -0
- package/examples/least-allocated-strategy.ts +224 -0
- package/examples/local-test.ts +172 -0
- package/examples/quickstart-bet.ts +72 -0
- package/examples/quickstart-read.ts +87 -0
- package/examples/simple-example.ts +122 -0
- package/examples/strategy-base.ts +283 -0
- package/package.json +71 -0
- package/skills/slvr-bot/SKILL.md +193 -0
- package/skills/slvr-bot/references/api.md +117 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.SlvrJackpot = exports.SlvrGameRegistry = exports.SlvrHub = exports.SlvrAutoCommit = exports.SlvrToken = exports.SlvrStaking = exports.SlvrGridLottery = exports.chainFromDeployment = exports.createSlvrClients = exports.ChainlinkPriceFeed = exports.SlvrPrice = exports.SlvrSDK = void 0;
|
|
18
|
+
const viem_1 = require("viem");
|
|
19
|
+
const lottery_1 = require("./contracts/lottery");
|
|
20
|
+
const staking_1 = require("./contracts/staking");
|
|
21
|
+
const token_1 = require("./contracts/token");
|
|
22
|
+
const autoCommit_1 = require("./contracts/autoCommit");
|
|
23
|
+
const hub_1 = require("./contracts/hub");
|
|
24
|
+
const registry_1 = require("./contracts/registry");
|
|
25
|
+
const jackpot_1 = require("./contracts/jackpot");
|
|
26
|
+
const price_1 = require("./price");
|
|
27
|
+
const oracle_1 = require("./oracle");
|
|
28
|
+
const ev_1 = require("./ev");
|
|
29
|
+
const connect_1 = require("./connect");
|
|
30
|
+
const deployments_1 = require("./deployments");
|
|
31
|
+
const errors_1 = require("./errors");
|
|
32
|
+
/**
|
|
33
|
+
* Main Slvr SDK class
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { createPublicClient, createWalletClient, http } from 'viem';
|
|
38
|
+
* import { SlvrSDK } from '@slvr-labs/sdk';
|
|
39
|
+
*
|
|
40
|
+
* const publicClient = createPublicClient({
|
|
41
|
+
* chain: robinhoodChain,
|
|
42
|
+
* transport: http(),
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* const walletClient = createWalletClient({
|
|
46
|
+
* chain: robinhoodChain,
|
|
47
|
+
* transport: http(),
|
|
48
|
+
* account: yourAccount,
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* const sdk = new SlvrSDK({
|
|
52
|
+
* publicClient,
|
|
53
|
+
* walletClient,
|
|
54
|
+
* addresses: {
|
|
55
|
+
* lottery: '0x...',
|
|
56
|
+
* staking: '0x...',
|
|
57
|
+
* token: '0x...',
|
|
58
|
+
* },
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* // Get current round
|
|
62
|
+
* const roundId = await sdk.lottery.currentRoundId();
|
|
63
|
+
*
|
|
64
|
+
* // Place a bet
|
|
65
|
+
* await sdk.lottery.bet({
|
|
66
|
+
* roundId,
|
|
67
|
+
* squares: [0, 1, 2],
|
|
68
|
+
* amounts: [1000000000000000000n, 2000000000000000000n, 3000000000000000000n],
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
class SlvrSDK {
|
|
73
|
+
constructor(config) {
|
|
74
|
+
this.config = config;
|
|
75
|
+
// Initialize core contracts
|
|
76
|
+
this.lottery = new lottery_1.SlvrGridLottery(config.publicClient, config.walletClient, config.addresses.lottery);
|
|
77
|
+
this.staking = new staking_1.SlvrStaking(config.publicClient, config.walletClient, config.addresses.staking);
|
|
78
|
+
this.token = new token_1.SlvrToken(config.publicClient, config.walletClient, config.addresses.token);
|
|
79
|
+
// Initialize optional contracts
|
|
80
|
+
if (config.addresses.autoCommit) {
|
|
81
|
+
this.autoCommit = new autoCommit_1.SlvrAutoCommit(config.publicClient, config.walletClient, config.addresses.autoCommit);
|
|
82
|
+
}
|
|
83
|
+
if (config.addresses.hub) {
|
|
84
|
+
this.hub = new hub_1.SlvrHub(config.publicClient, config.walletClient, config.addresses.hub);
|
|
85
|
+
}
|
|
86
|
+
if (config.addresses.registry) {
|
|
87
|
+
this.registry = new registry_1.SlvrGameRegistry(config.publicClient, config.walletClient, config.addresses.registry);
|
|
88
|
+
}
|
|
89
|
+
if (config.addresses.jackpot) {
|
|
90
|
+
this.jackpot = new jackpot_1.SlvrJackpot(config.publicClient, config.walletClient, config.addresses.jackpot);
|
|
91
|
+
}
|
|
92
|
+
// Price reader needs the pair address; SLVR side is resolved from the token address.
|
|
93
|
+
if (config.addresses.slvrEthPair) {
|
|
94
|
+
this.price = new price_1.SlvrPrice(config.publicClient, config.addresses.slvrEthPair, config.addresses.token);
|
|
95
|
+
}
|
|
96
|
+
// ETH/USD feed (optional; only on chains that have a Chainlink aggregator).
|
|
97
|
+
if (config.addresses.chainlinkEthUsd) {
|
|
98
|
+
this.ethUsd = new oracle_1.ChainlinkPriceFeed(config.publicClient, config.addresses.chainlinkEthUsd);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* One-line setup: build clients (with Multicall3 batching + resilient transport
|
|
103
|
+
* defaults) and an SDK for a deployment. Pass a `privateKey`/`account` to enable
|
|
104
|
+
* writes; omit it for a read-only SDK.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* import { SlvrSDK } from '@slvr-labs/sdk';
|
|
109
|
+
* const sdk = SlvrSDK.connect(); // read-only, Robinhood Chain
|
|
110
|
+
* const bot = SlvrSDK.connect({ privateKey: process.env.PK }); // wallet-backed
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
static connect(opts = {}) {
|
|
114
|
+
const deployment = opts.deployment ?? deployments_1.robinhood;
|
|
115
|
+
const { publicClient, walletClient } = (0, connect_1.createSlvrClients)(opts);
|
|
116
|
+
return new SlvrSDK({ publicClient, walletClient, addresses: deployment.addresses });
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get the public client
|
|
120
|
+
*/
|
|
121
|
+
getPublicClient() {
|
|
122
|
+
return this.config.publicClient;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the wallet client (if available)
|
|
126
|
+
*/
|
|
127
|
+
getWalletClient() {
|
|
128
|
+
return this.config.walletClient;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Update the wallet client and reinitialize contracts
|
|
132
|
+
* @param walletClient New wallet client (or undefined to remove)
|
|
133
|
+
*/
|
|
134
|
+
setWalletClient(walletClient) {
|
|
135
|
+
this.config.walletClient = walletClient;
|
|
136
|
+
// Reinitialize contracts with new wallet client
|
|
137
|
+
this.lottery.setWalletClient(walletClient);
|
|
138
|
+
this.staking.setWalletClient(walletClient);
|
|
139
|
+
this.token.setWalletClient(walletClient);
|
|
140
|
+
if (this.autoCommit) {
|
|
141
|
+
this.autoCommit.setWalletClient(walletClient);
|
|
142
|
+
}
|
|
143
|
+
if (this.hub) {
|
|
144
|
+
this.hub.setWalletClient(walletClient);
|
|
145
|
+
}
|
|
146
|
+
if (this.registry) {
|
|
147
|
+
this.registry.setWalletClient(walletClient);
|
|
148
|
+
}
|
|
149
|
+
if (this.jackpot) {
|
|
150
|
+
this.jackpot.setWalletClient(walletClient);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Helper: Calculate bet amounts from percentages
|
|
155
|
+
* @param totalAmount Total amount to bet
|
|
156
|
+
* @param percentages Array of percentages (0-100) for each square
|
|
157
|
+
* @returns Array of amounts in wei
|
|
158
|
+
* @throws ValidationError if percentages don't sum to 100 or if totalAmount is invalid
|
|
159
|
+
*/
|
|
160
|
+
static calculateBetAmounts(totalAmount, percentages) {
|
|
161
|
+
if (percentages.length === 0) {
|
|
162
|
+
throw new errors_1.ValidationError('Percentages array cannot be empty', 'percentages');
|
|
163
|
+
}
|
|
164
|
+
const totalPercent = percentages.reduce((sum, p) => sum + p, 0);
|
|
165
|
+
if (Math.abs(totalPercent - 100) > 0.01) {
|
|
166
|
+
throw new errors_1.ValidationError(`Percentages must sum to 100 (got ${totalPercent})`, 'percentages');
|
|
167
|
+
}
|
|
168
|
+
const amounts = [];
|
|
169
|
+
let allocated = 0n;
|
|
170
|
+
for (let i = 0; i < percentages.length; i++) {
|
|
171
|
+
const percentage = percentages[i];
|
|
172
|
+
if (percentage === undefined)
|
|
173
|
+
continue;
|
|
174
|
+
const amount = (totalAmount * BigInt(Math.round(percentage * 100))) / 10000n;
|
|
175
|
+
amounts.push(amount);
|
|
176
|
+
allocated += amount;
|
|
177
|
+
}
|
|
178
|
+
// Adjust first amount to account for rounding
|
|
179
|
+
if (allocated !== totalAmount && amounts.length > 0 && amounts[0] !== undefined) {
|
|
180
|
+
amounts[0] += totalAmount - allocated;
|
|
181
|
+
}
|
|
182
|
+
return amounts;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Helper: Format bigint to human-readable string.
|
|
186
|
+
*
|
|
187
|
+
* `precision` caps the number of decimal places shown; trailing zeros are
|
|
188
|
+
* stripped (like viem's `formatEther`), so `formatToken(1.5e18)` is `"1.5"`,
|
|
189
|
+
* not `"1.5000"`.
|
|
190
|
+
* @param value Value in wei
|
|
191
|
+
* @param decimals Number of decimals (default 18)
|
|
192
|
+
* @param precision Max decimal places to show (default 4)
|
|
193
|
+
*/
|
|
194
|
+
static formatToken(value, decimals = 18, precision = 4) {
|
|
195
|
+
const divisor = BigInt(10 ** decimals);
|
|
196
|
+
const whole = value / divisor;
|
|
197
|
+
const remainder = value % divisor;
|
|
198
|
+
const fractional = (remainder * BigInt(10 ** precision)) / divisor;
|
|
199
|
+
if (fractional === 0n) {
|
|
200
|
+
return whole.toString();
|
|
201
|
+
}
|
|
202
|
+
const fractionalStr = fractional.toString().padStart(precision, '0').replace(/0+$/, '');
|
|
203
|
+
return fractionalStr ? `${whole}.${fractionalStr}` : whole.toString();
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Helper: Parse human-readable string to bigint
|
|
207
|
+
* @param value Human-readable value (e.g., "1.5")
|
|
208
|
+
* @param decimals Number of decimals (default 18)
|
|
209
|
+
*/
|
|
210
|
+
static parseToken(value, decimals = 18) {
|
|
211
|
+
const parts = value.split('.');
|
|
212
|
+
const whole = BigInt(parts[0] || '0');
|
|
213
|
+
const fractional = parts[1] ? BigInt(parts[1].padEnd(decimals, '0').slice(0, decimals)) : 0n;
|
|
214
|
+
return whole * BigInt(10 ** decimals) + fractional;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Helper: Calculate time remaining until round ends
|
|
218
|
+
* @param roundId Round ID
|
|
219
|
+
* @returns Time remaining in seconds, or 0 if round has ended
|
|
220
|
+
*/
|
|
221
|
+
async getTimeRemaining(roundId) {
|
|
222
|
+
const roundEnd = await this.lottery.roundEnd(roundId);
|
|
223
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
224
|
+
const remaining = roundEnd - now;
|
|
225
|
+
return remaining > 0n ? Number(remaining) : 0;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Helper: Check if user can claim rewards for a round
|
|
229
|
+
* @param roundId Round ID
|
|
230
|
+
* @param user User address
|
|
231
|
+
* @returns True if user can claim
|
|
232
|
+
*/
|
|
233
|
+
async canClaim(roundId, user) {
|
|
234
|
+
const [round, hasClaimed_] = await Promise.all([
|
|
235
|
+
this.lottery.getRound(roundId),
|
|
236
|
+
this.lottery.getHasClaimed(roundId, user),
|
|
237
|
+
]);
|
|
238
|
+
if (!round.resolved || hasClaimed_) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
// Check if user has a bet on the winning square
|
|
242
|
+
const userBet = await this.lottery.getUserBet(roundId, round.winningSquare, user);
|
|
243
|
+
return userBet > 0n;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Helper: Get user's claimable rounds
|
|
247
|
+
* @param user User address
|
|
248
|
+
* @param startRoundId Start round ID to check from
|
|
249
|
+
* @param endRoundId End round ID to check to
|
|
250
|
+
* @returns Array of round IDs that can be claimed
|
|
251
|
+
*/
|
|
252
|
+
async getClaimableRounds(user, startRoundId, endRoundId) {
|
|
253
|
+
const claimable = [];
|
|
254
|
+
for (let roundId = startRoundId; roundId <= endRoundId; roundId++) {
|
|
255
|
+
if (await this.canClaim(roundId, user)) {
|
|
256
|
+
claimable.push(roundId);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return claimable;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Helper: Compute a game's effective SLVR/sec emission rate.
|
|
263
|
+
*
|
|
264
|
+
* Mirrors SlvrHub._effectiveRatePerSec: the game's weighted share of the global emission stream,
|
|
265
|
+
* i.e. emissionRatePerSec * weightOf(gameId) / totalActiveWeight. NOTE: this does not apply the
|
|
266
|
+
* per-game maxWeightBps ceiling that the contract also enforces; it is the pre-cap weighted rate.
|
|
267
|
+
*
|
|
268
|
+
* Requires both `hub` and `registry` addresses to be configured.
|
|
269
|
+
* @param gameId Registry game id
|
|
270
|
+
* @returns Effective emission rate in SLVR/sec (0 if there is no active weight)
|
|
271
|
+
*/
|
|
272
|
+
async effectiveEmissionRate(gameId) {
|
|
273
|
+
if (!this.hub) {
|
|
274
|
+
throw new errors_1.ValidationError('hub address is required for effectiveEmissionRate', 'hub');
|
|
275
|
+
}
|
|
276
|
+
if (!this.registry) {
|
|
277
|
+
throw new errors_1.ValidationError('registry address is required for effectiveEmissionRate', 'registry');
|
|
278
|
+
}
|
|
279
|
+
const [rate, weight, totalWeight] = await Promise.all([
|
|
280
|
+
this.hub.emissionRatePerSec(),
|
|
281
|
+
this.registry.weightOf(gameId),
|
|
282
|
+
this.registry.totalActiveWeight(),
|
|
283
|
+
]);
|
|
284
|
+
if (totalWeight === 0n) {
|
|
285
|
+
return 0n;
|
|
286
|
+
}
|
|
287
|
+
return (rate * weight) / totalWeight;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Helper: Get the accrued-but-unminted SLVR emission currently available to a game.
|
|
291
|
+
*
|
|
292
|
+
* Thin pass-through to SlvrHub.pendingEmission. Requires `hub` to be configured.
|
|
293
|
+
* @param gameId Registry game id
|
|
294
|
+
*/
|
|
295
|
+
async pendingEmission(gameId) {
|
|
296
|
+
if (!this.hub) {
|
|
297
|
+
throw new errors_1.ValidationError('hub address is required for pendingEmission', 'hub');
|
|
298
|
+
}
|
|
299
|
+
return await this.hub.pendingEmission(gameId);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Helper: current SLVR spot price in ETH (ETH per SLVR).
|
|
303
|
+
*
|
|
304
|
+
* Requires a `slvrEthPair` address to be configured (so `sdk.price` exists).
|
|
305
|
+
* @throws ValidationError if no pair address was configured.
|
|
306
|
+
*/
|
|
307
|
+
async getSlvrPriceInEth() {
|
|
308
|
+
if (!this.price) {
|
|
309
|
+
throw new errors_1.ValidationError('slvrEthPair address is required for getSlvrPriceInEth', 'slvrEthPair');
|
|
310
|
+
}
|
|
311
|
+
return await this.price.getPriceInEth();
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Helper: current ETH price in USD from the configured Chainlink feed.
|
|
315
|
+
*
|
|
316
|
+
* Requires a `chainlinkEthUsd` address (so `sdk.ethUsd` exists). This is wired
|
|
317
|
+
* for Robinhood Chain in `deployments.robinhood`; on chains without a feed,
|
|
318
|
+
* supply one or pass `ethUsd` to {@link getSlvrPrice}.
|
|
319
|
+
* @throws ValidationError if no ETH/USD feed was configured.
|
|
320
|
+
*/
|
|
321
|
+
async getEthPriceUsd() {
|
|
322
|
+
if (!this.ethUsd) {
|
|
323
|
+
throw new errors_1.ValidationError('chainlinkEthUsd address is required for getEthPriceUsd', 'chainlinkEthUsd');
|
|
324
|
+
}
|
|
325
|
+
return await this.ethUsd.getPrice();
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Helper: current SLVR price in **both ETH and USD**.
|
|
329
|
+
*
|
|
330
|
+
* SLVR/ETH comes from the UniswapV2 pair (`sdk.price`). The USD value uses, in
|
|
331
|
+
* order: an explicit `opts.ethUsd`, else the configured Chainlink ETH/USD feed
|
|
332
|
+
* (`sdk.ethUsd`), else `usd` is `null`.
|
|
333
|
+
*
|
|
334
|
+
* @param opts.ethUsd override the ETH/USD price (e.g. from your own off-chain source)
|
|
335
|
+
* @throws ValidationError if no `slvrEthPair` was configured.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* const { eth, usd } = await sdk.getSlvrPrice(); // uses Chainlink feed if configured
|
|
340
|
+
* const q = await sdk.getSlvrPrice({ ethUsd: 1797.35 }); // or supply ETH/USD yourself
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
async getSlvrPrice(opts) {
|
|
344
|
+
if (!this.price) {
|
|
345
|
+
throw new errors_1.ValidationError('slvrEthPair address is required for getSlvrPrice', 'slvrEthPair');
|
|
346
|
+
}
|
|
347
|
+
const eth = await this.price.getPriceInEth();
|
|
348
|
+
let ethUsd = opts?.ethUsd;
|
|
349
|
+
if (ethUsd === undefined && this.ethUsd) {
|
|
350
|
+
ethUsd = await this.ethUsd.getPrice();
|
|
351
|
+
}
|
|
352
|
+
return { eth, usd: ethUsd !== undefined ? eth * ethUsd : null };
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Helper: estimate the per-round expected value of grid mining for the given
|
|
356
|
+
* stake, pulling live pot, emission and SLVR price on-chain.
|
|
357
|
+
*
|
|
358
|
+
* This is the SDK-level convenience around {@link computeGridMiningEv}: it reads
|
|
359
|
+
* the round's pot (sum of all squares), the emission target (`slvrPerRound`), the
|
|
360
|
+
* protocol fee (`protocolFeeBps`), and the SLVR price (via `sdk.price`), then
|
|
361
|
+
* returns the full EV breakdown. Any of those can be overridden via `params`.
|
|
362
|
+
*
|
|
363
|
+
* The jackpot pool is **not** auto-read (it isn't exposed as a single call on the
|
|
364
|
+
* live lottery) — pass `jackpotPool` if you want the jackpot term included.
|
|
365
|
+
*
|
|
366
|
+
* @remarks `slvrPerRound` is the emission *target*; actual emission is hub-gated
|
|
367
|
+
* and may be lower, so treat the result as an upper-ish estimate. Requires a
|
|
368
|
+
* configured `slvrEthPair` unless you pass `slvrPriceEth`.
|
|
369
|
+
*/
|
|
370
|
+
async estimateRoundEv(params) {
|
|
371
|
+
const roundId = params.roundId ?? (await this.lottery.currentRoundId());
|
|
372
|
+
const [potEth, emissionPerRound, slvrPriceEth, feeBps] = await Promise.all([
|
|
373
|
+
params.pot !== undefined
|
|
374
|
+
? Promise.resolve(params.pot)
|
|
375
|
+
: this.lottery
|
|
376
|
+
.getRoundSquares(roundId)
|
|
377
|
+
.then((sqs) => Number((0, viem_1.formatEther)(sqs.reduce((sum, s) => sum + s.total, 0n)))),
|
|
378
|
+
params.emissionPerRound !== undefined
|
|
379
|
+
? Promise.resolve(params.emissionPerRound)
|
|
380
|
+
: this.lottery.slvrPerRound().then((v) => Number((0, viem_1.formatEther)(v))),
|
|
381
|
+
params.slvrPriceEth !== undefined
|
|
382
|
+
? Promise.resolve(params.slvrPriceEth)
|
|
383
|
+
: this.getSlvrPriceInEth(),
|
|
384
|
+
this.lottery.protocolFeeBps(),
|
|
385
|
+
]);
|
|
386
|
+
return (0, ev_1.computeGridMiningEv)({
|
|
387
|
+
stake: params.stake,
|
|
388
|
+
pot: potEth,
|
|
389
|
+
emissionPerRound,
|
|
390
|
+
slvrPriceEth,
|
|
391
|
+
feeBps,
|
|
392
|
+
cashOut: params.cashOut,
|
|
393
|
+
jackpotPool: params.jackpotPool,
|
|
394
|
+
jackpotOdds: params.jackpotOdds,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
exports.SlvrSDK = SlvrSDK;
|
|
399
|
+
// Export all types
|
|
400
|
+
__exportStar(require("./types"), exports);
|
|
401
|
+
// Export known deployments + ready-made viem chain
|
|
402
|
+
__exportStar(require("./deployments"), exports);
|
|
403
|
+
// Export expected-value math + SLVR price reader
|
|
404
|
+
__exportStar(require("./ev"), exports);
|
|
405
|
+
var price_2 = require("./price");
|
|
406
|
+
Object.defineProperty(exports, "SlvrPrice", { enumerable: true, get: function () { return price_2.SlvrPrice; } });
|
|
407
|
+
var oracle_2 = require("./oracle");
|
|
408
|
+
Object.defineProperty(exports, "ChainlinkPriceFeed", { enumerable: true, get: function () { return oracle_2.ChainlinkPriceFeed; } });
|
|
409
|
+
// Export client factory
|
|
410
|
+
var connect_2 = require("./connect");
|
|
411
|
+
Object.defineProperty(exports, "createSlvrClients", { enumerable: true, get: function () { return connect_2.createSlvrClients; } });
|
|
412
|
+
Object.defineProperty(exports, "chainFromDeployment", { enumerable: true, get: function () { return connect_2.chainFromDeployment; } });
|
|
413
|
+
// Export contract classes
|
|
414
|
+
var lottery_2 = require("./contracts/lottery");
|
|
415
|
+
Object.defineProperty(exports, "SlvrGridLottery", { enumerable: true, get: function () { return lottery_2.SlvrGridLottery; } });
|
|
416
|
+
var staking_2 = require("./contracts/staking");
|
|
417
|
+
Object.defineProperty(exports, "SlvrStaking", { enumerable: true, get: function () { return staking_2.SlvrStaking; } });
|
|
418
|
+
var token_2 = require("./contracts/token");
|
|
419
|
+
Object.defineProperty(exports, "SlvrToken", { enumerable: true, get: function () { return token_2.SlvrToken; } });
|
|
420
|
+
var autoCommit_2 = require("./contracts/autoCommit");
|
|
421
|
+
Object.defineProperty(exports, "SlvrAutoCommit", { enumerable: true, get: function () { return autoCommit_2.SlvrAutoCommit; } });
|
|
422
|
+
var hub_2 = require("./contracts/hub");
|
|
423
|
+
Object.defineProperty(exports, "SlvrHub", { enumerable: true, get: function () { return hub_2.SlvrHub; } });
|
|
424
|
+
var registry_2 = require("./contracts/registry");
|
|
425
|
+
Object.defineProperty(exports, "SlvrGameRegistry", { enumerable: true, get: function () { return registry_2.SlvrGameRegistry; } });
|
|
426
|
+
var jackpot_2 = require("./contracts/jackpot");
|
|
427
|
+
Object.defineProperty(exports, "SlvrJackpot", { enumerable: true, get: function () { return jackpot_2.SlvrJackpot; } });
|
|
428
|
+
// Export errors
|
|
429
|
+
__exportStar(require("./errors"), exports);
|
|
430
|
+
// Export utilities
|
|
431
|
+
__exportStar(require("./utils"), exports);
|
|
432
|
+
// Export transaction helpers
|
|
433
|
+
__exportStar(require("./transaction"), exports);
|
|
434
|
+
// Export event utilities
|
|
435
|
+
__exportStar(require("./events"), exports);
|
|
436
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/oracle.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Address, PublicClient } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Reads a Chainlink-style price feed (`AggregatorV3Interface`).
|
|
4
|
+
*
|
|
5
|
+
* Works with any standard aggregator — the canonical use here is an **ETH/USD**
|
|
6
|
+
* feed, which lets the SDK convert the pair-derived SLVR/ETH price into USD.
|
|
7
|
+
*
|
|
8
|
+
* Robinhood Chain has a Chainlink ETH/USD feed (`ETH / USD`, 8 decimals), wired
|
|
9
|
+
* into `deployments.robinhood.addresses.chainlinkEthUsd`, so `sdk.ethUsd` and USD
|
|
10
|
+
* prices work out of the box there. On chains without a feed, pass a USD price
|
|
11
|
+
* into {@link SlvrSDK.getSlvrPrice} instead, or wire your own off-chain source.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { ChainlinkPriceFeed } from '@slvr-labs/sdk';
|
|
16
|
+
* const ethUsd = new ChainlinkPriceFeed(publicClient, ethUsdFeedAddress);
|
|
17
|
+
* const price = await ethUsd.getPrice(); // e.g. 1797.35
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class ChainlinkPriceFeed {
|
|
21
|
+
private publicClient;
|
|
22
|
+
private feedAddress;
|
|
23
|
+
private maxStalenessSec?;
|
|
24
|
+
private static readonly ABI;
|
|
25
|
+
/**
|
|
26
|
+
* @param publicClient viem public client
|
|
27
|
+
* @param feedAddress the aggregator address
|
|
28
|
+
* @param opts.maxStalenessSec if set, {@link getPrice} throws when the feed's
|
|
29
|
+
* `updatedAt` is older than this many seconds (checked against the local
|
|
30
|
+
* clock). Off by default — enable it only where the local clock is trusted.
|
|
31
|
+
*/
|
|
32
|
+
constructor(publicClient: PublicClient, feedAddress: Address, opts?: {
|
|
33
|
+
maxStalenessSec?: number;
|
|
34
|
+
});
|
|
35
|
+
/** Raw `latestRoundData` answer plus the feed's decimals. */
|
|
36
|
+
getRoundData(): Promise<{
|
|
37
|
+
answer: bigint;
|
|
38
|
+
decimals: number;
|
|
39
|
+
updatedAt: bigint;
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* The feed price as a floating-point number (`answer / 10 ** decimals`).
|
|
43
|
+
* @throws {Error} if the answer is non-positive, or (when `maxStalenessSec` is
|
|
44
|
+
* set) if the feed is stale.
|
|
45
|
+
*/
|
|
46
|
+
getPrice(): Promise<number>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=oracle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oracle.d.ts","sourceRoot":"","sources":["../src/oracle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAY,MAAM,MAAM,CAAC;AAEvD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,eAAe,CAAC,CAAS;IAEjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAGxB;IAEH;;;;;;OAMG;gBAED,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,OAAO,EACpB,IAAI,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE;IAOrC,6DAA6D;IACvD,YAAY,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAgBtF;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;CAgBlC"}
|
package/dist/oracle.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChainlinkPriceFeed = void 0;
|
|
4
|
+
const viem_1 = require("viem");
|
|
5
|
+
/**
|
|
6
|
+
* Reads a Chainlink-style price feed (`AggregatorV3Interface`).
|
|
7
|
+
*
|
|
8
|
+
* Works with any standard aggregator — the canonical use here is an **ETH/USD**
|
|
9
|
+
* feed, which lets the SDK convert the pair-derived SLVR/ETH price into USD.
|
|
10
|
+
*
|
|
11
|
+
* Robinhood Chain has a Chainlink ETH/USD feed (`ETH / USD`, 8 decimals), wired
|
|
12
|
+
* into `deployments.robinhood.addresses.chainlinkEthUsd`, so `sdk.ethUsd` and USD
|
|
13
|
+
* prices work out of the box there. On chains without a feed, pass a USD price
|
|
14
|
+
* into {@link SlvrSDK.getSlvrPrice} instead, or wire your own off-chain source.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { ChainlinkPriceFeed } from '@slvr-labs/sdk';
|
|
19
|
+
* const ethUsd = new ChainlinkPriceFeed(publicClient, ethUsdFeedAddress);
|
|
20
|
+
* const price = await ethUsd.getPrice(); // e.g. 1797.35
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
class ChainlinkPriceFeed {
|
|
24
|
+
/**
|
|
25
|
+
* @param publicClient viem public client
|
|
26
|
+
* @param feedAddress the aggregator address
|
|
27
|
+
* @param opts.maxStalenessSec if set, {@link getPrice} throws when the feed's
|
|
28
|
+
* `updatedAt` is older than this many seconds (checked against the local
|
|
29
|
+
* clock). Off by default — enable it only where the local clock is trusted.
|
|
30
|
+
*/
|
|
31
|
+
constructor(publicClient, feedAddress, opts) {
|
|
32
|
+
this.publicClient = publicClient;
|
|
33
|
+
this.feedAddress = feedAddress;
|
|
34
|
+
this.maxStalenessSec = opts?.maxStalenessSec;
|
|
35
|
+
}
|
|
36
|
+
/** Raw `latestRoundData` answer plus the feed's decimals. */
|
|
37
|
+
async getRoundData() {
|
|
38
|
+
const [decimals, roundData] = await Promise.all([
|
|
39
|
+
this.publicClient.readContract({
|
|
40
|
+
address: this.feedAddress,
|
|
41
|
+
abi: ChainlinkPriceFeed.ABI,
|
|
42
|
+
functionName: 'decimals',
|
|
43
|
+
}),
|
|
44
|
+
this.publicClient.readContract({
|
|
45
|
+
address: this.feedAddress,
|
|
46
|
+
abi: ChainlinkPriceFeed.ABI,
|
|
47
|
+
functionName: 'latestRoundData',
|
|
48
|
+
}),
|
|
49
|
+
]);
|
|
50
|
+
return { answer: roundData[1], decimals, updatedAt: roundData[3] };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The feed price as a floating-point number (`answer / 10 ** decimals`).
|
|
54
|
+
* @throws {Error} if the answer is non-positive, or (when `maxStalenessSec` is
|
|
55
|
+
* set) if the feed is stale.
|
|
56
|
+
*/
|
|
57
|
+
async getPrice() {
|
|
58
|
+
const { answer, decimals, updatedAt } = await this.getRoundData();
|
|
59
|
+
if (answer <= 0n) {
|
|
60
|
+
throw new Error(`Chainlink feed ${this.feedAddress} returned a non-positive answer`);
|
|
61
|
+
}
|
|
62
|
+
if (this.maxStalenessSec !== undefined) {
|
|
63
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
64
|
+
const age = nowSec - Number(updatedAt);
|
|
65
|
+
if (age > this.maxStalenessSec) {
|
|
66
|
+
throw new Error(`Chainlink feed ${this.feedAddress} is stale: ${age}s old (max ${this.maxStalenessSec}s)`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return Number(answer) / 10 ** decimals;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.ChainlinkPriceFeed = ChainlinkPriceFeed;
|
|
73
|
+
ChainlinkPriceFeed.ABI = (0, viem_1.parseAbi)([
|
|
74
|
+
'function decimals() view returns (uint8)',
|
|
75
|
+
'function latestRoundData() view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)',
|
|
76
|
+
]);
|
|
77
|
+
//# sourceMappingURL=oracle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oracle.js","sourceRoot":"","sources":["../src/oracle.ts"],"names":[],"mappings":";;;AAAA,+BAAuD;AAEvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,kBAAkB;IAU7B;;;;;;OAMG;IACH,YACE,YAA0B,EAC1B,WAAoB,EACpB,IAAmC;QAEnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,IAAI,EAAE,eAAe,CAAC;IAC/C,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,YAAY;QAChB,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC9C,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC7B,OAAO,EAAE,IAAI,CAAC,WAAW;gBACzB,GAAG,EAAE,kBAAkB,CAAC,GAAG;gBAC3B,YAAY,EAAE,UAAU;aACzB,CAAoB;YACrB,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC7B,OAAO,EAAE,IAAI,CAAC,WAAW;gBACzB,GAAG,EAAE,kBAAkB,CAAC,GAAG;gBAC3B,YAAY,EAAE,iBAAiB;aAChC,CAA+D;SACjE,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAClE,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,WAAW,iCAAiC,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAC7C,MAAM,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,GAAG,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACb,kBAAkB,IAAI,CAAC,WAAW,cAAc,GAAG,cAAc,IAAI,CAAC,eAAe,IAAI,CAC1F,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAC;IACzC,CAAC;;AAhEH,gDAiEC;AA5DyB,sBAAG,GAAG,IAAA,eAAQ,EAAC;IACrC,0CAA0C;IAC1C,uIAAuI;CACxI,CAAC,CAAC"}
|
package/dist/price.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Address, PublicClient } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Reserves of the SLVR/ETH UniswapV2 pair, with the token ordering resolved.
|
|
4
|
+
*/
|
|
5
|
+
export interface SlvrReserves {
|
|
6
|
+
/** SLVR reserve, in wei (18 decimals). */
|
|
7
|
+
slvrReserve: bigint;
|
|
8
|
+
/** ETH (WETH) reserve, in wei (18 decimals). */
|
|
9
|
+
ethReserve: bigint;
|
|
10
|
+
/** Whether SLVR is `token0` in the pair (ordering is resolved for you). */
|
|
11
|
+
token0IsSlvr: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Reads the SLVR price from the SLVR/ETH UniswapV2 pair.
|
|
15
|
+
*
|
|
16
|
+
* Mirrors the web app's price logic: it reads the pair's `getReserves()` and
|
|
17
|
+
* `token0()`, figures out which reserve is SLVR (never assumes ordering), and
|
|
18
|
+
* prices SLVR as `ethReserve / slvrReserve`. Both tokens are 18-decimal, so the
|
|
19
|
+
* raw reserve ratio is already ETH-per-SLVR.
|
|
20
|
+
*
|
|
21
|
+
* This is a **spot** price straight from reserves — no TWAP, no slippage model.
|
|
22
|
+
* Fine for sizing bets and EV estimates; do not use it as an oracle for anything
|
|
23
|
+
* that must resist manipulation.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { SlvrPrice } from '@slvr-labs/sdk';
|
|
28
|
+
* const price = new SlvrPrice(publicClient, pairAddress, slvrTokenAddress);
|
|
29
|
+
* const ethPerSlvr = await price.getPriceInEth();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare class SlvrPrice {
|
|
33
|
+
private publicClient;
|
|
34
|
+
private pairAddress;
|
|
35
|
+
private slvrTokenAddress;
|
|
36
|
+
private static readonly PAIR_ABI;
|
|
37
|
+
constructor(publicClient: PublicClient, pairAddress: Address, slvrTokenAddress: Address);
|
|
38
|
+
/** Read the pair reserves and resolve which side is SLVR. */
|
|
39
|
+
getReserves(): Promise<SlvrReserves>;
|
|
40
|
+
/**
|
|
41
|
+
* SLVR price in ETH (ETH per SLVR), as a floating-point number.
|
|
42
|
+
* @throws {Error} if the pair has no SLVR liquidity (zero reserve).
|
|
43
|
+
*/
|
|
44
|
+
getPriceInEth(): Promise<number>;
|
|
45
|
+
/**
|
|
46
|
+
* SLVR price in ETH as a WAD (1e18-scaled `bigint`), for callers that want to
|
|
47
|
+
* stay in integer math: `priceWad = ethReserve * 1e18 / slvrReserve`.
|
|
48
|
+
* @throws {Error} if the pair has no SLVR liquidity (zero reserve).
|
|
49
|
+
*/
|
|
50
|
+
getPriceInEthWad(): Promise<bigint>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=price.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../src/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAY,MAAM,MAAM,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,gBAAgB,CAAU;IAElC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAG7B;gBAES,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO;IAMvF,6DAA6D;IACvD,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IAoB1C;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAQtC;;;;OAIG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CAO1C"}
|