@molpha/sdk 0.2.0-dev-20261008064918 → 0.2.0-dev-20261010184043

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { toPublicKey, addressBytes, toSolanaAddress, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ADDRESS, SYSTEM_PROGRAM_ADDRESS, setComputeUnitLimit, setComputeUnitPrice, addressFromBytes, findProgramAddressSync } from './chunk-H77BBZOL.js';
1
+ import { toPublicKey, addressBytes, setComputeUnitLimit, setComputeUnitPrice, SYSTEM_PROGRAM_ADDRESS, toSolanaAddress, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ADDRESS, addressFromBytes, findProgramAddressSync } from './chunk-H77BBZOL.js';
2
2
  import { getAddressEncoder, address, getProgramDerivedAddress } from '@solana/kit';
3
3
  import { keccak_256 } from '@noble/hashes/sha3.js';
4
4
  import { utf8ToBytes, hexToBytes as hexToBytes$1, concatBytes as concatBytes$1, bytesToHex as bytesToHex$1, randomBytes } from '@noble/hashes/utils.js';
5
5
  import { secp256k1 } from '@noble/curves/secp256k1.js';
6
6
  import { gcm } from '@noble/ciphers/aes.js';
7
- import { AnchorProvider, Program, web3 } from '@anchor-lang/core';
7
+ import { web3, AnchorProvider, Program } from '@anchor-lang/core';
8
8
  import BN from 'bn.js';
9
9
  import { ed25519 } from '@noble/curves/ed25519.js';
10
10
 
@@ -401,6 +401,17 @@ function deriveSelectionBitmap(sourceId, registryVersion, nodeCount, signaturesR
401
401
  const size = effectiveSelectionSize(signaturesRequired, redundancy, nodeCount);
402
402
  return deriveGroupBitmap(seed, nodeCount, size);
403
403
  }
404
+
405
+ // src/core/timestamp.ts
406
+ var ROUND_TICK_MS = 100;
407
+ function timestampSeconds(timestamp) {
408
+ const ms = typeof timestamp === "bigint" ? timestamp : BigInt(timestamp);
409
+ if (ms < 0n) throw new RangeError("timestamp must not be negative");
410
+ return Number(ms / 1000n);
411
+ }
412
+ function timestampAgeSeconds(timestamp, nowSeconds) {
413
+ return Math.max(0, nowSeconds - timestampSeconds(timestamp));
414
+ }
404
415
  var REQUEST_AUTH_DOMAIN = utf8("MOLPHA_REQAUTH_V1");
