@molpha/sdk 0.2.0-dev-20261002062009 → 0.2.0-dev-20261005191253
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/README.md +71 -14
- package/dist/{chunk-2X22JY7Q.js → chunk-H77BBZOL.js} +6 -3
- package/dist/chunk-H77BBZOL.js.map +1 -0
- package/dist/index.d.ts +281 -42
- package/dist/index.js +484 -123
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/dist/{wallet-HfGXPpOp.d.ts → wallet--IGHoCtG.d.ts} +14 -12
- package/idl/molpha.json +25 -8
- package/package.json +1 -1
- package/dist/chunk-2X22JY7Q.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Address } from '@solana/kit';
|
|
2
2
|
import { Wallet, Idl, AnchorProvider } from '@anchor-lang/core';
|
|
3
|
-
import { U as UpstreamQuote, A as APIConfig, a as AssetDomain, b as UpstreamTerms, E as EvmSigner,
|
|
4
|
-
export { l as AttestationPayload, m as EncKeyBundle, n as NumericConfig, o as RegistryInfo, p as SchnorrSignature, q as gatewaySignerFromWallet, s as signerFromKeypair } from './wallet
|
|
3
|
+
import { U as UpstreamQuote, A as APIConfig, a as AssetDomain, b as UpstreamTerms, E as EvmSigner, S as Signer, c as SourcePaymentOptions, R as RegistrySelectionConfig, N as Node, d as NodeKeyVerifier, e as NodesInfo, f as Attestation, g as SolanaAccountMeta, h as SolanaConnection, i as SolanaAddress, j as NodeKeyVerifierArgs, k as AggregationConfig, M as MolphaWallet } from './wallet--IGHoCtG.js';
|
|
4
|
+
export { l as AttestationPayload, m as EncKeyBundle, n as NumericConfig, o as RegistryInfo, p as SchnorrSignature, q as gatewaySignerFromWallet, s as signerFromKeypair } from './wallet--IGHoCtG.js';
|
|
5
5
|
import BN from 'bn.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -27,6 +27,12 @@ interface GatewayInfo {
|
|
|
27
27
|
gatewayAuthority: string;
|
|
28
28
|
/** Program id the gateway settles against; must match the client's when present. */
|
|
29
29
|
programId?: string;
|
|
30
|
+
/** The gateway's round timestamp grid in milliseconds (`round.tick_ms`), when advertised. */
|
|
31
|
+
tickMs?: number;
|
|
32
|
+
/** Longest the gateway waits for a round, in seconds (`node.agg_wait_seconds`), when advertised. */
|
|
33
|
+
roundTimeoutSeconds?: number;
|
|
34
|
+
/** Rounds the gateway runs at once (`limits.max_inflight_rounds`); 0 or absent: not advertised. */
|
|
35
|
+
maxInflightRounds?: number;
|
|
30
36
|
}
|
|
31
37
|
declare function normalizeEndpoint(input: GatewayEndpointInput): GatewayEndpoint;
|
|
32
38
|
/** 32-byte form of a base58 address. */
|
|
@@ -48,8 +54,8 @@ interface RequestAuthFields {
|
|
|
48
54
|
sourceId: Uint8Array | string;
|
|
49
55
|
/** u8 — the per-request quorum. */
|
|
50
56
|
signaturesRequired: number;
|
|
51
|
-
/** u64 unix
|
|
52
|
-
|
|
57
|
+
/** u64 unix SECONDS at signing (the auth freshness stamp, not the round's timestamp). */
|
|
58
|
+
authTimestamp: number | bigint;
|
|
53
59
|
}
|
|
54
60
|
/** Borsh encoding of `RequestAuth` — the hash body, without the domain. */
|
|
55
61
|
declare function encodeRequestAuth(fields: RequestAuthFields): Uint8Array;
|
|
@@ -117,15 +123,16 @@ interface RequestSignedDataOptions {
|
|
|
117
123
|
*/
|
|
118
124
|
subscriptionOwner?: string;
|
|
119
125
|
/**
|
|
120
|
-
* Solana pubkey (base58) of the consumer
|
|
126
|
+
* Solana pubkey (base58) of the consumer: the subscription owner, or a delegate of it.
|
|
121
127
|
* Overrides the gateway's `defaultConsumerAuthority` when set.
|
|
122
128
|
*/
|
|
123
129
|
consumerAuthority?: string;
|
|
124
130
|
/**
|
|
125
|
-
* Signs `hashRequestAuth({ programId, gateway, sourceId, signaturesRequired,
|
|
131
|
+
* Signs `hashRequestAuth({ programId, gateway, sourceId, signaturesRequired, authTimestamp })`.
|
|
126
132
|
* The hash binds the gateway's on-chain account, so it is computed — and the signer
|
|
127
|
-
* invoked — once per endpoint actually tried
|
|
128
|
-
* when set. When both are omitted, sends an all-zero
|
|
133
|
+
* invoked — once per endpoint actually tried, with a fresh `authTimestamp` each time.
|
|
134
|
+
* Overrides the gateway's `defaultSigner` when set. When both are omitted, sends an all-zero
|
|
135
|
+
* authSig (a gateway rejects it with 401; for tests and local tooling only).
|
|
129
136
|
*/
|
|
130
137
|
signer?: Signer;
|
|
131
138
|
encrypt?: {
|
|
@@ -144,9 +151,23 @@ interface RequestSignedDataOptions {
|
|
|
144
151
|
sourcePayment?: SourcePaymentOptions;
|
|
145
152
|
/** Max accepted value age in seconds. Default 60. */
|
|
146
153
|
maxAge?: number;
|
|
147
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Max attempts. Each retry waits for a later gateway tick, plus jitter, and for longer after a
|
|
156
|
+
* busy answer (`Retry-After`) or a failure that is not a conflict (capped exponential backoff);
|
|
157
|
+
* see {@link retryDelayMs}. Default {@link DEFAULT_MAX_RETRIES}.
|
|
158
|
+
*/
|
|
148
159
|
maxRetries?: number;
|
|
149
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* The gateway's tick grid in milliseconds (its `round.tick_ms`). A retry waits for the start of
|
|
162
|
+
* the next tick so it is a new round, not a duplicate of the last. Default: the gateway's
|
|
163
|
+
* advertised `tickMs` (read once, on the first retry), else 1000.
|
|
164
|
+
*/
|
|
165
|
+
tickMs?: number;
|
|
166
|
+
/**
|
|
167
|
+
* Per-request timeout in ms. Default {@link DEFAULT_ROUND_TIMEOUT_MS}, above the gateway's own
|
|
168
|
+
* wait for a round: a shorter timeout abandons rounds the gateway is still running and the retry
|
|
169
|
+
* then starts another.
|
|
170
|
+
*/
|
|
150
171
|
timeoutMs?: number;
|
|
151
172
|
/**
|
|
152
173
|
* Pre-fetched round inputs. Any field present here skips its network/on-chain
|
|
@@ -177,8 +198,9 @@ interface MolphaGatewayOptions {
|
|
|
177
198
|
/** Solana pubkey (base58) of the consumer authority used when a request omits it. */
|
|
178
199
|
defaultConsumerAuthority?: string;
|
|
179
200
|
/**
|
|
180
|
-
* Molpha program id the request authorization is bound to
|
|
181
|
-
*
|
|
201
|
+
* Molpha program id the request authorization is bound to (and that `fetchGatewayInfo`
|
|
202
|
+
* checks the gateway settles against). Defaults to the vendored `MOLPHA_PROGRAM_ID`;
|
|
203
|
+
* must match the gateway's deployment.
|
|
182
204
|
*/
|
|
183
205
|
programId?: string;
|
|
184
206
|
/**
|
|
@@ -191,15 +213,53 @@ interface MolphaGatewayOptions {
|
|
|
191
213
|
* may use gateway-provided node keys without authentication. Defaults to false.
|
|
192
214
|
*/
|
|
193
215
|
allowUnverifiedNodeKeysForPrivateApi?: boolean;
|
|
216
|
+
/** Source of randomness in [0, 1) for retry jitter; defaults to `Math.random` (tests only). */
|
|
217
|
+
random?: () => number;
|
|
194
218
|
}
|
|
195
219
|
/**
|
|
196
220
|
* The slow-changing inputs a `requestSignedData` round binds to. Fetch once with
|
|
197
221
|
* {@link MolphaGateway.prepareContext} and reuse across many rounds.
|
|
198
222
|
*/
|
|
199
223
|
interface RoundContext extends RegistrySelectionConfig {
|
|
200
|
-
/** Full node set
|
|
224
|
+
/** Full registry node set: private API secrets are encrypted for every node in it. */
|
|
201
225
|
nodes: Node[];
|
|
202
226
|
}
|
|
227
|
+
/** Milliseconds from `nowMs` to the start of the next tick, plus a millisecond of margin. */
|
|
228
|
+
declare function msUntilNextTick(nowMs: number, tickMs: number): number;
|
|
229
|
+
/**
|
|
230
|
+
* Default per-request timeout: above the gateway's own wait for a round (`node.agg_wait_seconds`,
|
|
231
|
+
* 30 s by default), so the client does not abandon a round the gateway is still running and then
|
|
232
|
+
* start a second one. A gateway advertises its value as `roundTimeoutSeconds` in `GET /v1/info`.
|
|
233
|
+
*/
|
|
234
|
+
declare const DEFAULT_ROUND_TIMEOUT_MS = 35000;
|
|
235
|
+
/** Default number of attempts. */
|
|
236
|
+
declare const DEFAULT_MAX_RETRIES = 6;
|
|
237
|
+
/**
|
|
238
|
+
* Why an attempt failed, as far as it decides how long to wait before the next one:
|
|
239
|
+
* - `conflict`: HTTP 409, this consumer already has a round for the source in this tick;
|
|
240
|
+
* - `busy`: HTTP 503 or 429, the gateway is at capacity or a node set is unavailable, optionally
|
|
241
|
+
* with the gateway's `Retry-After`;
|
|
242
|
+
* - `error`: anything else that may be transient (timeout, network, other 5xx).
|
|
243
|
+
*/
|
|
244
|
+
type RetryCause = {
|
|
245
|
+
kind: "conflict";
|
|
246
|
+
} | {
|
|
247
|
+
kind: "busy";
|
|
248
|
+
retryAfterMs?: number;
|
|
249
|
+
} | {
|
|
250
|
+
kind: "error";
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* How long to wait before the next attempt, in ms. Every delay reaches at least the start of the
|
|
254
|
+
* next tick (a retry inside the tick that just failed would be a duplicate round), then adds jitter
|
|
255
|
+
* so clients that failed together do not retry together:
|
|
256
|
+
* - conflict: the next tick plus up to half a tick;
|
|
257
|
+
* - busy: the later of the next tick and the gateway's `Retry-After` (a tick if absent), plus up to
|
|
258
|
+
* a tick;
|
|
259
|
+
* - error: capped exponential backoff (250 ms, 500 ms, ... 5 s) with half of it randomized.
|
|
260
|
+
* `failures` is the number of attempts that have failed so far (1 after the first).
|
|
261
|
+
*/
|
|
262
|
+
declare function retryDelayMs(cause: RetryCause, failures: number, nowMs: number, tickMs: number, random?: () => number): number;
|
|
203
263
|
/** Default gateway base URL when `endpoints` is omitted. */
|
|
204
264
|
declare const DEFAULT_GATEWAY_ENDPOINT = "https://dev-gateway.molpha.io/";
|
|
205
265
|
/** Thrown for terminal gateway errors (400/401) — never retried. */
|
|
@@ -220,12 +280,17 @@ declare class MolphaGateway {
|
|
|
220
280
|
private readonly programIdBytes;
|
|
221
281
|
/** Gateway PDA per endpoint URL; resolved once per client lifetime. */
|
|
222
282
|
private readonly gatewayPdas;
|
|
283
|
+
/** Advertised timing per endpoint URL, read lazily on the first retry. */
|
|
284
|
+
private readonly advertisedInfo;
|
|
285
|
+
private readonly random;
|
|
223
286
|
constructor(endpoints?: GatewayEndpointInput | GatewayEndpointInput[], getRegistrySelectionConfig?: () => Promise<RegistrySelectionConfig>, defaultSigner?: Signer,
|
|
224
287
|
/**
|
|
225
|
-
* Either a default subscription owner (base58) or gateway options. A string
|
|
226
|
-
*
|
|
288
|
+
* Either a default subscription owner (base58) or gateway options. A string is the
|
|
289
|
+
* shorthand for `{ defaultSubscriptionOwner }` used by standalone callers/tests.
|
|
227
290
|
*/
|
|
228
291
|
defaultSubscriptionOwnerOrOptions?: string | MolphaGatewayOptions, defaultConsumerAuthority?: string);
|
|
292
|
+
/** The configured gateway base URLs, in failover order. */
|
|
293
|
+
endpointUrls(): string[];
|
|
229
294
|
/** Tries endpoints in order; returns the first node list it can fetch. */
|
|
230
295
|
getNodes(): Promise<Node[]>;
|
|
231
296
|
/**
|
|
@@ -233,7 +298,7 @@ declare class MolphaGateway {
|
|
|
233
298
|
* selection policy, which sizes the eligible set a paid source must fund.
|
|
234
299
|
*
|
|
235
300
|
* The `registry` block is advisory: it is whatever the gateway read from the
|
|
236
|
-
* chain, and is absent
|
|
301
|
+
* chain, and is absent when that read failed. Prefer the
|
|
237
302
|
* on-chain read (`MolphaSolanaClient.getRegistrySelectionConfig`) whenever a
|
|
238
303
|
* Solana connection is available — `requestSignedData` already does.
|
|
239
304
|
*/
|
|
@@ -257,12 +322,23 @@ declare class MolphaGateway {
|
|
|
257
322
|
prepareContext(): Promise<RoundContext>;
|
|
258
323
|
/**
|
|
259
324
|
* Request a threshold-signed data update from the gateway, with retry +
|
|
260
|
-
* failover.
|
|
261
|
-
*
|
|
325
|
+
* failover. The body is POSTed to each endpoint in order until one `completed`s.
|
|
326
|
+
*
|
|
327
|
+
* The round's `sourceId` is derived from `apiConfig`. The request carries no round timestamp:
|
|
328
|
+
* the gateway assigns the round's `timestamp` (unix milliseconds) from its own clock
|
|
329
|
+
* on a tick grid, and the committee follows from it. The result carries the assigned
|
|
330
|
+
* timestamp and the signers' bitmap. A retry waits for a later tick, because a round that was
|
|
331
|
+
* already reserved or dispatched cannot run again in the same one (HTTP 409).
|
|
262
332
|
*
|
|
263
|
-
* The
|
|
264
|
-
*
|
|
265
|
-
*
|
|
333
|
+
* The request is authorized by a `RequestAuth` signature (`authSig`) over the program id, the
|
|
334
|
+
* endpoint's Gateway PDA, the source id, the quorum and `authTimestamp` (unix seconds, read
|
|
335
|
+
* from the local clock for every attempt). It only proves the caller may spend the
|
|
336
|
+
* subscription's rounds; it is not part of the round, so the signature is recomputed for every
|
|
337
|
+
* endpoint tried.
|
|
338
|
+
*
|
|
339
|
+
* Because the committee is unknown until the gateway stamps the round, private API
|
|
340
|
+
* secrets are encrypted for **every** node of the registry; the gateway forwards only the
|
|
341
|
+
* selected nodes' envelopes.
|
|
266
342
|
*
|
|
267
343
|
* By default this fetches the registry selection config up front and the node
|
|
268
344
|
* set only when the round needs it (private API encryption, or when the registry
|
|
@@ -282,6 +358,12 @@ declare class MolphaGateway {
|
|
|
282
358
|
* encryption) or when nothing else can tell us the node count.
|
|
283
359
|
*/
|
|
284
360
|
private resolveContext;
|
|
361
|
+
/**
|
|
362
|
+
* The gateway's advertised tick grid, read once per endpoint and only when a retry needs it. Any
|
|
363
|
+
* failure (an old gateway without `/v1/info`, a timeout) means "not advertised", so the caller
|
|
364
|
+
* falls back to the default; a failure is not cached.
|
|
365
|
+
*/
|
|
366
|
+
private advertisedTickMs;
|
|
285
367
|
/** Gateway PDA bytes for an endpoint, cached per URL. A failed lookup is not cached. */
|
|
286
368
|
private resolveGatewayPda;
|
|
287
369
|
private lookupGatewayPda;
|
|
@@ -374,6 +456,17 @@ declare function planIdFromVariant(variant: Record<string, unknown>): PlanId;
|
|
|
374
456
|
* `Program` over the vendored IDL (program `3d01170`, "Epoch settlements").
|
|
375
457
|
*/
|
|
376
458
|
|
|
459
|
+
/**
|
|
460
|
+
* Compute units to request for a `submit_attestation` carrying `signerCount` signatures.
|
|
461
|
+
*
|
|
462
|
+
* The program's LiteSVM benchmark measures the whole transaction at about `43k + 9.1k` units per
|
|
463
|
+
* signer (119k at 8 signers, 155k at 12, 208k at 18), so the old flat 1.4M request was 7-10 times
|
|
464
|
+
* what a typical aggregate uses. That matters once a priority fee is attached, because it is
|
|
465
|
+
* priced per requested unit, and for how the scheduler packs blocks. The estimate adds 15% and a
|
|
466
|
+
* fixed 10k: the program's selection check costs a little more on some registries than the
|
|
467
|
+
* benchmark's, and a limit that is hit fails the transaction for good.
|
|
468
|
+
*/
|
|
469
|
+
declare function estimateSubmitComputeUnits(signerCount: number): number;
|
|
377
470
|
type Commitment$1 = NonNullable<ConstructorParameters<typeof AnchorProvider>[2]>["commitment"];
|
|
378
471
|
interface SubscribeResult {
|
|
379
472
|
signature: string;
|
|
@@ -392,8 +485,7 @@ interface PlanInfo {
|
|
|
392
485
|
isActive: boolean;
|
|
393
486
|
}
|
|
394
487
|
/**
|
|
395
|
-
* On-chain `Subscription`. The program
|
|
396
|
-
* `prepaid_usdc` and the locked `price` were removed (round quota is counted by the
|
|
488
|
+
* On-chain `Subscription`. The program does not track usage (round quota is counted by the
|
|
397
489
|
* gateway's off-chain outbox), so there is no on-chain "rounds used" figure to read.
|
|
398
490
|
*/
|
|
399
491
|
interface SubscriptionInfo {
|
|
@@ -428,8 +520,8 @@ interface FeedAccount {
|
|
|
428
520
|
hash: Record<string, never>;
|
|
429
521
|
};
|
|
430
522
|
submitter: Address;
|
|
431
|
-
/** u64 unix
|
|
432
|
-
|
|
523
|
+
/** u64 unix MILLISECONDS (the round's gateway-assigned timestamp). */
|
|
524
|
+
timestamp: BN;
|
|
433
525
|
signaturesRequired: number;
|
|
434
526
|
signersBitmap: number[];
|
|
435
527
|
registryVersion: number;
|
|
@@ -443,7 +535,7 @@ interface SubmitAttestationArgs {
|
|
|
443
535
|
sourceId: number[];
|
|
444
536
|
registryVersion: number;
|
|
445
537
|
signaturesRequired: number;
|
|
446
|
-
|
|
538
|
+
timestamp: BN;
|
|
447
539
|
};
|
|
448
540
|
signature: {
|
|
449
541
|
aggSigS: number[];
|
|
@@ -459,7 +551,18 @@ interface SubmitAttestationArgs {
|
|
|
459
551
|
};
|
|
460
552
|
}
|
|
461
553
|
interface SubmitAttestationOptions {
|
|
554
|
+
/**
|
|
555
|
+
* Compute-unit limit. Defaults to {@link estimateSubmitComputeUnits} for the aggregate's signer
|
|
556
|
+
* count, not the 1.4M maximum.
|
|
557
|
+
*/
|
|
462
558
|
computeUnitLimit?: number;
|
|
559
|
+
/**
|
|
560
|
+
* Priority fee in micro-lamports per compute unit. A number is used as given; `"auto"` takes the
|
|
561
|
+
* 75th percentile of the fees recently paid by transactions that wrote the feed, capped at 1
|
|
562
|
+
* lamport per unit. Omitted: no priority fee, which is right on a quiet cluster. Raise it (or
|
|
563
|
+
* use `"auto"`) when submits are dropped under load.
|
|
564
|
+
*/
|
|
565
|
+
priorityFeeMicroLamports?: number | "auto";
|
|
463
566
|
/**
|
|
464
567
|
* Precomputed signer coalition key. When omitted, the client fetches signer `Node`
|
|
465
568
|
* accounts and sums their secp256k1 keys ({@link computeCoalitionKey}).
|
|
@@ -482,6 +585,10 @@ declare class MolphaSolanaClient {
|
|
|
482
585
|
private readonly program;
|
|
483
586
|
private readonly provider;
|
|
484
587
|
readonly programId: Address;
|
|
588
|
+
private readonly registryCache;
|
|
589
|
+
private readonly nodeKeyCache;
|
|
590
|
+
private readonly coalitionCache;
|
|
591
|
+
private priorityFeeCache?;
|
|
485
592
|
private constructor();
|
|
486
593
|
static create(opts: CreateClientOpts): MolphaSolanaClient;
|
|
487
594
|
private get wallet();
|
|
@@ -549,8 +656,12 @@ declare class MolphaSolanaClient {
|
|
|
549
656
|
* `keccak256(rawValue)`; {@link buildSubmitAttestationArgs} validates that before send.
|
|
550
657
|
*/
|
|
551
658
|
submitAttestation(attestation: Attestation, opts?: SubmitAttestationOptions): Promise<SubmitResult>;
|
|
659
|
+
/** The registry for `version`, reused for {@link REGISTRY_CACHE_MS}. */
|
|
660
|
+
private fetchRegistryCached;
|
|
661
|
+
private resolvePriorityFee;
|
|
552
662
|
/** Sum of the signers' keys, read from their on-chain `Node` accounts (one batched fetch). */
|
|
553
663
|
private computeSignerCoalitionKey;
|
|
664
|
+
private sumSignerKeys;
|
|
554
665
|
/**
|
|
555
666
|
* Read the feed written by `submitter` (default: this wallet) for
|
|
556
667
|
* `(sourceId, signaturesRequired)`, or `null` before its first submit.
|
|
@@ -709,8 +820,8 @@ interface AttestationMessageFields {
|
|
|
709
820
|
signersBitmap: string | Uint8Array;
|
|
710
821
|
/** 32-byte packed value (hex or bytes). */
|
|
711
822
|
value: string | Uint8Array;
|
|
712
|
-
/** Unix
|
|
713
|
-
|
|
823
|
+
/** Unix milliseconds (u64), assigned by the gateway. */
|
|
824
|
+
timestamp: number | bigint;
|
|
714
825
|
}
|
|
715
826
|
/** Compute the attestation message hash (32 bytes). */
|
|
716
827
|
declare function attestationMessageHash(fields: AttestationMessageFields): Uint8Array;
|
|
@@ -726,9 +837,17 @@ declare function normalizeSecp256k1PublicKeyHex(publicKeyHex: string, label?: st
|
|
|
726
837
|
declare function secp256k1PublicKeyFromCoordinates(x: Uint8Array, y: Uint8Array, label?: string): string;
|
|
727
838
|
|
|
728
839
|
/**
|
|
729
|
-
*
|
|
840
|
+
* Width in milliseconds of the window selection reads from the timestamp. The timestamp
|
|
841
|
+
* is unix milliseconds; the seed uses `floor(timestamp / SELECTION_WINDOW_MS)`, so
|
|
842
|
+
* sub-second precision never changes the committee. Changing it is a consensus break and must
|
|
843
|
+
* bump the selection prefix.
|
|
730
844
|
*/
|
|
731
|
-
declare
|
|
845
|
+
declare const SELECTION_WINDOW_MS = 1000n;
|
|
846
|
+
/**
|
|
847
|
+
* `seed = keccak256(keccak256("MOLPHA_SELECTION_V1") || sourceId || be32(rv) || be64(ts / 1000))`,
|
|
848
|
+
* where `ts` is the timestamp in unix MILLISECONDS (its 1 s window index is hashed).
|
|
849
|
+
*/
|
|
850
|
+
declare function deriveSelectionSeed(sourceId: Uint8Array, registryVersion: number, timestamp: number | bigint): Uint8Array;
|
|
732
851
|
/** `min(signaturesRequired + redundancyBuffer, nodeCount)`. */
|
|
733
852
|
declare function effectiveSelectionSize(signaturesRequired: number, redundancyBuffer: number, nodeCount: number): number;
|
|
734
853
|
/** Is bit `bit` set in the 32-byte big-endian `bitmap`? */
|
|
@@ -743,10 +862,24 @@ declare function selectedIndices(bitmap: Uint8Array, nodeCount: number): number[
|
|
|
743
862
|
declare function deriveGroupBitmap(seed: Uint8Array, nodeCount: number, groupSize: number): Uint8Array;
|
|
744
863
|
/**
|
|
745
864
|
* Convenience orchestrator: derive the selection bitmap end-to-end.
|
|
746
|
-
* `redundancy` defaults to 0; `ts`
|
|
865
|
+
* `redundancy` defaults to 0; `ts` is the timestamp in unix MILLISECONDS and defaults
|
|
866
|
+
* to now. The gateway assigns the real timestamp of a round, so this is for tests and tools.
|
|
747
867
|
*/
|
|
748
868
|
declare function deriveSelectionBitmap(sourceId: Uint8Array, registryVersion: number, nodeCount: number, signaturesRequired: number, redundancy?: number, ts?: number | bigint): Uint8Array;
|
|
749
869
|
|
|
870
|
+
/**
|
|
871
|
+
* `timestamp` is unix MILLISECONDS, assigned by the gateway. Chain clocks (Solana `Clock`,
|
|
872
|
+
* EVM `block.timestamp`), epoch windows and `maxAge`/staleness are measured in SECONDS, so
|
|
873
|
+
* anything that compares the two must go through {@link timestampSeconds}.
|
|
874
|
+
*/
|
|
875
|
+
/** `timestamp` (unix ms) as whole unix seconds, floored. */
|
|
876
|
+
declare function timestampSeconds(timestamp: number | bigint): number;
|
|
877
|
+
/**
|
|
878
|
+
* Age in whole seconds of a timestamp against `nowSeconds`, saturating at 0 so a
|
|
879
|
+
* timestamp slightly ahead of the local clock never goes negative.
|
|
880
|
+
*/
|
|
881
|
+
declare function timestampAgeSeconds(timestamp: number | bigint, nowSeconds: number): number;
|
|
882
|
+
|
|
750
883
|
/**
|
|
751
884
|
* Result codes returned by Molpha's stateless verifier contracts (`verify` on EVM and
|
|
752
885
|
* Starknet). Shared across VMs: the same attestation yields the same code on every chain.
|
|
@@ -761,11 +894,11 @@ declare const VERIFY_CODES: {
|
|
|
761
894
|
readonly FEED_WITNESS: 1;
|
|
762
895
|
/** The payload's `registryVersion` does not exist on this verifier. */
|
|
763
896
|
readonly BAD_REGISTRY_VERSION: 2;
|
|
764
|
-
/** Structurally invalid input, or a `
|
|
897
|
+
/** Structurally invalid input, or a `timestamp` in the future when `maxAge != 0`. */
|
|
765
898
|
readonly MALFORMED: 3;
|
|
766
|
-
/** `
|
|
899
|
+
/** `timestamp` predates the registry version's activation. */
|
|
767
900
|
readonly NOT_YET_ACTIVE: 4;
|
|
768
|
-
/** The registry version was superseded more than the grace window before `
|
|
901
|
+
/** The registry version was superseded more than the grace window before `timestamp`. */
|
|
769
902
|
readonly VERSION_EXPIRED: 5;
|
|
770
903
|
/** Reserved. Never returned. */
|
|
771
904
|
readonly COMPROMISED_QUORUM: 6;
|
|
@@ -823,7 +956,7 @@ declare const MOLPHA_VERIFIER_ABI: readonly [{
|
|
|
823
956
|
readonly type: "uint8";
|
|
824
957
|
readonly internalType: "uint8";
|
|
825
958
|
}, {
|
|
826
|
-
readonly name: "
|
|
959
|
+
readonly name: "timestamp";
|
|
827
960
|
readonly type: "uint64";
|
|
828
961
|
readonly internalType: "uint64";
|
|
829
962
|
}];
|
|
@@ -1071,8 +1204,8 @@ interface EvmAttestationPayload {
|
|
|
1071
1204
|
registryVersion: number;
|
|
1072
1205
|
/** `uint8`. */
|
|
1073
1206
|
signaturesRequired: number;
|
|
1074
|
-
/** `uint64`, unix seconds. */
|
|
1075
|
-
|
|
1207
|
+
/** `uint64`, unix MILLISECONDS (`timestamp / 1000` is the seconds the verifier's `maxAge` uses). */
|
|
1208
|
+
timestamp: bigint;
|
|
1076
1209
|
}
|
|
1077
1210
|
/** `IVerifier.SchnorrSignature`. */
|
|
1078
1211
|
interface EvmSchnorrSignature {
|
|
@@ -1136,7 +1269,7 @@ declare function buildEvmVerifierArgs(attestation: Attestation, options: BuildEv
|
|
|
1136
1269
|
* ABI calldata for `verify(attestation, maxAge)`: the 4-byte selector followed by nine
|
|
1137
1270
|
* 32-byte words. Both structs are static, so they encode inline with no offsets:
|
|
1138
1271
|
*
|
|
1139
|
-
* `value, sourceId, registryVersion, signaturesRequired,
|
|
1272
|
+
* `value, sourceId, registryVersion, signaturesRequired, timestamp, signature,
|
|
1140
1273
|
* commitment, signersBitmap, maxAge`
|
|
1141
1274
|
*
|
|
1142
1275
|
* For a raw `eth_call` (`{ to: verifier, data }`).
|
|
@@ -1182,8 +1315,8 @@ interface StarknetAttestationPayload {
|
|
|
1182
1315
|
registry_version: number;
|
|
1183
1316
|
/** `u8`. */
|
|
1184
1317
|
signatures_required: number;
|
|
1185
|
-
/** `u64`, unix seconds. */
|
|
1186
|
-
|
|
1318
|
+
/** `u64`, unix MILLISECONDS (`/ 1000` is the seconds the verifier's `max_age` uses). */
|
|
1319
|
+
timestamp: number;
|
|
1187
1320
|
}
|
|
1188
1321
|
/** Starknet calldata shape for `SchnorrSignature`. */
|
|
1189
1322
|
interface StarknetSchnorrSignature {
|
|
@@ -1243,7 +1376,7 @@ declare function buildStarknetVerifierArgs(attestation: Attestation, options: Bu
|
|
|
1243
1376
|
* Flat felt calldata for `verify(attestation, max_age)`, in Cairo `Serde` order — 13 felts:
|
|
1244
1377
|
*
|
|
1245
1378
|
* `value.low, value.high, source_id.low, source_id.high, registry_version,
|
|
1246
|
-
* signatures_required,
|
|
1379
|
+
* signatures_required, timestamp, signature.low, signature.high, commitment,
|
|
1247
1380
|
* signers_bitmap.low, signers_bitmap.high, max_age`
|
|
1248
1381
|
*
|
|
1249
1382
|
* For a raw `starknet_call` with `entry_point_selector = selector("verify")`.
|
|
@@ -1290,6 +1423,98 @@ declare const subscriptionPda: (owner: SolanaAddress, programId: SolanaAddress)
|
|
|
1290
1423
|
*/
|
|
1291
1424
|
declare function feedPda(sourceId: Uint8Array, signaturesRequired: number, submitter: SolanaAddress, programId: SolanaAddress): Address;
|
|
1292
1425
|
|
|
1426
|
+
/**
|
|
1427
|
+
* Drive many feeds through the gateway (and optionally on to Solana) without overloading it.
|
|
1428
|
+
*
|
|
1429
|
+
* The consumer is the party that pushes updates and pays for them, so the cost and the burst
|
|
1430
|
+
* behaviour of a large set of feeds is the consumer's to control. {@link requestMany} does the parts
|
|
1431
|
+
* that matter at volume:
|
|
1432
|
+
*
|
|
1433
|
+
* - the registry inputs are read once and shared by every request, not once per feed;
|
|
1434
|
+
* - concurrency is bounded and adapts: it starts from the gateway's advertised capacity, halves
|
|
1435
|
+
* when the gateway answers busy (503/429) and creeps back up while requests succeed (AIMD);
|
|
1436
|
+
* - request starts are spread over a window by a hash of each feed's source id, so feeds that fall
|
|
1437
|
+
* due together do not arrive together, and the same feed always lands at the same offset;
|
|
1438
|
+
* - submitting to Solana runs on its own, smaller limiter, pipelined behind the requests;
|
|
1439
|
+
* - a failed submit never discards the signed attestation the gateway returned (and quota paid for).
|
|
1440
|
+
*
|
|
1441
|
+
* Each request still has the single-request retry policy (backoff with jitter, `Retry-After`, a stale
|
|
1442
|
+
* registry refreshed once; see {@link retryDelayMs}).
|
|
1443
|
+
*/
|
|
1444
|
+
|
|
1445
|
+
/** One feed to update. */
|
|
1446
|
+
interface BulkFeed {
|
|
1447
|
+
apiConfig: APIConfig;
|
|
1448
|
+
signaturesRequired: number;
|
|
1449
|
+
/** Echoed in the result; for the caller's own bookkeeping. */
|
|
1450
|
+
label?: string;
|
|
1451
|
+
}
|
|
1452
|
+
interface BulkOptions {
|
|
1453
|
+
/**
|
|
1454
|
+
* Most gateway requests in flight. The limit adapts below this ceiling. Default: half the gateway's
|
|
1455
|
+
* advertised `maxInflightRounds` (at most 64), or 32 when it advertises none.
|
|
1456
|
+
*/
|
|
1457
|
+
concurrency?: number;
|
|
1458
|
+
/**
|
|
1459
|
+
* Spread request starts over this many ms by a hash of the feed's source id. Feeds that are due on
|
|
1460
|
+
* the same tick otherwise arrive together and queue at the gateway. Default 0 (no spreading).
|
|
1461
|
+
*/
|
|
1462
|
+
spreadMs?: number;
|
|
1463
|
+
/** Submit each attestation to Solana after its round. Default true. */
|
|
1464
|
+
submit?: boolean;
|
|
1465
|
+
/** Most Solana submits in flight. Default 8. */
|
|
1466
|
+
submitConcurrency?: number;
|
|
1467
|
+
/**
|
|
1468
|
+
* Options applied to every request (subscription owner, signer, `maxRetries`, `timeoutMs`, ...).
|
|
1469
|
+
* `apiConfig`, `signaturesRequired` and `context` are set per feed.
|
|
1470
|
+
*/
|
|
1471
|
+
request?: Omit<RequestSignedDataOptions, "apiConfig" | "signaturesRequired" | "context">;
|
|
1472
|
+
/** Called as each feed finishes, in completion order. */
|
|
1473
|
+
onResult?: (result: BulkResult) => void;
|
|
1474
|
+
/** Stops starting new feeds; those already started finish. */
|
|
1475
|
+
signal?: AbortSignal;
|
|
1476
|
+
}
|
|
1477
|
+
interface BulkResult {
|
|
1478
|
+
/** Position in the input array. */
|
|
1479
|
+
index: number;
|
|
1480
|
+
label?: string;
|
|
1481
|
+
/** The gateway round succeeded (submitting is reported separately in `submitError`). */
|
|
1482
|
+
ok: boolean;
|
|
1483
|
+
/** The signed attestation, whenever the round succeeded, including when the submit failed. */
|
|
1484
|
+
attestation?: Attestation;
|
|
1485
|
+
/** Transaction signature and feed account, when submitted. */
|
|
1486
|
+
signature?: string;
|
|
1487
|
+
feedAddress?: Address;
|
|
1488
|
+
/** Why the round failed. */
|
|
1489
|
+
error?: unknown;
|
|
1490
|
+
/** Why submitting failed after a successful round; `attestation` is still valid. */
|
|
1491
|
+
submitError?: unknown;
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* An adaptive concurrency limit: additive increase on success, multiplicative decrease on a busy
|
|
1495
|
+
* answer. Waiters are served in arrival order.
|
|
1496
|
+
*/
|
|
1497
|
+
declare class AdaptiveLimiter {
|
|
1498
|
+
private readonly max;
|
|
1499
|
+
private readonly now;
|
|
1500
|
+
private limit_;
|
|
1501
|
+
private inFlight;
|
|
1502
|
+
private successes;
|
|
1503
|
+
private lastCut;
|
|
1504
|
+
private readonly waiters;
|
|
1505
|
+
constructor(initial: number, max: number, now?: () => number);
|
|
1506
|
+
get limit(): number;
|
|
1507
|
+
acquire(): Promise<void>;
|
|
1508
|
+
/** Release a slot. `busy` reports that the gateway answered at capacity. */
|
|
1509
|
+
release(outcome: "ok" | "busy" | "other"): void;
|
|
1510
|
+
}
|
|
1511
|
+
/** Deterministic start offset for a feed: the same source id always lands at the same point. */
|
|
1512
|
+
declare function spreadOffsetMs(sourceIdHex: string, spreadMs: number): number;
|
|
1513
|
+
/**
|
|
1514
|
+
* Update many feeds. Results are returned in input order; a feed that fails does not stop the others.
|
|
1515
|
+
*/
|
|
1516
|
+
declare function requestMany(sdk: MolphaSDK, feeds: BulkFeed[], opts?: BulkOptions): Promise<BulkResult[]>;
|
|
1517
|
+
|
|
1293
1518
|
/**
|
|
1294
1519
|
* Vendored Molpha Anchor IDL (`target/idl/molpha.json` from the program repo).
|
|
1295
1520
|
*
|
|
@@ -1327,6 +1552,20 @@ interface MolphaSDKOptions {
|
|
|
1327
1552
|
idl?: Idl;
|
|
1328
1553
|
commitment?: Commitment;
|
|
1329
1554
|
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Thrown by {@link MolphaSDK.requestAndSubmit} when the gateway round succeeded but submitting the
|
|
1557
|
+
* attestation to Solana failed. The round consumed subscription quota and the signed attestation is
|
|
1558
|
+
* valid, so it is carried here: submit `error.result` again (it stays valid until its freshness
|
|
1559
|
+
* window passes, and re-submitting it is safe) instead of requesting, and paying for, a new round.
|
|
1560
|
+
*/
|
|
1561
|
+
declare class SubmitFailedError extends Error {
|
|
1562
|
+
/** The signed attestation the gateway returned. */
|
|
1563
|
+
readonly result: Attestation;
|
|
1564
|
+
readonly cause: unknown;
|
|
1565
|
+
constructor(
|
|
1566
|
+
/** The signed attestation the gateway returned. */
|
|
1567
|
+
result: Attestation, cause: unknown);
|
|
1568
|
+
}
|
|
1330
1569
|
declare class MolphaSDK {
|
|
1331
1570
|
readonly gateway: MolphaGateway;
|
|
1332
1571
|
readonly solana: MolphaSolanaClient;
|
|
@@ -1342,4 +1581,4 @@ declare class MolphaSDK {
|
|
|
1342
1581
|
}>;
|
|
1343
1582
|
}
|
|
1344
1583
|
|
|
1345
|
-
export { APIConfig, AggregationConfig, AggregationConfigError, AssetDomain, Attestation, type AttestationMessageFields, type BuildEvmVerifierArgsOptions, type BuildStarknetVerifierArgsOptions, type CoalitionKey, DEFAULT_GATEWAY_ENDPOINT, EIP712_DOMAIN_TYPEHASH, type Eip712Domain, type EvmAttestation, type EvmAttestationPayload, type EvmSchnorrSignature, EvmSigner, type EvmVerifierArgs, type EvmVerifyResult, type FeedAccount, type GatewayEndpoint, type GatewayEndpointInput, GatewayError, type GatewayInfo, INT256_MAX, INT256_MIN, MESSAGE_PREFIX, MIN_TOLERANCE_SIGNATURES, MOLPHA_IDL, MOLPHA_PROGRAM_ADDRESS, MOLPHA_PROGRAM_ID, MOLPHA_VERIFIER_ABI, MOLPHA_VERIFIER_ADDRESS, MOLPHA_VERIFIER_STARKNET_ADDRESSES, MOLPHA_VERIFIER_STARKNET_SEPOLIA, type MolphaEvmNetwork, MolphaGateway, type MolphaGatewayOptions, MolphaSDK, type MolphaSDKOptions, MolphaSolanaClient, type MolphaStarknetNetwork, MolphaWallet, Node, NodeKeyVerifier, NodeKeyVerifierArgs, NodesInfo, type PlanId, type PlanInfo, PlanType, REQUEST_AUTH_DOMAIN, RegistrySelectionConfig, type RegistryStateView, type RegistryView, type RequestAuthFields, type RequestSignedDataOptions, type RoundContext, type Secp256k1KeyInput, Signer, SourcePaymentOptions, type StarknetAttestation, type StarknetAttestationPayload, type StarknetFeltLike, type StarknetSchnorrSignature, type StarknetVerifierArgs, type StarknetVerifyResult, type SubmitAttestationArgs, type SubmitAttestationOptions, type SubmitResult, type SubscribeResult, type SubscriptionInfo, TRANSFER_WITH_AUTHORIZATION_TYPEHASH, type TransferAuthorization, UpstreamPaymentRequiredError, UpstreamQuote, UpstreamTerms, VERIFY_CODES, type VerifyCode, type VerifyCodeName, addressToBytes, assertAggregationQuorum, attestationMessageHash, attestationMessageHashFromAttestation, base64ToBytes, bigIntFromBytesBe, bitmapBitSet, bitmapToIndices, buildEvmVerifierArgs, buildStarknetVerifierArgs, buildSubmitAttestationArgs, bytesToBase64, bytesToHex, bytesToHex0x, canonicalizeAPIConfig, canonicalizeAggregation, commitmentAddressToStarknetFelt, computeCoalitionKey, concatBytes, createEvmSignerFromPrivateKey, decodeInt256, deriveGatewayPda, deriveGatewayPdaAddress, deriveGroupBitmap, deriveSelectionBitmap, deriveSelectionSeed, deriveSourceId, deriveSourceIdString, domainSeparator, effectiveSelectionSize, eligibleSetSize, encodeEvmVerifyCalldata, encodeInt256, encodeInt256Decimal, encodeRequestAuth, encodeStarknetVerifyCalldata, ensureLength, evmAddressFromPrivateKey, feedPda, formatInt256Decimal, gatewayPda, getMolphaStarknetVerifierAddress, hashRequestAuth, hexToBytes, nodePda, normalizeEndpoint, normalizeSecp256k1PublicKeyHex, parseEvmVerifyResult, parseGatewayInfo, parseStarknetVerifyResult, parseUpstreamQuote, planIdFromVariant, planPda, planVariant, probeSource, protocolConfigPda, registryPda, registryStatePda, resolveRemainingAccounts, secp256k1PublicKeyFromCoordinates, selectedIndices, signSourcePayments, signersBitmapToDecimal, signersBitmapToStarknetUint256, signersBitmapToUint256, subscriptionPda, toChecksumAddress, toFixedBytes, toFixedHex, transferWithAuthorizationDigest, transferWithAuthorizationHash, u256beFromBigInt, u32be, u32le, u64be, u64le, u8, utf8, validateSuppliedTerms, verifyCodeName };
|
|
1584
|
+
export { APIConfig, AdaptiveLimiter, AggregationConfig, AggregationConfigError, AssetDomain, Attestation, type AttestationMessageFields, type BuildEvmVerifierArgsOptions, type BuildStarknetVerifierArgsOptions, type BulkFeed, type BulkOptions, type BulkResult, type CoalitionKey, DEFAULT_GATEWAY_ENDPOINT, DEFAULT_MAX_RETRIES, DEFAULT_ROUND_TIMEOUT_MS, EIP712_DOMAIN_TYPEHASH, type Eip712Domain, type EvmAttestation, type EvmAttestationPayload, type EvmSchnorrSignature, EvmSigner, type EvmVerifierArgs, type EvmVerifyResult, type FeedAccount, type GatewayEndpoint, type GatewayEndpointInput, GatewayError, type GatewayInfo, INT256_MAX, INT256_MIN, MESSAGE_PREFIX, MIN_TOLERANCE_SIGNATURES, MOLPHA_IDL, MOLPHA_PROGRAM_ADDRESS, MOLPHA_PROGRAM_ID, MOLPHA_VERIFIER_ABI, MOLPHA_VERIFIER_ADDRESS, MOLPHA_VERIFIER_STARKNET_ADDRESSES, MOLPHA_VERIFIER_STARKNET_SEPOLIA, type MolphaEvmNetwork, MolphaGateway, type MolphaGatewayOptions, MolphaSDK, type MolphaSDKOptions, MolphaSolanaClient, type MolphaStarknetNetwork, MolphaWallet, Node, NodeKeyVerifier, NodeKeyVerifierArgs, NodesInfo, type PlanId, type PlanInfo, PlanType, REQUEST_AUTH_DOMAIN, RegistrySelectionConfig, type RegistryStateView, type RegistryView, type RequestAuthFields, type RequestSignedDataOptions, type RetryCause, type RoundContext, SELECTION_WINDOW_MS, type Secp256k1KeyInput, Signer, SourcePaymentOptions, type StarknetAttestation, type StarknetAttestationPayload, type StarknetFeltLike, type StarknetSchnorrSignature, type StarknetVerifierArgs, type StarknetVerifyResult, type SubmitAttestationArgs, type SubmitAttestationOptions, SubmitFailedError, type SubmitResult, type SubscribeResult, type SubscriptionInfo, TRANSFER_WITH_AUTHORIZATION_TYPEHASH, type TransferAuthorization, UpstreamPaymentRequiredError, UpstreamQuote, UpstreamTerms, VERIFY_CODES, type VerifyCode, type VerifyCodeName, addressToBytes, assertAggregationQuorum, attestationMessageHash, attestationMessageHashFromAttestation, base64ToBytes, bigIntFromBytesBe, bitmapBitSet, bitmapToIndices, buildEvmVerifierArgs, buildStarknetVerifierArgs, buildSubmitAttestationArgs, bytesToBase64, bytesToHex, bytesToHex0x, canonicalizeAPIConfig, canonicalizeAggregation, commitmentAddressToStarknetFelt, computeCoalitionKey, concatBytes, createEvmSignerFromPrivateKey, decodeInt256, deriveGatewayPda, deriveGatewayPdaAddress, deriveGroupBitmap, deriveSelectionBitmap, deriveSelectionSeed, deriveSourceId, deriveSourceIdString, domainSeparator, effectiveSelectionSize, eligibleSetSize, encodeEvmVerifyCalldata, encodeInt256, encodeInt256Decimal, encodeRequestAuth, encodeStarknetVerifyCalldata, ensureLength, estimateSubmitComputeUnits, evmAddressFromPrivateKey, feedPda, formatInt256Decimal, gatewayPda, getMolphaStarknetVerifierAddress, hashRequestAuth, hexToBytes, msUntilNextTick, nodePda, normalizeEndpoint, normalizeSecp256k1PublicKeyHex, parseEvmVerifyResult, parseGatewayInfo, parseStarknetVerifyResult, parseUpstreamQuote, planIdFromVariant, planPda, planVariant, probeSource, protocolConfigPda, registryPda, registryStatePda, requestMany, resolveRemainingAccounts, retryDelayMs, secp256k1PublicKeyFromCoordinates, selectedIndices, signSourcePayments, signersBitmapToDecimal, signersBitmapToStarknetUint256, signersBitmapToUint256, spreadOffsetMs, subscriptionPda, timestampAgeSeconds, timestampSeconds, toChecksumAddress, toFixedBytes, toFixedHex, transferWithAuthorizationDigest, transferWithAuthorizationHash, u256beFromBigInt, u32be, u32le, u64be, u64le, u8, utf8, validateSuppliedTerms, verifyCodeName };
|