solid-drift 0.15.0 → 0.17.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.
@@ -0,0 +1,323 @@
1
+ import { type Accessor } from "solid-js";
2
+ /**
3
+ * Web3 data layer: zero-dependency chain and market data as signals.
4
+ *
5
+ * Public RPC and API endpoints over fetch, with user-swappable endpoints.
6
+ * Every network primitive shares the `{ data, error, status, retry, abort }`
7
+ * shape and is SSR-safe (nothing fetches on the server).
8
+ *
9
+ * Honest limits: public endpoints are rate-limited, so default polling
10
+ * intervals are conservative. This is a read-only data layer: transaction
11
+ * signing stays with wallet libraries like wagmi.
12
+ */
13
+ export type PollStatus = "idle" | "loading" | "success" | "error";
14
+ export interface PollOptions {
15
+ /** Milliseconds between fetches. Default 30000. */
16
+ interval?: number;
17
+ /** Error backoff multiplier. Default 2. */
18
+ backoff?: number;
19
+ /** Backoff cap in milliseconds. Default 300000. */
20
+ maxInterval?: number;
21
+ /** Fetch immediately on creation. Default true. */
22
+ immediate?: boolean;
23
+ }
24
+ export interface PollControls<T> {
25
+ data: Accessor<T | undefined>;
26
+ error: Accessor<Error | null>;
27
+ status: Accessor<PollStatus>;
28
+ /** Fetch now and reset the backoff. */
29
+ retry: () => void;
30
+ /** Stop polling and abort any in-flight request. */
31
+ abort: () => void;
32
+ }
33
+ /**
34
+ * Backoff polling infrastructure for the data primitives.
35
+ *
36
+ * Fetches immediately (unless `immediate: false`), then on `interval`.
37
+ * On error the interval multiplies by `backoff` up to `maxInterval` and
38
+ * resets on the next success. Uses `setTimeout`, so background tabs get
39
+ * the browser's natural timer throttling instead of a busy rAF loop.
40
+ * SSR-safe: never fetches on the server.
41
+ *
42
+ * ```ts
43
+ * const { data, status, retry, abort } = createPoll(
44
+ * async (signal) => {
45
+ * const res = await fetch("https://api.example.com/price", { signal });
46
+ * return res.json();
47
+ * },
48
+ * { interval: 30000 },
49
+ * );
50
+ * ```
51
+ */
52
+ export declare function createPoll<T>(fetcher: (signal: AbortSignal) => Promise<T>, options?: PollOptions): PollControls<T>;
53
+ /**
54
+ * Shorten an EVM address: `0x1234567890abcdef...` becomes `0x1234…abcd`.
55
+ * Returns the input unchanged when it is not a valid address.
56
+ */
57
+ export declare function shortenAddress(address: string, chars?: number): string;
58
+ /** True for `0x` + 40 hex chars. Checksum-agnostic. */
59
+ export declare function isAddress(value: string): boolean;
60
+ /**
61
+ * Format a wei-style integer as a decimal string: `formatUnits(1500000000000000000n)`
62
+ * is `"1.5"`. Accepts bigint or integer strings. BigInt-safe, no floats.
63
+ */
64
+ export declare function formatUnits(value: bigint | string, decimals?: number): string;
65
+ /**
66
+ * Parse a decimal string into wei-style bigint: `parseUnits("1.5")` is
67
+ * `1500000000000000000n`. Throws on invalid input or too many decimals.
68
+ */
69
+ export declare function parseUnits(value: string, decimals?: number): bigint;
70
+ export interface ChainInfo {
71
+ id: number;
72
+ name: string;
73
+ currency: string;
74
+ decimals: number;
75
+ explorer: string;
76
+ rpc: string;
77
+ }
78
+ /** Registry of well-known EVM chains: id to name, currency, explorer, RPC. */
79
+ export declare const CHAINS: Record<number, ChainInfo>;
80
+ /**
81
+ * Look up a chain in `CHAINS` as an accessor. Unknown ids give `undefined`.
82
+ *
83
+ * ```ts
84
+ * const chain = createChain(() => 1)
85
+ * chain()?.explorer // "https://etherscan.io"
86
+ * ```
87
+ */
88
+ export declare function createChain(source: number | Accessor<number>): Accessor<ChainInfo | undefined>;
89
+ /**
90
+ * keccak256 of a byte array. Exported for tests; not part of the public API.
91
+ */
92
+ export declare function keccak256(data: Uint8Array): Uint8Array<ArrayBuffer>;
93
+ export interface TokenPrice {
94
+ /** Price in the quote currency. */
95
+ price: number;
96
+ /** 24h change percent, when the source reports it. */
97
+ change24h?: number;
98
+ }
99
+ export interface TokenPriceOptions extends PollOptions {
100
+ /** Quote currency id. Default "usd". */
101
+ vsCurrency?: string;
102
+ /** Price API base. Default CoinGecko public API. */
103
+ endpoint?: string;
104
+ }
105
+ /**
106
+ * Live token price as a signal, via CoinGecko's public API.
107
+ *
108
+ * The free endpoint is rate-limited; the default 60s interval is
109
+ * conservative on purpose. Pass your own `endpoint` (any base that
110
+ * answers `/simple/price?ids={id}&vs_currencies={vs}&include_24hr_change=true`).
111
+ *
112
+ * ```ts
113
+ * const { price, change24h, status } = createTokenPrice("ethereum");
114
+ * <Show when={status() === "success"}>
115
+ * ${(price() ?? 0).toFixed(2)} ({(change24h() ?? 0).toFixed(1)}%)
116
+ * </Show>
117
+ * ```
118
+ */
119
+ export declare function createTokenPrice(tokenId: string | Accessor<string>, options?: TokenPriceOptions): PollControls<TokenPrice> & {
120
+ price: Accessor<number | undefined>;
121
+ change24h: Accessor<number | undefined>;
122
+ };
123
+ export interface PriceChangeOptions {
124
+ /** Rolling window in ms. Default 3600000 (1h). */
125
+ windowMs?: number;
126
+ /** How often to sample the source in ms. Default 60000. */
127
+ sampleMs?: number;
128
+ }
129
+ /**
130
+ * Percent change of any numeric signal over a rolling window.
131
+ *
132
+ * Samples the source on each change and on `sampleMs`, keeps samples
133
+ * within `windowMs`, and reports `(last - first) / first * 100`.
134
+ * `undefined` until at least two samples exist. Signal-native, no network.
135
+ *
136
+ * ```ts
137
+ * const { price } = createTokenPrice("ethereum");
138
+ * const { change, reset } = createPriceChange(price);
139
+ * ```
140
+ */
141
+ export declare function createPriceChange(source: Accessor<number | undefined>, options?: PriceChangeOptions): {
142
+ change: Accessor<number | undefined>;
143
+ reset: () => void;
144
+ };
145
+ /**
146
+ * Compare two numeric signals: their ratio, percent difference, and which
147
+ * is larger. Any side `undefined` makes everything `undefined` until both
148
+ * have values. Signal-native, no network.
149
+ *
150
+ * ```ts
151
+ * const { price: eth } = createTokenPrice("ethereum");
152
+ * const { price: btc } = createTokenPrice("bitcoin");
153
+ * const { ratio, diffPercent, leader } = createPriceCompare(eth, btc);
154
+ * ```
155
+ */
156
+ export declare function createPriceCompare(a: Accessor<number | undefined>, b: Accessor<number | undefined>): {
157
+ ratio: Accessor<number | undefined>;
158
+ diffPercent: Accessor<number | undefined>;
159
+ leader: Accessor<"a" | "b" | "tie" | undefined>;
160
+ };
161
+ export interface GasPriceOptions extends PollOptions {
162
+ /** JSON-RPC endpoint. Default a public mainnet endpoint. */
163
+ endpoint?: string;
164
+ }
165
+ export interface GasPriceData {
166
+ wei: bigint;
167
+ gwei: number;
168
+ }
169
+ /**
170
+ * Current gas price over JSON-RPC (`eth_gasPrice`), as wei bigint and gwei.
171
+ * Default 15s polling. Swap `endpoint` for any chain.
172
+ */
173
+ export declare function createGasPrice(options?: GasPriceOptions): PollControls<GasPriceData> & {
174
+ wei: Accessor<bigint | undefined>;
175
+ gwei: Accessor<number | undefined>;
176
+ };
177
+ export interface BalanceOptions extends PollOptions {
178
+ /** JSON-RPC endpoint. Default a public mainnet endpoint. */
179
+ endpoint?: string;
180
+ /** ERC20 token contract. Omit for the native balance. */
181
+ token?: string;
182
+ /** Decimals for formatting. Default 18. */
183
+ decimals?: number;
184
+ }
185
+ export interface BalanceData {
186
+ balance: bigint;
187
+ formatted: string;
188
+ }
189
+ /**
190
+ * Token balance of an address: native (`eth_getBalance`) or ERC20
191
+ * (`balanceOf` via `eth_call`). Read-only; never signs.
192
+ *
193
+ * ```ts
194
+ * const { formatted } = createBalance("0xabc…", { token: "0xdef…" });
195
+ * ```
196
+ */
197
+ export declare function createBalance(address: string, options?: BalanceOptions): PollControls<BalanceData> & {
198
+ balance: Accessor<bigint | undefined>;
199
+ formatted: Accessor<string | undefined>;
200
+ };
201
+ export interface TxReceiptData {
202
+ transactionHash: string;
203
+ blockNumber: number;
204
+ /** true when `status` is 0x1, false when 0x0 (reverted). */
205
+ success: boolean;
206
+ gasUsed: bigint;
207
+ }
208
+ export interface TxReceiptOptions extends PollOptions {
209
+ /** JSON-RPC endpoint. Default a public mainnet endpoint. */
210
+ endpoint?: string;
211
+ }
212
+ /**
213
+ * Watch a transaction hash until its receipt lands. Polls every 4s and
214
+ * stops on its own once the receipt arrives; `mined()` mirrors that.
215
+ * Read-only confirmation; pairs with `createTxLifecycle` from web3.ts.
216
+ */
217
+ export declare function createTxReceipt(hash: string, options?: TxReceiptOptions): PollControls<TxReceiptData | null> & {
218
+ receipt: Accessor<TxReceiptData | null | undefined>;
219
+ mined: Accessor<boolean>;
220
+ };
221
+ export interface BlockNumberOptions extends PollOptions {
222
+ /** JSON-RPC endpoint. Default a public mainnet endpoint. */
223
+ endpoint?: string;
224
+ }
225
+ /**
226
+ * Latest block number over JSON-RPC. Default 12s polling.
227
+ * Handy as a chain-health heartbeat and a cache-busting ticker.
228
+ */
229
+ export declare function createBlockNumber(options?: BlockNumberOptions): PollControls<number> & {
230
+ blockNumber: Accessor<number | undefined>;
231
+ };
232
+ export interface ChainlinkPriceOptions extends PollOptions {
233
+ /** JSON-RPC endpoint. Default a public mainnet endpoint. */
234
+ endpoint?: string;
235
+ }
236
+ /**
237
+ * Read a Chainlink `AggregatorV3Interface` price feed on-chain:
238
+ * `decimals()` once, then `latestRoundData()` polled every 30s.
239
+ * Feed addresses live on the
240
+ * [Chainlink docs](https://docs.chain.link/data-feeds/price-feeds/addresses).
241
+ *
242
+ * ```ts
243
+ * // ETH / USD feed on mainnet
244
+ * const { price } = createChainlinkPrice("0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419");
245
+ * ```
246
+ */
247
+ export declare function createChainlinkPrice(feed: string, options?: ChainlinkPriceOptions): PollControls<number> & {
248
+ price: Accessor<number | undefined>;
249
+ };
250
+ export interface NFTMetadata {
251
+ name?: string;
252
+ description?: string;
253
+ image?: string;
254
+ attributes?: Array<Record<string, unknown>>;
255
+ raw: unknown;
256
+ }
257
+ export interface NFTMetadataOptions {
258
+ /** JSON-RPC endpoint for `tokenURI`. Default a public mainnet endpoint. */
259
+ endpoint?: string;
260
+ /** IPFS gateway base. Default "https://ipfs.io". */
261
+ gateway?: string;
262
+ }
263
+ /**
264
+ * Fetch an NFT's `tokenURI` on-chain and resolve its JSON metadata
265
+ * (one-shot, with `retry`). `ipfs://` URIs are rewritten through the
266
+ * gateway. Returns the parsed fields plus `raw` for anything custom.
267
+ *
268
+ * ```ts
269
+ * const { metadata, image, status, retry } = createNFTMetadata(
270
+ * "0xcontract…",
271
+ * 42,
272
+ * );
273
+ * ```
274
+ */
275
+ export declare function createNFTMetadata(contract: string, tokenId: string | number | bigint, options?: NFTMetadataOptions): {
276
+ data: Accessor<NFTMetadata | undefined>;
277
+ error: Accessor<Error | null>;
278
+ status: Accessor<PollStatus>;
279
+ retry: () => void;
280
+ abort: () => void;
281
+ metadata: Accessor<NFTMetadata | undefined>;
282
+ image: Accessor<string | undefined>;
283
+ };
284
+ export interface ENSOptions {
285
+ /** JSON-RPC endpoint. Default a public mainnet endpoint. */
286
+ endpoint?: string;
287
+ }
288
+ /**
289
+ * Reverse-resolve an address to its ENS name via the public ENS registry
290
+ * (one-shot, with `retry`). `undefined` when the address has no name set;
291
+ * errors (network, RPC) surface on `error`.
292
+ *
293
+ * ```ts
294
+ * const { name, status } = createENS("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045");
295
+ * ```
296
+ */
297
+ export declare function createENS(address: string, options?: ENSOptions): {
298
+ data: Accessor<string | undefined>;
299
+ error: Accessor<Error | null>;
300
+ status: Accessor<PollStatus>;
301
+ retry: () => void;
302
+ abort: () => void;
303
+ name: Accessor<string | undefined>;
304
+ };
305
+ export interface IdenticonOptions {
306
+ /** Pixel size of the square image. Default 64. */
307
+ size?: number;
308
+ /** Grid cells per side. Default 8. */
309
+ cells?: number;
310
+ /** Background color. Default "#f0f0f0". */
311
+ background?: string;
312
+ }
313
+ /**
314
+ * Deterministic identicon avatar for any address as a data URI: a mirrored
315
+ * random-walk grid in SVG, so the same address always renders the same
316
+ * image. Pure computation, works on the server, no network.
317
+ *
318
+ * ```tsx
319
+ * const avatar = createIdenticon("0xabc…");
320
+ * <img src={avatar()} alt="avatar" width={64} height={64} />;
321
+ * ```
322
+ */
323
+ export declare function createIdenticon(address: string | Accessor<string>, options?: IdenticonOptions): Accessor<string>;