405
416
  function encodeRequestAuth(fields) {
406
417
  if (!Number.isInteger(fields.signaturesRequired) || fields.signaturesRequired < 1 || fields.signaturesRequired > 255) {
@@ -808,8 +819,6 @@ function parseGatewayInfo(data) {
808
819
  const info = { gatewayAuthority };
809
820
  if (programId !== void 0) info.programId = programId;
810
821
  const positive = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : void 0;
811
- const tickMs = positive(record.tickMs);
812
- if (tickMs !== void 0) info.tickMs = tickMs;
813
822
  const roundTimeoutSeconds = positive(record.roundTimeoutSeconds);
814
823
  if (roundTimeoutSeconds !== void 0) info.roundTimeoutSeconds = roundTimeoutSeconds;
815
824
  const maxInflightRounds = positive(record.maxInflightRounds);
@@ -820,26 +829,21 @@ function parseGatewayInfo(data) {
820
829
  // src/gateway/index.ts
821
830
  var ZERO_AUTH_SIG = new Uint8Array(64);
822
831
  var authTimestampNow = () => Math.floor(Date.now() / 1e3);
823
- var DEFAULT_TICK_MS = 1e3;
824
- function msUntilNextTick(nowMs, tickMs) {
825
- return tickMs - nowMs % tickMs + 1;
826
- }
827
- var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
832
+ var timerSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
833
+ var CONFLICT_JITTER_MS = 20;
828
834
  var BACKOFF_BASE_MS = 250;
829
835
  var BACKOFF_MAX_MS = 5e3;
830
836
  var DEFAULT_ROUND_TIMEOUT_MS = 35e3;
831
837
  var DEFAULT_MAX_RETRIES = 6;
832
- function retryDelayMs(cause, failures, nowMs, tickMs, random = Math.random) {
833
- const nextTick = msUntilNextTick(nowMs, tickMs);
838
+ function retryDelayMs(cause, failures, random = Math.random) {
839
+ const backoff = Math.min(BACKOFF_BASE_MS * 2 ** Math.max(failures - 1, 0), BACKOFF_MAX_MS);
834
840
  switch (cause.kind) {
835
841
  case "conflict":
836
- return nextTick + random() * (tickMs / 2);
842
+ return ROUND_TICK_MS + random() * CONFLICT_JITTER_MS;
837
843
  case "busy":
838
- return Math.max(nextTick, cause.retryAfterMs ?? tickMs) + random() * tickMs;
839
- case "error": {
840
- const backoff = Math.min(BACKOFF_BASE_MS * 2 ** Math.max(failures - 1, 0), BACKOFF_MAX_MS);
841
- return Math.max(nextTick, backoff / 2 + random() * (backoff / 2));
842
- }
844
+ return Math.max(cause.retryAfterMs ?? 0, backoff) + random() * backoff;
845
+ case "error":
846
+ return backoff / 2 + random() * (backoff / 2);
843
847
  }
844
848
  }
845
849
  function mergeCause(a, b) {
@@ -877,9 +881,8 @@ var MolphaGateway = class {
877
881
  programIdBytes;
878
882
  /** Gateway PDA per endpoint URL; resolved once per client lifetime. */
879
883
  gatewayPdas = /* @__PURE__ */ new Map();
880
- /** Advertised timing per endpoint URL, read lazily on the first retry. */
881
- advertisedInfo = /* @__PURE__ */ new Map();
882
884
  random;
885
+ sleep;
883
886
  constructor(endpoints, getRegistrySelectionConfig = async () => {
884
887
  throw new Error(
885
888
  "MolphaGateway requires getRegistrySelectionConfig to request signed data \u2014 pass the current on-chain registry version, redundancy buffer and node count (e.g. () => solana.getRegistrySelectionConfig())"
@@ -901,6 +904,7 @@ var MolphaGateway = class {
901
904
  this.programId = options.programId ?? MOLPHA_PROGRAM_ID;
902
905
  this.programIdBytes = addressToBytes(this.programId);
903
906
  this.random = options.random ?? Math.random;
907
+ this.sleep = options.sleep ?? timerSleep;
904
908
  }
905
909
  /** The configured gateway base URLs, in failover order. */
906
910
  endpointUrls() {
@@ -976,10 +980,13 @@ var MolphaGateway = class {
976
980
  * failover. The body is POSTed to each endpoint in order until one `completed`s.
977
981
  *
978
982
  * The round's `sourceId` is derived from `apiConfig`. The request carries no round timestamp:
979
- * the gateway assigns the round's `timestamp` (unix milliseconds) from its own clock
980
- * on a tick grid, and the committee follows from it. The result carries the assigned
981
- * timestamp and the signers' bitmap. A retry waits for a later tick, because a round that was
982
- * already reserved or dispatched cannot run again in the same one (HTTP 409).
983
+ * the gateway stamps the round with its own clock floored to the round tick (`timestamp`, unix
984
+ * milliseconds, a multiple of {@link ROUND_TICK_MS}), and the committee follows from it. The
985
+ * result carries the assigned timestamp and the signers' bitmap; the timestamp is taken as the
986
+ * gateway gave it. Requests for the same source, quorum and registry version inside one tick
987
+ * share one round. One consumer gets one round per tick per source and quorum: a second request
988
+ * in the tick is refused (HTTP 409) and retried one tick later. A retry is stamped anew, so it
989
+ * is a new round that spends another unit of round quota.
983
990
  *
984
991
  * The request is authorized by a `RequestAuth` signature (`authSig`) over the program id, the
985
992
  * endpoint's Gateway PDA, the source id, the quorum and `authTimestamp` (unix seconds, read
@@ -1066,7 +1073,6 @@ var MolphaGateway = class {
1066
1073
  }
1067
1074
  }
1068
1075
  let lastError;
1069
- let tickMs = opts.tickMs;
1070
1076
  let groupSize = effectiveSelectionSize(signaturesRequired, redundancyBuffer, nodeCount);
1071
1077
  let registryIndexes = Array.from({ length: nodeCount }, (_, index) => index);
1072
1078
  let cause = { kind: "error" };
@@ -1074,8 +1080,7 @@ var MolphaGateway = class {
1074
1080
  let retryNow = false;
1075
1081
  for (let attempt = 0; attempt < maxRetries; attempt++) {
1076
1082
  if (attempt > 0 && !retryNow) {
1077
- tickMs ??= await this.advertisedTickMs(timeoutMs) ?? DEFAULT_TICK_MS;
1078
- await sleep(retryDelayMs(cause, attempt, Date.now(), tickMs, this.random));
1083
+ await this.sleep(retryDelayMs(cause, attempt, this.random));
1079
1084
  }
1080
1085
  retryNow = false;
1081
1086
  cause = { kind: "error" };
@@ -1273,27 +1278,6 @@ var MolphaGateway = class {
1273
1278
  if (registry.nodeCount !== void 0) return registry;
1274
1279
  return { ...registry, nodes: await this.getNodes() };
1275
1280
  }
1276
- /**
1277
- * The gateway's advertised tick grid, read once per endpoint and only when a retry needs it. Any
1278
- * failure (an old gateway without `/v1/info`, a timeout) means "not advertised", so the caller
1279
- * falls back to the default; a failure is not cached.
1280
- */
1281
- async advertisedTickMs(timeoutMs) {
1282
- for (const endpoint of this.endpoints) {
1283
- let pending = this.advertisedInfo.get(endpoint.url);
1284
- if (!pending) {
1285
- pending = this.fetchGatewayInfo(endpoint, Math.min(timeoutMs, 3e3)).catch(() => void 0);
1286
- this.advertisedInfo.set(endpoint.url, pending);
1287
- }
1288
- const info = await pending;
1289
- if (info === void 0) {
1290
- this.advertisedInfo.delete(endpoint.url);
1291
- continue;
1292
- }
1293
- if (info.tickMs !== void 0) return info.tickMs;
1294
- }
1295
- return void 0;
1296
- }
1297
1281
  /** Gateway PDA bytes for an endpoint, cached per URL. A failed lookup is not cached. */
1298
1282
  resolveGatewayPda(endpoint, timeoutMs) {
1299
1283
  let pending = this.gatewayPdas.get(endpoint.url);
@@ -1630,7 +1614,7 @@ var molpha_default = {
1630
1614
  name: "molpha",
1631
1615
  version: "0.1.0",
1632
1616
  spec: "0.1.0",
1633
- description: "Molpha Oracle Solana Program - Merged from molpha-solana and molpha-feed"
1617
+ description: "Molpha Oracle Solana Program"
1634
1618
  },
1635
1619
  instructions: [
1636
1620
  {
@@ -3089,6 +3073,16 @@ var molpha_default = {
3089
3073
  writable: true,
3090
3074
  signer: true
3091
3075
  },
3076
+ {
3077
+ name: "program",
3078
+ docs: [
3079
+ "This program. Its account names the ProgramData account holding the upgrade authority."
3080
+ ],
3081
+ address: "chivcFQgxzwkpLvW41PV431HQ4dYpaW3povQH3AdpQt"
3082
+ },
3083
+ {
3084
+ name: "program_data"
3085
+ },
3092
3086
  {
3093
3087
  name: "token_program",
3094
3088
  address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
@@ -5736,19 +5730,6 @@ var molpha_default = {
5736
5730
  84
5737
5731
  ]
5738
5732
  },
5739
- {
5740
- name: "DelegateStatusChanged",
5741
- discriminator: [
5742
- 188,
5743
- 202,
5744
- 137,
5745
- 41,
5746
- 54,
5747
- 213,
5748
- 14,
5749
- 92
5750
- ]
5751
- },
5752
5733
  {
5753
5734
  name: "EpochClosed",
5754
5735
  discriminator: [
@@ -6611,6 +6592,16 @@ var molpha_default = {
6611
6592
  code: 6101,
6612
6593
  name: "InvalidInitialTau",
6613
6594
  msg: "initial_tau is below the minimum ticket threshold"
6595
+ },
6596
+ {
6597
+ code: 6102,
6598
+ name: "InvalidProgramData",
6599
+ msg: "program data account is not this program's"
6600
+ },
6601
+ {
6602
+ code: 6103,
6603
+ name: "NotUpgradeAuthority",
6604
+ msg: "initialize must be signed by the program's upgrade authority"
6614
6605
  }
6615
6606
  ],
6616
6607
  types: [
@@ -6693,6 +6684,9 @@ var molpha_default = {
6693
6684
  },
6694
6685
  {
6695
6686
  name: "timestamp",
6687
+ docs: [
6688
+ "Gateway-assigned round time in unix **milliseconds**."
6689
+ ],
6696
6690
  type: "u64"
6697
6691
  }
6698
6692
  ]
@@ -6908,34 +6902,6 @@ var molpha_default = {
6908
6902
  ]
6909
6903
  }
6910
6904
  },
6911
- {
6912
- name: "DelegateStatusChanged",
6913
- type: {
6914
- kind: "struct",
6915
- fields: [
6916
- {
6917
- name: "delegate",
6918
- type: "pubkey"
6919
- },
6920
- {
6921
- name: "owner",
6922
- type: "pubkey"
6923
- },
6924
- {
6925
- name: "old_status",
6926
- type: "u8"
6927
- },
6928
- {
6929
- name: "new_status",
6930
- type: "u8"
6931
- },
6932
- {
6933
- name: "updated_at",
6934
- type: "i64"
6935
- }
6936
- ]
6937
- }
6938
- },
6939
6905
  {
6940
6906
  name: "EpochClosed",
6941
6907
  type: {
@@ -7344,6 +7310,9 @@ var molpha_default = {
7344
7310
  },
7345
7311
  {
7346
7312
  name: "timestamp",
7313
+ docs: [
7314
+ "Unix milliseconds. Updates are strictly ordered on it, so two rounds in one second order."
7315
+ ],
7347
7316
  type: "u64"
7348
7317
  },
7349
7318
  {
@@ -9501,11 +9470,85 @@ function estimateSubmitComputeUnits(signerCount) {
9501
9470
  const measured = 43e3 + 9200 * signerCount;
9502
9471
  return Math.min(Math.round(measured * 1.15) + 1e4, MAX_COMPUTE_UNIT_LIMIT);
9503
9472
  }
9473
+ function estimateSubmitBatchComputeUnits(signerCounts) {
9474
+ if (signerCounts.length === 0 || signerCounts.some((n) => !Number.isInteger(n) || n < 1)) {
9475
+ return MAX_COMPUTE_UNIT_LIMIT;
9476
+ }
9477
+ const measured = signerCounts.reduce((sum, n) => sum + 43e3 + 9200 * n, 0);
9478
+ return Math.min(Math.round(measured * 1.15) + 1e4, MAX_COMPUTE_UNIT_LIMIT);
9479
+ }
9480
+ var SUBMIT_INSTRUCTION_DATA_BYTES = 234;
9481
+ var PLACEHOLDER_BLOCKHASH = "11111111111111111111111111111111";
9482
+ var shortVecBytes = (n) => n < 128 ? 1 : n < 16384 ? 2 : 3;
9483
+ function transactionSize(payer, instructions) {
9484
+ const tx = new web3.Transaction();
9485
+ tx.feePayer = payer;
9486
+ tx.recentBlockhash = PLACEHOLDER_BLOCKHASH;
9487
+ tx.add(...instructions);
9488
+ const message = tx.compileMessage();
9489
+ const keys = message.accountKeys.length;
9490
+ let size = 1 + 64 + 3 + shortVecBytes(keys) + 32 * keys + 32 + shortVecBytes(message.instructions.length);
9491
+ message.instructions.forEach((compiled, i) => {
9492
+ const dataBytes = instructions[i].data.length;
9493
+ size += 1 + shortVecBytes(compiled.accounts.length) + compiled.accounts.length + shortVecBytes(dataBytes) + dataBytes;
9494
+ });
9495
+ return size;
9496
+ }
9497
+ function estimateSubmitTransactionSize(count, signerCount, opts = {}) {
9498
+ const key = () => web3.Keypair.generate().publicKey;
9499
+ const [payer, registry, feed, protocolConfig, program] = [key(), key(), key(), key(), key()];
9500
+ const distinct = Math.max(signerCount, opts.distinctSigners ?? signerCount);
9501
+ const nodes = Array.from({ length: distinct }, key);
9502
+ const instructions = [setComputeUnitLimit(1)];
9503
+ if (opts.priorityFee) instructions.push(setComputeUnitPrice(1));
9504
+ for (let i = 0; i < count; i++) {
9505
+ instructions.push(
9506
+ new web3.TransactionInstruction({
9507
+ programId: program,
9508
+ keys: [
9509
+ { pubkey: payer, isSigner: true, isWritable: true },
9510
+ { pubkey: registry, isSigner: false, isWritable: false },
9511
+ { pubkey: feed, isSigner: false, isWritable: true },
9512
+ { pubkey: protocolConfig, isSigner: false, isWritable: false },
9513
+ { pubkey: new web3.PublicKey(SYSTEM_PROGRAM_ADDRESS), isSigner: false, isWritable: false },
9514
+ ...Array.from({ length: signerCount }, (_, j) => ({
9515
+ pubkey: nodes[(i * signerCount + j) % distinct],
9516
+ isSigner: false,
9517
+ isWritable: false
9518
+ }))
9519
+ ],
9520
+ data: Buffer.alloc(SUBMIT_INSTRUCTION_DATA_BYTES)
9521
+ })
9522
+ );
9523
+ }
9524
+ return transactionSize(payer, instructions);
9525
+ }
9526
+ function maxAttestationsPerTransaction(signerCount, opts = {}) {
9527
+ let count = 0;
9528
+ while (estimateSubmitTransactionSize(count + 1, signerCount, opts) <= web3.PACKET_DATA_SIZE) count++;
9529
+ return count;
9530
+ }
9504
9531
  var REGISTRY_CACHE_MS = 3e4;
9505
9532
  var KEY_CACHE_LIMIT = 8192;
9506
9533
  var PRIORITY_FEE_CACHE_MS = 5e3;
9507
9534
  var AUTO_FEE_PERCENTILE = 0.75;
9508
9535
  var AUTO_FEE_CAP_MICRO_LAMPORTS = 1e6;
9536
+ var BatchTooLargeError = class extends RangeError {
9537
+ constructor(fits, size, limit, count) {
9538
+ super(
9539
+ `${count} attestations need a ${size} byte transaction, over the ${limit} byte limit; ${fits} fit`
9540
+ );
9541
+ this.fits = fits;
9542
+ this.size = size;
9543
+ this.limit = limit;
9544
+ this.count = count;
9545
+ this.name = "BatchTooLargeError";
9546
+ }
9547
+ fits;
9548
+ size;
9549
+ limit;
9550
+ count;
9551
+ };
9509
9552
  var MolphaSolanaClient = class _MolphaSolanaClient {
9510
9553
  constructor(program, provider, programId) {
9511
9554
  this.program = program;
@@ -9677,6 +9720,87 @@ var MolphaSolanaClient = class _MolphaSolanaClient {
9677
9720
  * `keccak256(rawValue)`; {@link buildSubmitAttestationArgs} validates that before send.
9678
9721
  */
9679
9722
  async submitAttestation(attestation, opts) {
9723
+ const { args, accounts, remaining, feed } = await this.prepareSubmit(attestation, opts);
9724
+ const preInstructions = [
9725
+ setComputeUnitLimit(opts?.computeUnitLimit ?? estimateSubmitComputeUnits(remaining.length))
9726
+ ];
9727
+ const price = await this.resolvePriorityFee(opts?.priorityFeeMicroLamports, feed);
9728
+ if (price > 0) preInstructions.push(setComputeUnitPrice(price));
9729
+ const signature = await this.methods.submitAttestation(args).accountsPartial(accounts).remainingAccounts(remaining).preInstructions(preInstructions).rpc();
9730
+ return { signature, feed };
9731
+ }
9732
+ /**
9733
+ * Submit several attestations of one feed in one transaction.
9734
+ *
9735
+ * Each becomes its own `submit_attestation` instruction, in timestamp order, and instructions run
9736
+ * in the order they are listed: all of them are applied, oldest first, whatever order other
9737
+ * transactions reach the leader in. That is what separate submits cannot promise. Transactions sent
9738
+ * milliseconds apart for one feed are overtaken by a newer one often enough (about a third at 250 ms
9739
+ * spacing in a devnet run) that the older one fails with `FeedNotNewer`; a batch makes the spacing
9740
+ * between transactions several times longer and spends one fee and one signature for them all.
9741
+ *
9742
+ * The transaction is atomic: if one instruction fails (typically because a newer attestation
9743
+ * of the feed landed first, so every instruction is stale) none of them applies. Batch only what
9744
+ * is due together, and keep batches of one feed in the order they were made.
9745
+ *
9746
+ * All attestations must be for one feed (the same `sourceId` and `signaturesRequired`) with
9747
+ * distinct timestamps. They need not share a registry version or a signer set. Values longer than
9748
+ * 32 bytes (`rawValue`) are not supported here: submit those with {@link submitAttestation}.
9749
+ *
9750
+ * @throws {BatchTooLargeError} when they do not fit in one transaction (about three do with
9751
+ * three signers; see {@link maxAttestationsPerTransaction}). Nothing is sent.
9752
+ */
9753
+ async submitAttestations(attestations, opts) {
9754
+ if (attestations.length === 0) {
9755
+ throw new RangeError("submitAttestations needs at least one attestation");
9756
+ }
9757
+ const sorted = [...attestations].sort((a, b) => a.payload.timestamp - b.payload.timestamp);
9758
+ const feedKey = (a) => `${bytesToHex(toFixedBytes(a.payload.sourceId, 32, "sourceId"))}:${a.payload.signaturesRequired}`;
9759
+ const first = feedKey(sorted[0]);
9760
+ sorted.forEach((a, i) => {
9761
+ if (feedKey(a) !== first) {
9762
+ throw new RangeError(
9763
+ "submitAttestations: every attestation must be for the same feed (sourceId and signaturesRequired)"
9764
+ );
9765
+ }
9766
+ if (i > 0 && a.payload.timestamp === sorted[i - 1].payload.timestamp) {
9767
+ throw new RangeError(
9768
+ `submitAttestations: two attestations have timestamp ${a.payload.timestamp}; the second would be refused as not newer`
9769
+ );
9770
+ }
9771
+ });
9772
+ if (sorted.length === 1) return { ...await this.submitAttestation(sorted[0], opts), count: 1 };
9773
+ const prepared = await Promise.all(sorted.map((a) => this.prepareSubmit(a)));
9774
+ const instructions = await Promise.all(
9775
+ prepared.map(
9776
+ (p) => this.methods.submitAttestation(p.args).accountsPartial(p.accounts).remainingAccounts(p.remaining).instruction()
9777
+ )
9778
+ );
9779
+ const feed = prepared[0].feed;
9780
+ const budget = [
9781
+ setComputeUnitLimit(
9782
+ opts?.computeUnitLimit ?? estimateSubmitBatchComputeUnits(prepared.map((p) => p.remaining.length))
9783
+ )
9784
+ ];
9785
+ const price = await this.resolvePriorityFee(opts?.priorityFeeMicroLamports, feed);
9786
+ if (price > 0) budget.push(setComputeUnitPrice(price));
9787
+ const payer = this.provider.wallet.publicKey;
9788
+ const size = transactionSize(payer, [...budget, ...instructions]);
9789
+ if (size > web3.PACKET_DATA_SIZE) {
9790
+ let fits = 0;
9791
+ while (fits < instructions.length && transactionSize(payer, [...budget, ...instructions.slice(0, fits + 1)]) <= web3.PACKET_DATA_SIZE) {
9792
+ fits++;
9793
+ }
9794
+ throw new BatchTooLargeError(fits, size, web3.PACKET_DATA_SIZE, instructions.length);
9795
+ }
9796
+ const signature = await this.provider.sendAndConfirm(new web3.Transaction().add(...budget, ...instructions));
9797
+ return { signature, feed, count: instructions.length };
9798
+ }
9799
+ /**
9800
+ * Everything one `submit_attestation` instruction needs: the arguments, the named accounts, the
9801
+ * signer `Node` accounts (ascending bit order) and the feed address.
9802
+ */
9803
+ async prepareSubmit(attestation, opts) {
9680
9804
  const { payload, signature: schnorr } = attestation;
9681
9805
  const sourceId = toFixedBytes(payload.sourceId, 32, "sourceId");
9682
9806
  const submitter = this.wallet;
@@ -9685,21 +9809,18 @@ var MolphaSolanaClient = class _MolphaSolanaClient {
9685
9809
  assertSignerCount(remaining.length, payload.signaturesRequired, registry);
9686
9810
  const coalitionKey = opts?.coalitionKey ?? await this.computeSignerCoalitionKey(remaining, registry, schnorr.signersBitmap);
9687
9811
  const feed = feedPda(sourceId, payload.signaturesRequired, submitter, this.programId);
9688
- const preInstructions = [
9689
- setComputeUnitLimit(opts?.computeUnitLimit ?? estimateSubmitComputeUnits(remaining.length))
9690
- ];
9691
- const price = await this.resolvePriorityFee(opts?.priorityFeeMicroLamports, feed);
9692
- if (price > 0) preInstructions.push(setComputeUnitPrice(price));
9693
- const signature = await this.methods.submitAttestation(
9694
- buildSubmitAttestationArgs(attestation, coalitionKey, opts?.rawValue)
9695
- ).accountsPartial({
9696
- submitter,
9697
- registry: registryPda(payload.registryVersion, this.programId),
9698
- feed,
9699
- protocolConfig: protocolConfigPda(this.programId),
9700
- systemProgram: SYSTEM_PROGRAM_ADDRESS
9701
- }).remainingAccounts(remaining).preInstructions(preInstructions).rpc();
9702
- return { signature, feed };
9812
+ return {
9813
+ args: buildSubmitAttestationArgs(attestation, coalitionKey, opts?.rawValue),
9814
+ accounts: {
9815
+ submitter,
9816
+ registry: registryPda(payload.registryVersion, this.programId),
9817
+ feed,
9818
+ protocolConfig: protocolConfigPda(this.programId),
9819
+ systemProgram: SYSTEM_PROGRAM_ADDRESS
9820
+ },
9821
+ remaining,
9822
+ feed
9823
+ };
9703
9824
  }
9704
9825
  /** The registry for `version`, reused for {@link REGISTRY_CACHE_MS}. */
9705
9826
  fetchRegistryCached(version) {
@@ -10024,16 +10145,6 @@ function attestationMessageHashFromAttestation(attestation) {
10024
10145
  });
10025
10146
  }
10026
10147
 
10027
- // src/core/timestamp.ts
10028
- function timestampSeconds(timestamp) {
10029
- const ms = typeof timestamp === "bigint" ? timestamp : BigInt(timestamp);
10030
- if (ms < 0n) throw new RangeError("timestamp must not be negative");
10031
- return Number(ms / 1000n);
10032
- }
10033
- function timestampAgeSeconds(timestamp, nowSeconds) {
10034
- return Math.max(0, nowSeconds - timestampSeconds(timestamp));
10035
- }
10036
-
10037
10148
  // src/core/verifyCodes.ts
10038
10149
  var VERIFY_CODES = {
10039
10150
  OK: 0,
@@ -10632,6 +10743,6 @@ var MolphaSDK = class {
10632
10743
  }
10633
10744
  };
10634
10745
 
10635
- export { AdaptiveLimiter, AggregationConfigError, DEFAULT_GATEWAY_ENDPOINT, DEFAULT_MAX_RETRIES, DEFAULT_ROUND_TIMEOUT_MS, EIP712_DOMAIN_TYPEHASH, GatewayError, INT256_MAX, INT256_MIN, MESSAGE_PREFIX, MIN_TOLERANCE_SIGNATURES, MOLPHA_DEV_VERIFIERS_PROVISIONAL, MOLPHA_IDL, MOLPHA_PROGRAM_ADDRESS, MOLPHA_PROGRAM_ID, MOLPHA_SDK_PROFILE, MOLPHA_VERIFIER_ABI, MOLPHA_VERIFIER_ADDRESS, MOLPHA_VERIFIER_STARKNET_ADDRESSES, MOLPHA_VERIFIER_STARKNET_SEPOLIA, MolphaGateway, MolphaSDK, MolphaSolanaClient, PlanType, REQUEST_AUTH_DOMAIN, SELECTION_WINDOW_MS, SubmitFailedError, TRANSFER_WITH_AUTHORIZATION_TYPEHASH, UpstreamPaymentRequiredError, VERIFY_CODES, 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, gatewaySignerFromWallet, getMolphaStarknetVerifierAddress, hashRequestAuth, hexToBytes, msUntilNextTick, nodePda, normalizeEndpoint, normalizeSecp256k1PublicKeyHex, parseEvmVerifyResult, parseGatewayInfo, parseStarknetVerifyResult, parseUpstreamQuote, planIdFromVariant, planPda, planVariant, probeSource, protocolConfigPda, registryPda, registryStatePda, requestMany, resolveRemainingAccounts, retryDelayMs, secp256k1PublicKeyFromCoordinates, selectedIndices, signSourcePayments, signerFromKeypair, signersBitmapToDecimal, signersBitmapToStarknetUint256, signersBitmapToUint256, spreadOffsetMs, subscriptionPda, timestampAgeSeconds, timestampSeconds, toChecksumAddress, toFixedBytes, toFixedHex, transferWithAuthorizationDigest, transferWithAuthorizationHash, u256beFromBigInt, u32be, u32le, u64be, u64le, u8, utf8, validateSuppliedTerms, verifyCodeName };
10746
+ export { AdaptiveLimiter, AggregationConfigError, BatchTooLargeError, DEFAULT_GATEWAY_ENDPOINT, DEFAULT_MAX_RETRIES, DEFAULT_ROUND_TIMEOUT_MS, EIP712_DOMAIN_TYPEHASH, GatewayError, INT256_MAX, INT256_MIN, MESSAGE_PREFIX, MIN_TOLERANCE_SIGNATURES, MOLPHA_DEV_VERIFIERS_PROVISIONAL, MOLPHA_IDL, MOLPHA_PROGRAM_ADDRESS, MOLPHA_PROGRAM_ID, MOLPHA_SDK_PROFILE, MOLPHA_VERIFIER_ABI, MOLPHA_VERIFIER_ADDRESS, MOLPHA_VERIFIER_STARKNET_ADDRESSES, MOLPHA_VERIFIER_STARKNET_SEPOLIA, MolphaGateway, MolphaSDK, MolphaSolanaClient, PlanType, REQUEST_AUTH_DOMAIN, ROUND_TICK_MS, SELECTION_WINDOW_MS, SUBMIT_INSTRUCTION_DATA_BYTES, SubmitFailedError, TRANSFER_WITH_AUTHORIZATION_TYPEHASH, UpstreamPaymentRequiredError, VERIFY_CODES, 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, estimateSubmitBatchComputeUnits, estimateSubmitComputeUnits, estimateSubmitTransactionSize, evmAddressFromPrivateKey, feedPda, formatInt256Decimal, gatewayPda, gatewaySignerFromWallet, getMolphaStarknetVerifierAddress, hashRequestAuth, hexToBytes, maxAttestationsPerTransaction, nodePda, normalizeEndpoint, normalizeSecp256k1PublicKeyHex, parseEvmVerifyResult, parseGatewayInfo, parseStarknetVerifyResult, parseUpstreamQuote, planIdFromVariant, planPda, planVariant, probeSource, protocolConfigPda, registryPda, registryStatePda, requestMany, resolveRemainingAccounts, retryDelayMs, secp256k1PublicKeyFromCoordinates, selectedIndices, signSourcePayments, signerFromKeypair, signersBitmapToDecimal, signersBitmapToStarknetUint256, signersBitmapToUint256, spreadOffsetMs, subscriptionPda, timestampAgeSeconds, timestampSeconds, toChecksumAddress, toFixedBytes, toFixedHex, transferWithAuthorizationDigest, transferWithAuthorizationHash, u256beFromBigInt, u32be, u32le, u64be, u64le, u8, utf8, validateSuppliedTerms, verifyCodeName };
10636
10747
  //# sourceMappingURL=index.js.map
10637
10748
  //# sourceMappingURL=index.js.map