@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.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { toPublicKey, addressBytes, toSolanaAddress, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ADDRESS, SYSTEM_PROGRAM_ADDRESS, setComputeUnitLimit, addressFromBytes, findProgramAddressSync } from './chunk-
|
|
1
|
+
import { toPublicKey, addressBytes, toSolanaAddress, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ADDRESS, SYSTEM_PROGRAM_ADDRESS, setComputeUnitLimit, setComputeUnitPrice, 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 } from '@anchor-lang/core';
|
|
7
|
+
import { AnchorProvider, Program, web3 } from '@anchor-lang/core';
|
|
8
8
|
import BN from 'bn.js';
|
|
9
9
|
import { ed25519 } from '@noble/curves/ed25519.js';
|
|
10
10
|
|
|
@@ -313,18 +313,19 @@ function secp256k1PublicKeyFromCoordinates(x, y, label = "secp256k1 public key c
|
|
|
313
313
|
}
|
|
314
314
|
var SELECTION_SEED_DOMAIN = keccak_256(utf8("MOLPHA_SELECTION_V1"));
|
|
315
315
|
var SELECTION_DERIVE_DOMAIN = keccak_256(utf8("MOLPHA_SELECTION_DERIVE"));
|
|
316
|
+
var SELECTION_WINDOW_MS = 1000n;
|
|
316
317
|
var MAX_ROUNDS = 65536;
|
|
317
318
|
var BITMAP_BYTES = 32;
|
|
318
319
|
var MAX_NODES = BITMAP_BYTES * 8;
|
|
319
320
|
var U32_MAX = 4294967295;
|
|
320
|
-
function deriveSelectionSeed(sourceId, registryVersion,
|
|
321
|
+
function deriveSelectionSeed(sourceId, registryVersion, timestamp) {
|
|
321
322
|
ensureLength(sourceId, 32, "sourceId");
|
|
322
323
|
return keccak_256(
|
|
323
324
|
concatBytes(
|
|
324
325
|
SELECTION_SEED_DOMAIN,
|
|
325
326
|
sourceId,
|
|
326
327
|
u32be(registryVersion),
|
|
327
|
-
u64be(
|
|
328
|
+
u64be(BigInt(timestamp) / SELECTION_WINDOW_MS)
|
|
328
329
|
)
|
|
329
330
|
);
|
|
330
331
|
}
|
|
@@ -390,7 +391,7 @@ function deriveGroupBitmap(seed, nodeCount, groupSize) {
|
|
|
390
391
|
}
|
|
391
392
|
return bitmap;
|
|
392
393
|
}
|
|
393
|
-
function deriveSelectionBitmap(sourceId, registryVersion, nodeCount, signaturesRequired, redundancy = 0, ts =
|
|
394
|
+
function deriveSelectionBitmap(sourceId, registryVersion, nodeCount, signaturesRequired, redundancy = 0, ts = Date.now()) {
|
|
394
395
|
const seed = deriveSelectionSeed(sourceId, registryVersion, ts);
|
|
395
396
|
const size = effectiveSelectionSize(signaturesRequired, redundancy, nodeCount);
|
|
396
397
|
return deriveGroupBitmap(seed, nodeCount, size);
|
|
@@ -405,7 +406,7 @@ function encodeRequestAuth(fields) {
|
|
|
405
406
|
ensureLength(fields.gateway, 32, "gateway"),
|
|
406
407
|
toFixedBytes(fields.sourceId, 32, "sourceId"),
|
|
407
408
|
Uint8Array.of(fields.signaturesRequired),
|
|
408
|
-
u64le(fields.
|
|
409
|
+
u64le(fields.authTimestamp)
|
|
409
410
|
);
|
|
410
411
|
}
|
|
411
412
|
function hashRequestAuth(fields) {
|
|
@@ -774,11 +775,57 @@ function parseGatewayInfo(data) {
|
|
|
774
775
|
if (programId !== void 0 && typeof programId !== "string") {
|
|
775
776
|
throw new Error("GET /v1/info programId must be a base58 string");
|
|
776
777
|
}
|
|
777
|
-
|
|
778
|
+
const info = { gatewayAuthority };
|
|
779
|
+
if (programId !== void 0) info.programId = programId;
|
|
780
|
+
const positive = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : void 0;
|
|
781
|
+
const tickMs = positive(record.tickMs);
|
|
782
|
+
if (tickMs !== void 0) info.tickMs = tickMs;
|
|
783
|
+
const roundTimeoutSeconds = positive(record.roundTimeoutSeconds);
|
|
784
|
+
if (roundTimeoutSeconds !== void 0) info.roundTimeoutSeconds = roundTimeoutSeconds;
|
|
785
|
+
const maxInflightRounds = positive(record.maxInflightRounds);
|
|
786
|
+
if (maxInflightRounds !== void 0) info.maxInflightRounds = maxInflightRounds;
|
|
787
|
+
return info;
|
|
778
788
|
}
|
|
779
789
|
|
|
780
790
|
// src/gateway/index.ts
|
|
781
791
|
var ZERO_AUTH_SIG = new Uint8Array(64);
|
|
792
|
+
var authTimestampNow = () => Math.floor(Date.now() / 1e3);
|
|
793
|
+
var DEFAULT_TICK_MS = 1e3;
|
|
794
|
+
function msUntilNextTick(nowMs, tickMs) {
|
|
795
|
+
return tickMs - nowMs % tickMs + 1;
|
|
796
|
+
}
|
|
797
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
798
|
+
var BACKOFF_BASE_MS = 250;
|
|
799
|
+
var BACKOFF_MAX_MS = 5e3;
|
|
800
|
+
var DEFAULT_ROUND_TIMEOUT_MS = 35e3;
|
|
801
|
+
var DEFAULT_MAX_RETRIES = 6;
|
|
802
|
+
function retryDelayMs(cause, failures, nowMs, tickMs, random = Math.random) {
|
|
803
|
+
const nextTick = msUntilNextTick(nowMs, tickMs);
|
|
804
|
+
switch (cause.kind) {
|
|
805
|
+
case "conflict":
|
|
806
|
+
return nextTick + random() * (tickMs / 2);
|
|
807
|
+
case "busy":
|
|
808
|
+
return Math.max(nextTick, cause.retryAfterMs ?? tickMs) + random() * tickMs;
|
|
809
|
+
case "error": {
|
|
810
|
+
const backoff = Math.min(BACKOFF_BASE_MS * 2 ** Math.max(failures - 1, 0), BACKOFF_MAX_MS);
|
|
811
|
+
return Math.max(nextTick, backoff / 2 + random() * (backoff / 2));
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function mergeCause(a, b) {
|
|
816
|
+
if (a.kind === "busy" || b.kind === "busy") {
|
|
817
|
+
const waits = [a, b].flatMap((c) => c.kind === "busy" && c.retryAfterMs !== void 0 ? [c.retryAfterMs] : []);
|
|
818
|
+
return waits.length ? { kind: "busy", retryAfterMs: Math.max(...waits) } : { kind: "busy" };
|
|
819
|
+
}
|
|
820
|
+
if (a.kind === "conflict" || b.kind === "conflict") return { kind: "conflict" };
|
|
821
|
+
return { kind: "error" };
|
|
822
|
+
}
|
|
823
|
+
function retryAfterMs(res) {
|
|
824
|
+
const raw = res.headers.get("retry-after");
|
|
825
|
+
if (raw === null) return void 0;
|
|
826
|
+
const seconds = Number(raw);
|
|
827
|
+
return Number.isFinite(seconds) && seconds >= 0 ? Math.min(seconds, 60) * 1e3 : void 0;
|
|
828
|
+
}
|
|
782
829
|
var DEFAULT_GATEWAY_ENDPOINT = "https://dev-gateway.molpha.io/";
|
|
783
830
|
var GatewayError = class extends Error {
|
|
784
831
|
constructor(message, status) {
|
|
@@ -801,6 +848,9 @@ var MolphaGateway = class {
|
|
|
801
848
|
programIdBytes;
|
|
802
849
|
/** Gateway PDA per endpoint URL; resolved once per client lifetime. */
|
|
803
850
|
gatewayPdas = /* @__PURE__ */ new Map();
|
|
851
|
+
/** Advertised timing per endpoint URL, read lazily on the first retry. */
|
|
852
|
+
advertisedInfo = /* @__PURE__ */ new Map();
|
|
853
|
+
random;
|
|
804
854
|
constructor(endpoints, getRegistrySelectionConfig = async () => {
|
|
805
855
|
throw new Error(
|
|
806
856
|
"MolphaGateway requires getRegistrySelectionConfig to request signed data \u2014 pass the current on-chain registry version, redundancy buffer and node count (e.g. () => solana.getRegistrySelectionConfig())"
|
|
@@ -821,6 +871,11 @@ var MolphaGateway = class {
|
|
|
821
871
|
this.allowUnverifiedNodeKeysForPrivateApi = options.allowUnverifiedNodeKeysForPrivateApi ?? false;
|
|
822
872
|
this.programId = options.programId ?? MOLPHA_PROGRAM_ID;
|
|
823
873
|
this.programIdBytes = addressToBytes(this.programId);
|
|
874
|
+
this.random = options.random ?? Math.random;
|
|
875
|
+
}
|
|
876
|
+
/** The configured gateway base URLs, in failover order. */
|
|
877
|
+
endpointUrls() {
|
|
878
|
+
return this.endpoints.map((e) => e.url);
|
|
824
879
|
}
|
|
825
880
|
/** Tries endpoints in order; returns the first node list it can fetch. */
|
|
826
881
|
async getNodes() {
|
|
@@ -831,13 +886,12 @@ var MolphaGateway = class {
|
|
|
831
886
|
* selection policy, which sizes the eligible set a paid source must fund.
|
|
832
887
|
*
|
|
833
888
|
* The `registry` block is advisory: it is whatever the gateway read from the
|
|
834
|
-
* chain, and is absent
|
|
889
|
+
* chain, and is absent when that read failed. Prefer the
|
|
835
890
|
* on-chain read (`MolphaSolanaClient.getRegistrySelectionConfig`) whenever a
|
|
836
891
|
* Solana connection is available — `requestSignedData` already does.
|
|
837
892
|
*/
|
|
838
893
|
async getNodesInfo() {
|
|
839
894
|
const data = await this.firstReachableData("/v1/nodes");
|
|
840
|
-
if (Array.isArray(data)) return { nodes: data };
|
|
841
895
|
return {
|
|
842
896
|
nodes: data.nodes,
|
|
843
897
|
...data.registry ? { registry: data.registry } : {}
|
|
@@ -890,12 +944,23 @@ var MolphaGateway = class {
|
|
|
890
944
|
}
|
|
891
945
|
/**
|
|
892
946
|
* Request a threshold-signed data update from the gateway, with retry +
|
|
893
|
-
* failover.
|
|
894
|
-
*
|
|
947
|
+
* failover. The body is POSTed to each endpoint in order until one `completed`s.
|
|
948
|
+
*
|
|
949
|
+
* The round's `sourceId` is derived from `apiConfig`. The request carries no round timestamp:
|
|
950
|
+
* the gateway assigns the round's `timestamp` (unix milliseconds) from its own clock
|
|
951
|
+
* on a tick grid, and the committee follows from it. The result carries the assigned
|
|
952
|
+
* timestamp and the signers' bitmap. A retry waits for a later tick, because a round that was
|
|
953
|
+
* already reserved or dispatched cannot run again in the same one (HTTP 409).
|
|
954
|
+
*
|
|
955
|
+
* The request is authorized by a `RequestAuth` signature (`authSig`) over the program id, the
|
|
956
|
+
* endpoint's Gateway PDA, the source id, the quorum and `authTimestamp` (unix seconds, read
|
|
957
|
+
* from the local clock for every attempt). It only proves the caller may spend the
|
|
958
|
+
* subscription's rounds; it is not part of the round, so the signature is recomputed for every
|
|
959
|
+
* endpoint tried.
|
|
895
960
|
*
|
|
896
|
-
*
|
|
897
|
-
*
|
|
898
|
-
*
|
|
961
|
+
* Because the committee is unknown until the gateway stamps the round, private API
|
|
962
|
+
* secrets are encrypted for **every** node of the registry; the gateway forwards only the
|
|
963
|
+
* selected nodes' envelopes.
|
|
899
964
|
*
|
|
900
965
|
* By default this fetches the registry selection config up front and the node
|
|
901
966
|
* set only when the round needs it (private API encryption, or when the registry
|
|
@@ -914,8 +979,8 @@ var MolphaGateway = class {
|
|
|
914
979
|
encrypt,
|
|
915
980
|
sourcePayment,
|
|
916
981
|
maxAge = 60,
|
|
917
|
-
maxRetries =
|
|
918
|
-
timeoutMs =
|
|
982
|
+
maxRetries = DEFAULT_MAX_RETRIES,
|
|
983
|
+
timeoutMs = DEFAULT_ROUND_TIMEOUT_MS
|
|
919
984
|
} = opts;
|
|
920
985
|
const signaturesRequired = assertSignaturesRequired(opts.signaturesRequired);
|
|
921
986
|
const verifyNodeKeys = opts.verifyNodeKeys ?? this.verifyNodeKeys;
|
|
@@ -937,17 +1002,19 @@ var MolphaGateway = class {
|
|
|
937
1002
|
}
|
|
938
1003
|
const consumerAuthority = opts.consumerAuthority ?? this.defaultConsumerAuthority ?? subscriptionOwner;
|
|
939
1004
|
const authSigner = signer ?? this.defaultSigner;
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
throw new Error("Round context resolved neither nodeCount nor nodes");
|
|
950
|
-
|
|
1005
|
+
let round = await this.resolveContext(opts.context, encrypt !== void 0);
|
|
1006
|
+
let { registryVersion, redundancyBuffer } = round;
|
|
1007
|
+
const nodeCountOf = (r) => {
|
|
1008
|
+
if (r.nodeCount !== void 0 && r.nodes !== void 0 && r.nodes.length !== r.nodeCount) {
|
|
1009
|
+
throw new Error(
|
|
1010
|
+
`Gateway node list has ${r.nodes.length} nodes but registry ${r.registryVersion} has node_count ${r.nodeCount} \u2014 refresh the round context`
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
const n = r.nodeCount ?? r.nodes?.length;
|
|
1014
|
+
if (n === void 0) throw new Error("Round context resolved neither nodeCount nor nodes");
|
|
1015
|
+
return n;
|
|
1016
|
+
};
|
|
1017
|
+
let nodeCount = nodeCountOf(round);
|
|
951
1018
|
let terms = null;
|
|
952
1019
|
let authorizations = 0;
|
|
953
1020
|
let requoted = false;
|
|
@@ -970,28 +1037,31 @@ var MolphaGateway = class {
|
|
|
970
1037
|
}
|
|
971
1038
|
}
|
|
972
1039
|
let lastError;
|
|
973
|
-
let
|
|
1040
|
+
let tickMs = opts.tickMs;
|
|
1041
|
+
let groupSize = effectiveSelectionSize(signaturesRequired, redundancyBuffer, nodeCount);
|
|
1042
|
+
let registryIndexes = Array.from({ length: nodeCount }, (_, index) => index);
|
|
1043
|
+
let cause = { kind: "error" };
|
|
1044
|
+
let refreshedOnce = false;
|
|
1045
|
+
let retryNow = false;
|
|
974
1046
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
const indices = selectedIndices(bitmap, nodeCount);
|
|
1047
|
+
if (attempt > 0 && !retryNow) {
|
|
1048
|
+
tickMs ??= await this.advertisedTickMs(timeoutMs) ?? DEFAULT_TICK_MS;
|
|
1049
|
+
await sleep(retryDelayMs(cause, attempt, Date.now(), tickMs, this.random));
|
|
1050
|
+
}
|
|
1051
|
+
retryNow = false;
|
|
1052
|
+
cause = { kind: "error" };
|
|
982
1053
|
let encKeyBundle;
|
|
983
1054
|
if (encrypt) {
|
|
984
|
-
const
|
|
1055
|
+
const recipients = selectedNodesForPrivateApiEncryption(round.nodes ?? [], registryIndexes);
|
|
985
1056
|
if (verifyNodeKeys) {
|
|
986
1057
|
await verifyNodeKeys({
|
|
987
1058
|
sourceId,
|
|
988
1059
|
registryVersion,
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
selectedNodes: selected.map((node) => ({ ...node }))
|
|
1060
|
+
nodeIndexes: [...registryIndexes],
|
|
1061
|
+
nodes: recipients.map((node) => ({ ...node }))
|
|
992
1062
|
});
|
|
993
1063
|
}
|
|
994
|
-
encKeyBundle = encryptForNodes(requestApiConfig, encrypt.secrets,
|
|
1064
|
+
encKeyBundle = encryptForNodes(requestApiConfig, encrypt.secrets, recipients);
|
|
995
1065
|
}
|
|
996
1066
|
let sourcePayments;
|
|
997
1067
|
if (terms && sourcePayment && authorizations > 0) {
|
|
@@ -1004,7 +1074,6 @@ var MolphaGateway = class {
|
|
|
1004
1074
|
const baseBody = {
|
|
1005
1075
|
sourceId,
|
|
1006
1076
|
registryVersion,
|
|
1007
|
-
timestamp,
|
|
1008
1077
|
maxAge,
|
|
1009
1078
|
signaturesRequired,
|
|
1010
1079
|
subscriptionOwner,
|
|
@@ -1014,22 +1083,25 @@ var MolphaGateway = class {
|
|
|
1014
1083
|
if (encKeyBundle) baseBody.encKeyBundle = encKeyBundle;
|
|
1015
1084
|
if (sourcePayments) baseBody.sourcePayments = sourcePayments;
|
|
1016
1085
|
let requote = false;
|
|
1086
|
+
let restartForRefresh = false;
|
|
1017
1087
|
for (const endpoint of this.endpoints) {
|
|
1018
1088
|
try {
|
|
1019
1089
|
let authSig = ZERO_AUTH_SIG;
|
|
1090
|
+
let authTimestamp = authTimestampNow();
|
|
1020
1091
|
if (authSigner) {
|
|
1021
1092
|
const gateway = await this.resolveGatewayPda(endpoint, timeoutMs);
|
|
1093
|
+
authTimestamp = authTimestampNow();
|
|
1022
1094
|
authSig = await authSigner(
|
|
1023
1095
|
hashRequestAuth({
|
|
1024
1096
|
programId: this.programIdBytes,
|
|
1025
1097
|
gateway,
|
|
1026
1098
|
sourceId: sourceIdBytes,
|
|
1027
1099
|
signaturesRequired,
|
|
1028
|
-
|
|
1100
|
+
authTimestamp
|
|
1029
1101
|
})
|
|
1030
1102
|
);
|
|
1031
1103
|
}
|
|
1032
|
-
const body = { ...baseBody, authSig: bytesToHex0x(authSig) };
|
|
1104
|
+
const body = { ...baseBody, authSig: bytesToHex0x(authSig), authTimestamp };
|
|
1033
1105
|
const res = await this.post(
|
|
1034
1106
|
`${endpoint.url}/v1/round/execute`,
|
|
1035
1107
|
body,
|
|
@@ -1085,17 +1157,27 @@ var MolphaGateway = class {
|
|
|
1085
1157
|
break;
|
|
1086
1158
|
}
|
|
1087
1159
|
const errorDetail = !res.ok ? await parseGatewayErrorDetail(res) : void 0;
|
|
1088
|
-
if (res.status === 400
|
|
1160
|
+
if (res.status === 400 && !refreshedOnce && !restartForRefresh && /registryVersion.*current version/i.test(errorDetail ?? "")) {
|
|
1161
|
+
restartForRefresh = true;
|
|
1162
|
+
break;
|
|
1163
|
+
}
|
|
1164
|
+
if (res.status === 400 || res.status === 401 || res.status === 403) {
|
|
1089
1165
|
throw new GatewayError(
|
|
1090
1166
|
formatGatewayErrorMessage("Gateway rejected request", res.status, errorDetail),
|
|
1091
1167
|
res.status
|
|
1092
1168
|
);
|
|
1093
1169
|
}
|
|
1094
|
-
if (res.status === 503) {
|
|
1170
|
+
if (res.status === 503 || res.status === 429) {
|
|
1095
1171
|
lastError = new GatewayError(
|
|
1096
|
-
formatGatewayErrorMessage(
|
|
1097
|
-
|
|
1172
|
+
formatGatewayErrorMessage(
|
|
1173
|
+
res.status === 429 ? "Gateway rate limited" : "Gateway unavailable",
|
|
1174
|
+
res.status,
|
|
1175
|
+
errorDetail
|
|
1176
|
+
),
|
|
1177
|
+
res.status
|
|
1098
1178
|
);
|
|
1179
|
+
const wait = retryAfterMs(res);
|
|
1180
|
+
cause = mergeCause(cause, wait === void 0 ? { kind: "busy" } : { kind: "busy", retryAfterMs: wait });
|
|
1099
1181
|
continue;
|
|
1100
1182
|
}
|
|
1101
1183
|
if (!res.ok) {
|
|
@@ -1103,29 +1185,37 @@ var MolphaGateway = class {
|
|
|
1103
1185
|
formatGatewayErrorMessage("Gateway error", res.status, errorDetail),
|
|
1104
1186
|
res.status
|
|
1105
1187
|
);
|
|
1188
|
+
if (res.status === 409) cause = mergeCause(cause, { kind: "conflict" });
|
|
1106
1189
|
continue;
|
|
1107
1190
|
}
|
|
1108
1191
|
const json = await res.json();
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
return toResult(payload, {
|
|
1192
|
+
if (json.status === "completed" && json.data) {
|
|
1193
|
+
return toResult(json.data, {
|
|
1112
1194
|
sourceId,
|
|
1113
|
-
registryVersion,
|
|
1114
|
-
timestamp,
|
|
1115
1195
|
signaturesRequired,
|
|
1116
|
-
bitmap,
|
|
1117
1196
|
...requestApiConfig.aggregation ? { aggregation: requestApiConfig.aggregation } : {}
|
|
1118
1197
|
});
|
|
1119
1198
|
}
|
|
1120
1199
|
lastError = new Error(`Gateway returned status: ${json.status}`);
|
|
1121
1200
|
} catch (err) {
|
|
1122
1201
|
if (err instanceof UpstreamPaymentRequiredError) throw err;
|
|
1123
|
-
if (err instanceof GatewayError && (err.status === 400 || err.status === 401 || err.status === 402)) {
|
|
1202
|
+
if (err instanceof GatewayError && (err.status === 400 || err.status === 401 || err.status === 402 || err.status === 403)) {
|
|
1124
1203
|
throw err;
|
|
1125
1204
|
}
|
|
1126
1205
|
lastError = err;
|
|
1127
1206
|
}
|
|
1128
1207
|
}
|
|
1208
|
+
if (restartForRefresh) {
|
|
1209
|
+
round = await this.resolveContext(void 0, encrypt !== void 0);
|
|
1210
|
+
({ registryVersion, redundancyBuffer } = round);
|
|
1211
|
+
nodeCount = nodeCountOf(round);
|
|
1212
|
+
groupSize = effectiveSelectionSize(signaturesRequired, redundancyBuffer, nodeCount);
|
|
1213
|
+
registryIndexes = Array.from({ length: nodeCount }, (_, index) => index);
|
|
1214
|
+
refreshedOnce = true;
|
|
1215
|
+
retryNow = true;
|
|
1216
|
+
attempt--;
|
|
1217
|
+
continue;
|
|
1218
|
+
}
|
|
1129
1219
|
if (requote) continue;
|
|
1130
1220
|
}
|
|
1131
1221
|
throw lastError instanceof Error ? lastError : new Error("Gateway round failed after retries");
|
|
@@ -1154,6 +1244,27 @@ var MolphaGateway = class {
|
|
|
1154
1244
|
if (registry.nodeCount !== void 0) return registry;
|
|
1155
1245
|
return { ...registry, nodes: await this.getNodes() };
|
|
1156
1246
|
}
|
|
1247
|
+
/**
|
|
1248
|
+
* The gateway's advertised tick grid, read once per endpoint and only when a retry needs it. Any
|
|
1249
|
+
* failure (an old gateway without `/v1/info`, a timeout) means "not advertised", so the caller
|
|
1250
|
+
* falls back to the default; a failure is not cached.
|
|
1251
|
+
*/
|
|
1252
|
+
async advertisedTickMs(timeoutMs) {
|
|
1253
|
+
for (const endpoint of this.endpoints) {
|
|
1254
|
+
let pending = this.advertisedInfo.get(endpoint.url);
|
|
1255
|
+
if (!pending) {
|
|
1256
|
+
pending = this.fetchGatewayInfo(endpoint, Math.min(timeoutMs, 3e3)).catch(() => void 0);
|
|
1257
|
+
this.advertisedInfo.set(endpoint.url, pending);
|
|
1258
|
+
}
|
|
1259
|
+
const info = await pending;
|
|
1260
|
+
if (info === void 0) {
|
|
1261
|
+
this.advertisedInfo.delete(endpoint.url);
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
if (info.tickMs !== void 0) return info.tickMs;
|
|
1265
|
+
}
|
|
1266
|
+
return void 0;
|
|
1267
|
+
}
|
|
1157
1268
|
/** Gateway PDA bytes for an endpoint, cached per URL. A failed lookup is not cached. */
|
|
1158
1269
|
resolveGatewayPda(endpoint, timeoutMs) {
|
|
1159
1270
|
let pending = this.gatewayPdas.get(endpoint.url);
|
|
@@ -1216,14 +1327,11 @@ function assertSignaturesRequired(value) {
|
|
|
1216
1327
|
return value;
|
|
1217
1328
|
}
|
|
1218
1329
|
function unwrapEnvelope(json, path, status) {
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
throw new GatewayError(`GET ${path} returned malformed payload`, status);
|
|
1223
|
-
}
|
|
1224
|
-
return wrapped.data;
|
|
1330
|
+
const wrapped = json;
|
|
1331
|
+
if (wrapped === null || typeof wrapped !== "object" || wrapped.data === void 0) {
|
|
1332
|
+
throw new GatewayError(`GET ${path} returned malformed payload`, status);
|
|
1225
1333
|
}
|
|
1226
|
-
return
|
|
1334
|
+
return wrapped.data;
|
|
1227
1335
|
}
|
|
1228
1336
|
function selectedNodesForPrivateApiEncryption(nodes, selectedIndexes) {
|
|
1229
1337
|
if (!Array.isArray(nodes)) {
|
|
@@ -1309,11 +1417,12 @@ function flattenGatewayData(data) {
|
|
|
1309
1417
|
if (!nested) return data;
|
|
1310
1418
|
const { attestation: _nested, ...rest } = data;
|
|
1311
1419
|
const { payload, signature } = nested;
|
|
1420
|
+
const timestamp = payload?.timestamp ?? payload?.canonicalTimestamp;
|
|
1312
1421
|
return {
|
|
1313
1422
|
...rest,
|
|
1314
1423
|
...payload?.sourceId !== void 0 ? { sourceId: payload.sourceId } : {},
|
|
1315
1424
|
...payload?.value !== void 0 ? { valuePacked: payload.value } : {},
|
|
1316
|
-
...
|
|
1425
|
+
...timestamp !== void 0 ? { timestamp } : {},
|
|
1317
1426
|
...payload?.registryVersion !== void 0 ? { registryVersion: payload.registryVersion } : {},
|
|
1318
1427
|
...payload?.signaturesRequired !== void 0 ? { signaturesRequired: payload.signaturesRequired } : {},
|
|
1319
1428
|
...signature?.signersBitmap !== void 0 ? { signersBitmap: signature.signersBitmap } : {},
|
|
@@ -1322,6 +1431,12 @@ function flattenGatewayData(data) {
|
|
|
1322
1431
|
};
|
|
1323
1432
|
}
|
|
1324
1433
|
function toResult(raw, ctx) {
|
|
1434
|
+
if (raw.attestation) {
|
|
1435
|
+
const { payload, signature } = raw.attestation;
|
|
1436
|
+
if (!payload || !signature) {
|
|
1437
|
+
throw new GatewayError("Gateway response is missing the attestation");
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1325
1440
|
const data = flattenGatewayData(raw);
|
|
1326
1441
|
if (data.sourceId !== void 0 && normalizeHex(data.sourceId) !== ctx.sourceId) {
|
|
1327
1442
|
throw new GatewayError(
|
|
@@ -1358,33 +1473,41 @@ function toResult(raw, ctx) {
|
|
|
1358
1473
|
);
|
|
1359
1474
|
}
|
|
1360
1475
|
}
|
|
1476
|
+
const fields = {
|
|
1477
|
+
timestamp: data.timestamp,
|
|
1478
|
+
registryVersion: data.registryVersion,
|
|
1479
|
+
value: data.valuePacked,
|
|
1480
|
+
signersBitmap: data.signersBitmap,
|
|
1481
|
+
s: data.s,
|
|
1482
|
+
commitmentAddr: data.commitmentAddr
|
|
1483
|
+
};
|
|
1484
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
1485
|
+
if (field === void 0 || field === "") {
|
|
1486
|
+
throw new GatewayError(`Gateway response is missing ${name}`);
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1361
1489
|
let value = data.value ?? "";
|
|
1362
1490
|
if (ctx.aggregation) {
|
|
1363
|
-
for (const field of ["valuePacked", "signersBitmap", "s", "commitmentAddr"]) {
|
|
1364
|
-
if (!data[field]) {
|
|
1365
|
-
throw new GatewayError(`Gateway tolerance response is missing ${field}`);
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
1491
|
try {
|
|
1369
|
-
value = formatInt256Decimal(
|
|
1492
|
+
value = formatInt256Decimal(fields.value, ctx.aggregation.numeric.decimals);
|
|
1370
1493
|
} catch (err) {
|
|
1371
1494
|
throw new GatewayError(
|
|
1372
|
-
`Gateway tolerance response
|
|
1495
|
+
`Gateway tolerance response value is not an int256 word: ${err instanceof Error ? err.message : String(err)}`
|
|
1373
1496
|
);
|
|
1374
1497
|
}
|
|
1375
1498
|
}
|
|
1376
1499
|
return {
|
|
1377
1500
|
payload: {
|
|
1378
1501
|
sourceId: ctx.sourceId,
|
|
1379
|
-
value:
|
|
1380
|
-
|
|
1381
|
-
registryVersion:
|
|
1502
|
+
value: fields.value,
|
|
1503
|
+
timestamp: fields.timestamp,
|
|
1504
|
+
registryVersion: fields.registryVersion,
|
|
1382
1505
|
signaturesRequired: ctx.signaturesRequired
|
|
1383
1506
|
},
|
|
1384
1507
|
signature: {
|
|
1385
|
-
signersBitmap:
|
|
1386
|
-
s:
|
|
1387
|
-
commitmentAddr:
|
|
1508
|
+
signersBitmap: fields.signersBitmap,
|
|
1509
|
+
s: fields.s,
|
|
1510
|
+
commitmentAddr: fields.commitmentAddr
|
|
1388
1511
|
},
|
|
1389
1512
|
value,
|
|
1390
1513
|
fresh: data.fresh ?? true
|
|
@@ -6103,7 +6226,7 @@ var molpha_default = {
|
|
|
6103
6226
|
{
|
|
6104
6227
|
code: 6030,
|
|
6105
6228
|
name: "FeedNotNewer",
|
|
6106
|
-
msg: "
|
|
6229
|
+
msg: "timestamp <= feed.timestamp"
|
|
6107
6230
|
},
|
|
6108
6231
|
{
|
|
6109
6232
|
code: 6031,
|
|
@@ -6248,12 +6371,12 @@ var molpha_default = {
|
|
|
6248
6371
|
{
|
|
6249
6372
|
code: 6059,
|
|
6250
6373
|
name: "AttestationTooStale",
|
|
6251
|
-
msg: "
|
|
6374
|
+
msg: "timestamp is older than now - max_settlement_delay_seconds"
|
|
6252
6375
|
},
|
|
6253
6376
|
{
|
|
6254
6377
|
code: 6060,
|
|
6255
6378
|
name: "AttestationInFuture",
|
|
6256
|
-
msg: "
|
|
6379
|
+
msg: "timestamp is further ahead of cluster time than the allowed drift"
|
|
6257
6380
|
},
|
|
6258
6381
|
{
|
|
6259
6382
|
code: 6061,
|
|
@@ -6378,7 +6501,7 @@ var molpha_default = {
|
|
|
6378
6501
|
{
|
|
6379
6502
|
code: 6085,
|
|
6380
6503
|
name: "RoundOutsideEpoch",
|
|
6381
|
-
msg: "
|
|
6504
|
+
msg: "timestamp is outside the epoch window"
|
|
6382
6505
|
},
|
|
6383
6506
|
{
|
|
6384
6507
|
code: 6086,
|
|
@@ -6454,6 +6577,11 @@ var molpha_default = {
|
|
|
6454
6577
|
code: 6100,
|
|
6455
6578
|
name: "InvalidRentReceiver",
|
|
6456
6579
|
msg: "rent receiver must be the account that paid for the closed account"
|
|
6580
|
+
},
|
|
6581
|
+
{
|
|
6582
|
+
code: 6101,
|
|
6583
|
+
name: "InvalidInitialTau",
|
|
6584
|
+
msg: "initial_tau is below the minimum ticket threshold"
|
|
6457
6585
|
}
|
|
6458
6586
|
],
|
|
6459
6587
|
types: [
|
|
@@ -6535,7 +6663,7 @@ var molpha_default = {
|
|
|
6535
6663
|
type: "u8"
|
|
6536
6664
|
},
|
|
6537
6665
|
{
|
|
6538
|
-
name: "
|
|
6666
|
+
name: "timestamp",
|
|
6539
6667
|
type: "u64"
|
|
6540
6668
|
}
|
|
6541
6669
|
]
|
|
@@ -7186,7 +7314,7 @@ var molpha_default = {
|
|
|
7186
7314
|
type: "pubkey"
|
|
7187
7315
|
},
|
|
7188
7316
|
{
|
|
7189
|
-
name: "
|
|
7317
|
+
name: "timestamp",
|
|
7190
7318
|
type: "u64"
|
|
7191
7319
|
},
|
|
7192
7320
|
{
|
|
@@ -7232,7 +7360,7 @@ var molpha_default = {
|
|
|
7232
7360
|
type: "u32"
|
|
7233
7361
|
},
|
|
7234
7362
|
{
|
|
7235
|
-
name: "
|
|
7363
|
+
name: "timestamp",
|
|
7236
7364
|
type: "u64"
|
|
7237
7365
|
},
|
|
7238
7366
|
{
|
|
@@ -7493,6 +7621,18 @@ var molpha_default = {
|
|
|
7493
7621
|
{
|
|
7494
7622
|
name: "protocol_fee_bps",
|
|
7495
7623
|
type: "u16"
|
|
7624
|
+
},
|
|
7625
|
+
{
|
|
7626
|
+
name: "initial_tau",
|
|
7627
|
+
docs: [
|
|
7628
|
+
"Ticket threshold of the two genesis epochs: a round is a ticket when the 64-bit prefix of its",
|
|
7629
|
+
"ticket hash is below it, so the sampling probability is `initial_tau / 2^64`. Size it as",
|
|
7630
|
+
"`2^64 * target_tickets_per_epoch / expected_rounds_per_epoch`. `u64::MAX` samples every round",
|
|
7631
|
+
"(every round then costs a ticket transaction until the controller, which moves the",
|
|
7632
|
+
"threshold at most 8x per epoch with a two-epoch lag, brings it down). Must be at least",
|
|
7633
|
+
"`TAU_MIN`."
|
|
7634
|
+
],
|
|
7635
|
+
type: "u64"
|
|
7496
7636
|
}
|
|
7497
7637
|
]
|
|
7498
7638
|
}
|
|
@@ -8287,7 +8427,7 @@ var molpha_default = {
|
|
|
8287
8427
|
{
|
|
8288
8428
|
name: "max_settlement_delay_seconds",
|
|
8289
8429
|
docs: [
|
|
8290
|
-
"Max age in seconds of `
|
|
8430
|
+
"Max age in seconds of `timestamp` relative to cluster time at attestation",
|
|
8291
8431
|
"ingress, and the grace period of a superseded registry version."
|
|
8292
8432
|
],
|
|
8293
8433
|
type: "u64"
|
|
@@ -9326,7 +9466,17 @@ function planIdFromVariant(variant) {
|
|
|
9326
9466
|
}
|
|
9327
9467
|
|
|
9328
9468
|
// src/solana/client.ts
|
|
9329
|
-
var
|
|
9469
|
+
var MAX_COMPUTE_UNIT_LIMIT = 14e5;
|
|
9470
|
+
function estimateSubmitComputeUnits(signerCount) {
|
|
9471
|
+
if (!Number.isInteger(signerCount) || signerCount < 1) return MAX_COMPUTE_UNIT_LIMIT;
|
|
9472
|
+
const measured = 43e3 + 9200 * signerCount;
|
|
9473
|
+
return Math.min(Math.round(measured * 1.15) + 1e4, MAX_COMPUTE_UNIT_LIMIT);
|
|
9474
|
+
}
|
|
9475
|
+
var REGISTRY_CACHE_MS = 3e4;
|
|
9476
|
+
var KEY_CACHE_LIMIT = 8192;
|
|
9477
|
+
var PRIORITY_FEE_CACHE_MS = 5e3;
|
|
9478
|
+
var AUTO_FEE_PERCENTILE = 0.75;
|
|
9479
|
+
var AUTO_FEE_CAP_MICRO_LAMPORTS = 1e6;
|
|
9330
9480
|
var MolphaSolanaClient = class _MolphaSolanaClient {
|
|
9331
9481
|
constructor(program, provider, programId) {
|
|
9332
9482
|
this.program = program;
|
|
@@ -9336,6 +9486,13 @@ var MolphaSolanaClient = class _MolphaSolanaClient {
|
|
|
9336
9486
|
program;
|
|
9337
9487
|
provider;
|
|
9338
9488
|
programId;
|
|
9489
|
+
// Registry reads and signer keys are shared by every submit that names the same registry
|
|
9490
|
+
// version, so a fleet of feeds reads them once. Promises are cached, so concurrent submits
|
|
9491
|
+
// coalesce; a failed read is dropped and retried by the next call.
|
|
9492
|
+
registryCache = /* @__PURE__ */ new Map();
|
|
9493
|
+
nodeKeyCache = /* @__PURE__ */ new Map();
|
|
9494
|
+
coalitionCache = /* @__PURE__ */ new Map();
|
|
9495
|
+
priorityFeeCache;
|
|
9339
9496
|
static create(opts) {
|
|
9340
9497
|
const programId = toSolanaAddress(opts.programId ?? MOLPHA_PROGRAM_ADDRESS);
|
|
9341
9498
|
const provider = new AnchorProvider(opts.connection, opts.wallet, {
|
|
@@ -9494,12 +9651,16 @@ var MolphaSolanaClient = class _MolphaSolanaClient {
|
|
|
9494
9651
|
const { payload, signature: schnorr } = attestation;
|
|
9495
9652
|
const sourceId = toFixedBytes(payload.sourceId, 32, "sourceId");
|
|
9496
9653
|
const submitter = this.wallet;
|
|
9497
|
-
const registry = await this.
|
|
9654
|
+
const registry = await this.fetchRegistryCached(payload.registryVersion);
|
|
9498
9655
|
const remaining = resolveRemainingAccounts(schnorr.signersBitmap, registry);
|
|
9499
9656
|
assertSignerCount(remaining.length, payload.signaturesRequired, registry);
|
|
9500
|
-
const coalitionKey = opts?.coalitionKey ?? await this.computeSignerCoalitionKey(remaining, registry);
|
|
9657
|
+
const coalitionKey = opts?.coalitionKey ?? await this.computeSignerCoalitionKey(remaining, registry, schnorr.signersBitmap);
|
|
9501
9658
|
const feed = feedPda(sourceId, payload.signaturesRequired, submitter, this.programId);
|
|
9502
|
-
const
|
|
9659
|
+
const preInstructions = [
|
|
9660
|
+
setComputeUnitLimit(opts?.computeUnitLimit ?? estimateSubmitComputeUnits(remaining.length))
|
|
9661
|
+
];
|
|
9662
|
+
const price = await this.resolvePriorityFee(opts?.priorityFeeMicroLamports, feed);
|
|
9663
|
+
if (price > 0) preInstructions.push(setComputeUnitPrice(price));
|
|
9503
9664
|
const signature = await this.methods.submitAttestation(
|
|
9504
9665
|
buildSubmitAttestationArgs(attestation, coalitionKey, opts?.rawValue)
|
|
9505
9666
|
).accountsPartial({
|
|
@@ -9508,26 +9669,80 @@ var MolphaSolanaClient = class _MolphaSolanaClient {
|
|
|
9508
9669
|
feed,
|
|
9509
9670
|
protocolConfig: protocolConfigPda(this.programId),
|
|
9510
9671
|
systemProgram: SYSTEM_PROGRAM_ADDRESS
|
|
9511
|
-
}).remainingAccounts(remaining).preInstructions(
|
|
9672
|
+
}).remainingAccounts(remaining).preInstructions(preInstructions).rpc();
|
|
9512
9673
|
return { signature, feed };
|
|
9513
9674
|
}
|
|
9514
|
-
/**
|
|
9515
|
-
|
|
9516
|
-
const
|
|
9517
|
-
|
|
9518
|
-
);
|
|
9519
|
-
const
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9675
|
+
/** The registry for `version`, reused for {@link REGISTRY_CACHE_MS}. */
|
|
9676
|
+
fetchRegistryCached(version) {
|
|
9677
|
+
const now = Date.now();
|
|
9678
|
+
const hit = this.registryCache.get(version);
|
|
9679
|
+
if (hit && now - hit.at < REGISTRY_CACHE_MS) return hit.value;
|
|
9680
|
+
const value = this.fetchRegistry(version);
|
|
9681
|
+
this.registryCache.set(version, { at: now, value });
|
|
9682
|
+
value.catch(() => {
|
|
9683
|
+
if (this.registryCache.get(version)?.value === value) this.registryCache.delete(version);
|
|
9684
|
+
});
|
|
9685
|
+
return value;
|
|
9686
|
+
}
|
|
9687
|
+
async resolvePriorityFee(option, feed) {
|
|
9688
|
+
if (option === void 0) return 0;
|
|
9689
|
+
if (option !== "auto") {
|
|
9690
|
+
if (!Number.isFinite(option) || option < 0) {
|
|
9691
|
+
throw new Error('priorityFeeMicroLamports must be a non-negative number or "auto"');
|
|
9524
9692
|
}
|
|
9525
|
-
return
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9693
|
+
return Math.floor(option);
|
|
9694
|
+
}
|
|
9695
|
+
const now = Date.now();
|
|
9696
|
+
if (!this.priorityFeeCache || now - this.priorityFeeCache.at >= PRIORITY_FEE_CACHE_MS) {
|
|
9697
|
+
const value = (async () => {
|
|
9698
|
+
try {
|
|
9699
|
+
const recent = await this.provider.connection.getRecentPrioritizationFees({
|
|
9700
|
+
lockedWritableAccounts: [new web3.PublicKey(feed)]
|
|
9701
|
+
});
|
|
9702
|
+
const fees = recent.map((r) => r.prioritizationFee).sort((a, b) => a - b);
|
|
9703
|
+
if (fees.length === 0) return 0;
|
|
9704
|
+
const fee = fees[Math.min(fees.length - 1, Math.floor(fees.length * AUTO_FEE_PERCENTILE))];
|
|
9705
|
+
return Math.min(fee, AUTO_FEE_CAP_MICRO_LAMPORTS);
|
|
9706
|
+
} catch {
|
|
9707
|
+
return 0;
|
|
9708
|
+
}
|
|
9709
|
+
})();
|
|
9710
|
+
this.priorityFeeCache = { at: now, value };
|
|
9711
|
+
}
|
|
9712
|
+
return this.priorityFeeCache.value;
|
|
9713
|
+
}
|
|
9714
|
+
/** Sum of the signers' keys, read from their on-chain `Node` accounts (one batched fetch). */
|
|
9715
|
+
computeSignerCoalitionKey(remaining, registry, signersBitmap) {
|
|
9716
|
+
const setKey = `${registry.version}:${signersBitmap}`;
|
|
9717
|
+
const known = this.coalitionCache.get(setKey);
|
|
9718
|
+
if (known) return known;
|
|
9719
|
+
if (this.coalitionCache.size >= KEY_CACHE_LIMIT) this.coalitionCache.clear();
|
|
9720
|
+
const pending = this.sumSignerKeys(remaining, registry);
|
|
9721
|
+
this.coalitionCache.set(setKey, pending);
|
|
9722
|
+
pending.catch(() => {
|
|
9723
|
+
if (this.coalitionCache.get(setKey) === pending) this.coalitionCache.delete(setKey);
|
|
9529
9724
|
});
|
|
9530
|
-
return
|
|
9725
|
+
return pending;
|
|
9726
|
+
}
|
|
9727
|
+
async sumSignerKeys(remaining, registry) {
|
|
9728
|
+
const addresses = remaining.map((meta) => meta.pubkey);
|
|
9729
|
+
const missing = addresses.filter((a) => !this.nodeKeyCache.has(a.toBase58()));
|
|
9730
|
+
if (missing.length > 0) {
|
|
9731
|
+
const accounts = await this.accounts.node.fetchMultiple(missing);
|
|
9732
|
+
if (this.nodeKeyCache.size + missing.length > KEY_CACHE_LIMIT) this.nodeKeyCache.clear();
|
|
9733
|
+
accounts.forEach((account, i) => {
|
|
9734
|
+
if (!account) {
|
|
9735
|
+
throw new Error(
|
|
9736
|
+
`Node account ${missing[i].toBase58()} (registry ${registry.version}) does not exist`
|
|
9737
|
+
);
|
|
9738
|
+
}
|
|
9739
|
+
this.nodeKeyCache.set(missing[i].toBase58(), {
|
|
9740
|
+
x: nodeCoordinate(account, "secp256k1PubkeyX", "secp256k1_pubkey_x"),
|
|
9741
|
+
y: nodeCoordinate(account, "secp256k1PubkeyY", "secp256k1_pubkey_y")
|
|
9742
|
+
});
|
|
9743
|
+
});
|
|
9744
|
+
}
|
|
9745
|
+
return computeCoalitionKey(addresses.map((a) => this.nodeKeyCache.get(a.toBase58())));
|
|
9531
9746
|
}
|
|
9532
9747
|
/**
|
|
9533
9748
|
* Read the feed written by `submitter` (default: this wallet) for
|
|
@@ -9643,7 +9858,7 @@ function buildSubmitAttestationArgs(attestation, coalitionKey, rawValue) {
|
|
|
9643
9858
|
sourceId: Array.from(toFixedBytes(payload.sourceId, 32, "sourceId")),
|
|
9644
9859
|
registryVersion: payload.registryVersion,
|
|
9645
9860
|
signaturesRequired: payload.signaturesRequired,
|
|
9646
|
-
|
|
9861
|
+
timestamp: new BN(payload.timestamp)
|
|
9647
9862
|
},
|
|
9648
9863
|
signature: {
|
|
9649
9864
|
aggSigS: Array.from(toFixedBytes(signature.s, 32, "signature.s")),
|
|
@@ -9699,16 +9914,16 @@ function nodeCoordinate(account, camelCaseField, snakeCaseField) {
|
|
|
9699
9914
|
return toFixedBytes(Uint8Array.from(value), 32, `Node.${camelCaseField}`);
|
|
9700
9915
|
}
|
|
9701
9916
|
function selectedNodesForVerifier(args) {
|
|
9702
|
-
if (args.
|
|
9917
|
+
if (args.nodeIndexes.length === 0) {
|
|
9703
9918
|
throw new Error("Private API node-key verification requires at least one selected index");
|
|
9704
9919
|
}
|
|
9705
|
-
if (args.
|
|
9920
|
+
if (args.nodes.length !== args.nodeIndexes.length) {
|
|
9706
9921
|
throw new Error(
|
|
9707
|
-
`Private API node-key verification expected ${args.
|
|
9922
|
+
`Private API node-key verification expected ${args.nodeIndexes.length} selected nodes, got ${args.nodes.length}`
|
|
9708
9923
|
);
|
|
9709
9924
|
}
|
|
9710
9925
|
const expected = /* @__PURE__ */ new Set();
|
|
9711
|
-
for (const index of args.
|
|
9926
|
+
for (const index of args.nodeIndexes) {
|
|
9712
9927
|
if (!Number.isInteger(index) || index < 0) {
|
|
9713
9928
|
throw new Error(`Private API selected index must be a non-negative integer: ${index}`);
|
|
9714
9929
|
}
|
|
@@ -9718,7 +9933,7 @@ function selectedNodesForVerifier(args) {
|
|
|
9718
9933
|
expected.add(index);
|
|
9719
9934
|
}
|
|
9720
9935
|
const byIndex = /* @__PURE__ */ new Map();
|
|
9721
|
-
for (const node of args.
|
|
9936
|
+
for (const node of args.nodes) {
|
|
9722
9937
|
if (!Number.isInteger(node.index) || node.index < 0) {
|
|
9723
9938
|
throw new Error(
|
|
9724
9939
|
`Private API selected node index must be a non-negative integer: ${node.index}`
|
|
@@ -9732,7 +9947,7 @@ function selectedNodesForVerifier(args) {
|
|
|
9732
9947
|
}
|
|
9733
9948
|
byIndex.set(node.index, node);
|
|
9734
9949
|
}
|
|
9735
|
-
return args.
|
|
9950
|
+
return args.nodeIndexes.map((index) => {
|
|
9736
9951
|
const node = byIndex.get(index);
|
|
9737
9952
|
if (!node) {
|
|
9738
9953
|
throw new Error(`Private API selected node is missing for index: ${index}`);
|
|
@@ -9763,7 +9978,7 @@ function attestationMessageHash(fields) {
|
|
|
9763
9978
|
toFixedBytes(fields.sourceId, 32, "sourceId"),
|
|
9764
9979
|
u32be(fields.registryVersion),
|
|
9765
9980
|
u8(fields.signaturesRequired),
|
|
9766
|
-
u64be(fields.
|
|
9981
|
+
u64be(fields.timestamp),
|
|
9767
9982
|
toFixedBytes(fields.signersBitmap, 32, "signersBitmap")
|
|
9768
9983
|
)
|
|
9769
9984
|
);
|
|
@@ -9776,10 +9991,20 @@ function attestationMessageHashFromAttestation(attestation) {
|
|
|
9776
9991
|
signaturesRequired: payload.signaturesRequired,
|
|
9777
9992
|
signersBitmap: signature.signersBitmap,
|
|
9778
9993
|
value: payload.value,
|
|
9779
|
-
|
|
9994
|
+
timestamp: payload.timestamp
|
|
9780
9995
|
});
|
|
9781
9996
|
}
|
|
9782
9997
|
|
|
9998
|
+
// src/core/timestamp.ts
|
|
9999
|
+
function timestampSeconds(timestamp) {
|
|
10000
|
+
const ms = typeof timestamp === "bigint" ? timestamp : BigInt(timestamp);
|
|
10001
|
+
if (ms < 0n) throw new RangeError("timestamp must not be negative");
|
|
10002
|
+
return Number(ms / 1000n);
|
|
10003
|
+
}
|
|
10004
|
+
function timestampAgeSeconds(timestamp, nowSeconds) {
|
|
10005
|
+
return Math.max(0, nowSeconds - timestampSeconds(timestamp));
|
|
10006
|
+
}
|
|
10007
|
+
|
|
9783
10008
|
// src/core/verifyCodes.ts
|
|
9784
10009
|
var VERIFY_CODES = {
|
|
9785
10010
|
OK: 0,
|
|
@@ -9787,11 +10012,11 @@ var VERIFY_CODES = {
|
|
|
9787
10012
|
FEED_WITNESS: 1,
|
|
9788
10013
|
/** The payload's `registryVersion` does not exist on this verifier. */
|
|
9789
10014
|
BAD_REGISTRY_VERSION: 2,
|
|
9790
|
-
/** Structurally invalid input, or a `
|
|
10015
|
+
/** Structurally invalid input, or a `timestamp` in the future when `maxAge != 0`. */
|
|
9791
10016
|
MALFORMED: 3,
|
|
9792
|
-
/** `
|
|
10017
|
+
/** `timestamp` predates the registry version's activation. */
|
|
9793
10018
|
NOT_YET_ACTIVE: 4,
|
|
9794
|
-
/** The registry version was superseded more than the grace window before `
|
|
10019
|
+
/** The registry version was superseded more than the grace window before `timestamp`. */
|
|
9795
10020
|
VERSION_EXPIRED: 5,
|
|
9796
10021
|
/** Reserved. Never returned. */
|
|
9797
10022
|
COMPROMISED_QUORUM: 6,
|
|
@@ -9835,7 +10060,7 @@ var MOLPHA_VERIFIER_ABI = [
|
|
|
9835
10060
|
{ name: "sourceId", type: "bytes32", internalType: "bytes32" },
|
|
9836
10061
|
{ name: "registryVersion", type: "uint32", internalType: "uint32" },
|
|
9837
10062
|
{ name: "signaturesRequired", type: "uint8", internalType: "uint8" },
|
|
9838
|
-
{ name: "
|
|
10063
|
+
{ name: "timestamp", type: "uint64", internalType: "uint64" }
|
|
9839
10064
|
]
|
|
9840
10065
|
},
|
|
9841
10066
|
{
|
|
@@ -10008,7 +10233,7 @@ function buildEvmVerifierArgs(attestation, options) {
|
|
|
10008
10233
|
sourceId: toFixedHex(signed.sourceId, 32, "sourceId"),
|
|
10009
10234
|
registryVersion: assertUint2(signed.registryVersion, U32_MAX2, "registryVersion"),
|
|
10010
10235
|
signaturesRequired: assertUint2(signed.signaturesRequired, U8_MAX, "signaturesRequired"),
|
|
10011
|
-
|
|
10236
|
+
timestamp: assertBigUint(signed.timestamp, U64_MAX, "timestamp")
|
|
10012
10237
|
};
|
|
10013
10238
|
const signature = {
|
|
10014
10239
|
signature: toFixedHex(sig.s, 32, "signature"),
|
|
@@ -10030,7 +10255,7 @@ function encodeEvmVerifyCalldata(args) {
|
|
|
10030
10255
|
u256beFromBigInt(
|
|
10031
10256
|
BigInt(assertUint2(payload.signaturesRequired, U8_MAX, "signaturesRequired"))
|
|
10032
10257
|
),
|
|
10033
|
-
u256beFromBigInt(assertBigUint(payload.
|
|
10258
|
+
u256beFromBigInt(assertBigUint(payload.timestamp, U64_MAX, "timestamp")),
|
|
10034
10259
|
word2(signature.signature, 32, "signature"),
|
|
10035
10260
|
word2(signature.commitment, 20, "commitment"),
|
|
10036
10261
|
u256beFromBigInt(assertBigUint(signature.signersBitmap, U256_MAX, "signersBitmap")),
|
|
@@ -10160,7 +10385,7 @@ function buildStarknetVerifierArgs(attestation, options) {
|
|
|
10160
10385
|
source_id: fixedHexToBigInt(signed.sourceId, 32, "sourceId"),
|
|
10161
10386
|
registry_version: assertUint3(signed.registryVersion, U32_MAX3, "registryVersion"),
|
|
10162
10387
|
signatures_required: assertUint3(signed.signaturesRequired, U8_MAX2, "signaturesRequired"),
|
|
10163
|
-
|
|
10388
|
+
timestamp: assertUint3(signed.timestamp, U64_MAX2, "timestamp")
|
|
10164
10389
|
};
|
|
10165
10390
|
const signature = {
|
|
10166
10391
|
signature: fixedHexToBigInt(sig.s, 32, "signature"),
|
|
@@ -10179,7 +10404,7 @@ function encodeStarknetVerifyCalldata(args) {
|
|
|
10179
10404
|
...u256Felts(payload.source_id, "source_id"),
|
|
10180
10405
|
toFelt(assertUint3(payload.registry_version, U32_MAX3, "registry_version")),
|
|
10181
10406
|
toFelt(assertUint3(payload.signatures_required, U8_MAX2, "signatures_required")),
|
|
10182
|
-
toFelt(assertUint3(payload.
|
|
10407
|
+
toFelt(assertUint3(payload.timestamp, U64_MAX2, "timestamp")),
|
|
10183
10408
|
...u256Felts(signature.signature, "signature"),
|
|
10184
10409
|
// An Ethereum-style address, so it must fit 160 bits (the verifier reports a wider one
|
|
10185
10410
|
// as `MALFORMED`; one past the field prime would not even deserialize).
|
|
@@ -10211,7 +10436,139 @@ function parseStarknetVerifyResult(result) {
|
|
|
10211
10436
|
return { success, code, reason: verifyCodeName(code) ?? "UNKNOWN" };
|
|
10212
10437
|
}
|
|
10213
10438
|
|
|
10439
|
+
// src/bulk.ts
|
|
10440
|
+
var DEFAULT_CONCURRENCY = 32;
|
|
10441
|
+
var MAX_DEFAULT_CONCURRENCY = 64;
|
|
10442
|
+
var DEFAULT_SUBMIT_CONCURRENCY = 8;
|
|
10443
|
+
var BACKOFF_COOLDOWN_MS = 1e3;
|
|
10444
|
+
var AdaptiveLimiter = class {
|
|
10445
|
+
constructor(initial, max, now = Date.now) {
|
|
10446
|
+
this.max = max;
|
|
10447
|
+
this.now = now;
|
|
10448
|
+
this.max = Math.max(1, max);
|
|
10449
|
+
this.limit_ = Math.min(Math.max(1, Math.floor(initial)), this.max);
|
|
10450
|
+
}
|
|
10451
|
+
max;
|
|
10452
|
+
now;
|
|
10453
|
+
limit_;
|
|
10454
|
+
inFlight = 0;
|
|
10455
|
+
successes = 0;
|
|
10456
|
+
lastCut = -Infinity;
|
|
10457
|
+
waiters = [];
|
|
10458
|
+
get limit() {
|
|
10459
|
+
return this.limit_;
|
|
10460
|
+
}
|
|
10461
|
+
async acquire() {
|
|
10462
|
+
if (this.inFlight < this.limit_) {
|
|
10463
|
+
this.inFlight++;
|
|
10464
|
+
return;
|
|
10465
|
+
}
|
|
10466
|
+
await new Promise((resolve) => this.waiters.push(resolve));
|
|
10467
|
+
}
|
|
10468
|
+
/** Release a slot. `busy` reports that the gateway answered at capacity. */
|
|
10469
|
+
release(outcome) {
|
|
10470
|
+
this.inFlight--;
|
|
10471
|
+
if (outcome === "busy") {
|
|
10472
|
+
this.successes = 0;
|
|
10473
|
+
const t = this.now();
|
|
10474
|
+
if (t - this.lastCut >= BACKOFF_COOLDOWN_MS) {
|
|
10475
|
+
this.limit_ = Math.max(1, Math.floor(this.limit_ / 2));
|
|
10476
|
+
this.lastCut = t;
|
|
10477
|
+
}
|
|
10478
|
+
} else if (outcome === "ok") {
|
|
10479
|
+
if (++this.successes >= this.limit_ && this.limit_ < this.max) {
|
|
10480
|
+
this.limit_++;
|
|
10481
|
+
this.successes = 0;
|
|
10482
|
+
}
|
|
10483
|
+
}
|
|
10484
|
+
while (this.waiters.length > 0 && this.inFlight < this.limit_) {
|
|
10485
|
+
this.inFlight++;
|
|
10486
|
+
this.waiters.shift()();
|
|
10487
|
+
}
|
|
10488
|
+
}
|
|
10489
|
+
};
|
|
10490
|
+
function spreadOffsetMs(sourceIdHex, spreadMs) {
|
|
10491
|
+
if (spreadMs <= 0) return 0;
|
|
10492
|
+
return Number.parseInt(sourceIdHex.slice(0, 8), 16) % spreadMs;
|
|
10493
|
+
}
|
|
10494
|
+
var isBusy = (err) => err instanceof GatewayError && (err.status === 503 || err.status === 429);
|
|
10495
|
+
async function requestMany(sdk, feeds, opts = {}) {
|
|
10496
|
+
const results = new Array(feeds.length);
|
|
10497
|
+
if (feeds.length === 0) return results;
|
|
10498
|
+
const advertised = await sdk.gateway.fetchGatewayInfo(sdkFirstEndpoint(sdk)).catch(() => void 0);
|
|
10499
|
+
const ceiling = opts.concurrency ?? (advertised?.maxInflightRounds ? Math.min(Math.max(1, Math.floor(advertised.maxInflightRounds / 2)), MAX_DEFAULT_CONCURRENCY) : DEFAULT_CONCURRENCY);
|
|
10500
|
+
const requests = new AdaptiveLimiter(ceiling, ceiling);
|
|
10501
|
+
const submits = new AdaptiveLimiter(
|
|
10502
|
+
opts.submitConcurrency ?? DEFAULT_SUBMIT_CONCURRENCY,
|
|
10503
|
+
opts.submitConcurrency ?? DEFAULT_SUBMIT_CONCURRENCY
|
|
10504
|
+
);
|
|
10505
|
+
const context = await sdk.gateway.prepareContext();
|
|
10506
|
+
const submit = opts.submit ?? true;
|
|
10507
|
+
const started = Date.now();
|
|
10508
|
+
const one = async (index) => {
|
|
10509
|
+
const feed = feeds[index];
|
|
10510
|
+
const result = { index, ok: false, ...feed.label !== void 0 ? { label: feed.label } : {} };
|
|
10511
|
+
results[index] = result;
|
|
10512
|
+
try {
|
|
10513
|
+
const wait = spreadOffsetMs(deriveSourceIdString(feed.apiConfig), opts.spreadMs ?? 0) - (Date.now() - started);
|
|
10514
|
+
if (wait > 0) await new Promise((resolve) => setTimeout(resolve, wait));
|
|
10515
|
+
if (opts.signal?.aborted) {
|
|
10516
|
+
result.error = new Error("aborted before the feed was started");
|
|
10517
|
+
return;
|
|
10518
|
+
}
|
|
10519
|
+
await requests.acquire();
|
|
10520
|
+
let outcome = "other";
|
|
10521
|
+
try {
|
|
10522
|
+
result.attestation = await sdk.gateway.requestSignedData({
|
|
10523
|
+
...opts.request,
|
|
10524
|
+
apiConfig: feed.apiConfig,
|
|
10525
|
+
signaturesRequired: feed.signaturesRequired,
|
|
10526
|
+
context
|
|
10527
|
+
});
|
|
10528
|
+
result.ok = true;
|
|
10529
|
+
outcome = "ok";
|
|
10530
|
+
} catch (err) {
|
|
10531
|
+
result.error = err;
|
|
10532
|
+
outcome = isBusy(err) ? "busy" : "other";
|
|
10533
|
+
} finally {
|
|
10534
|
+
requests.release(outcome);
|
|
10535
|
+
}
|
|
10536
|
+
if (result.ok && submit && result.attestation) {
|
|
10537
|
+
await submits.acquire();
|
|
10538
|
+
try {
|
|
10539
|
+
const sent = await sdk.solana.submitAttestation(result.attestation);
|
|
10540
|
+
result.signature = sent.signature;
|
|
10541
|
+
result.feedAddress = sent.feed;
|
|
10542
|
+
} catch (err) {
|
|
10543
|
+
result.submitError = err;
|
|
10544
|
+
} finally {
|
|
10545
|
+
submits.release("other");
|
|
10546
|
+
}
|
|
10547
|
+
}
|
|
10548
|
+
} finally {
|
|
10549
|
+
opts.onResult?.(result);
|
|
10550
|
+
}
|
|
10551
|
+
};
|
|
10552
|
+
await Promise.all(feeds.map((_, index) => one(index)));
|
|
10553
|
+
return results;
|
|
10554
|
+
}
|
|
10555
|
+
function sdkFirstEndpoint(sdk) {
|
|
10556
|
+
return sdk.gateway.endpointUrls()[0];
|
|
10557
|
+
}
|
|
10558
|
+
|
|
10214
10559
|
// src/index.ts
|
|
10560
|
+
var SubmitFailedError = class extends Error {
|
|
10561
|
+
constructor(result, cause) {
|
|
10562
|
+
super(
|
|
10563
|
+
`Gateway round succeeded but submitting the attestation failed: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
10564
|
+
);
|
|
10565
|
+
this.result = result;
|
|
10566
|
+
this.cause = cause;
|
|
10567
|
+
this.name = "SubmitFailedError";
|
|
10568
|
+
}
|
|
10569
|
+
result;
|
|
10570
|
+
cause;
|
|
10571
|
+
};
|
|
10215
10572
|
var MolphaSDK = class {
|
|
10216
10573
|
gateway;
|
|
10217
10574
|
solana;
|
|
@@ -10241,11 +10598,15 @@ var MolphaSDK = class {
|
|
|
10241
10598
|
*/
|
|
10242
10599
|
async requestAndSubmit(opts) {
|
|
10243
10600
|
const result = await this.gateway.requestSignedData(opts);
|
|
10244
|
-
|
|
10245
|
-
|
|
10601
|
+
try {
|
|
10602
|
+
const { signature, feed } = await this.solana.submitAttestation(result);
|
|
10603
|
+
return { result, signature, feed };
|
|
10604
|
+
} catch (cause) {
|
|
10605
|
+
throw new SubmitFailedError(result, cause);
|
|
10606
|
+
}
|
|
10246
10607
|
}
|
|
10247
10608
|
};
|
|
10248
10609
|
|
|
10249
|
-
export { AggregationConfigError, DEFAULT_GATEWAY_ENDPOINT, EIP712_DOMAIN_TYPEHASH, GatewayError, 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, MolphaGateway, MolphaSDK, MolphaSolanaClient, PlanType, REQUEST_AUTH_DOMAIN, 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, evmAddressFromPrivateKey, feedPda, formatInt256Decimal, gatewayPda, gatewaySignerFromWallet, getMolphaStarknetVerifierAddress, hashRequestAuth, hexToBytes, nodePda, normalizeEndpoint, normalizeSecp256k1PublicKeyHex, parseEvmVerifyResult, parseGatewayInfo, parseStarknetVerifyResult, parseUpstreamQuote, planIdFromVariant, planPda, planVariant, probeSource, protocolConfigPda, registryPda, registryStatePda, resolveRemainingAccounts, secp256k1PublicKeyFromCoordinates, selectedIndices, signSourcePayments, signerFromKeypair, signersBitmapToDecimal, signersBitmapToStarknetUint256, signersBitmapToUint256, subscriptionPda, toChecksumAddress, toFixedBytes, toFixedHex, transferWithAuthorizationDigest, transferWithAuthorizationHash, u256beFromBigInt, u32be, u32le, u64be, u64le, u8, utf8, validateSuppliedTerms, verifyCodeName };
|
|
10610
|
+
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_IDL, MOLPHA_PROGRAM_ADDRESS, MOLPHA_PROGRAM_ID, 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 };
|
|
10250
10611
|
//# sourceMappingURL=index.js.map
|
|
10251
10612
|
//# sourceMappingURL=index.js.map
|