@lucid-evolution/provider 0.1.96 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -37,11 +37,103 @@ __export(index_exports, {
37
37
  Kupmios: () => Kupmios,
38
38
  KupmiosError: () => KupmiosError,
39
39
  Maestro: () => Maestro,
40
+ OgmiosJsonRpcError: () => OgmiosJsonRpcError,
40
41
  generateEmulatorAccount: () => generateEmulatorAccount,
41
- generateEmulatorAccountFromPrivateKey: () => generateEmulatorAccountFromPrivateKey
42
+ generateEmulatorAccountFromPrivateKey: () => generateEmulatorAccountFromPrivateKey,
43
+ isEmulatorProvider: () => isEmulatorProvider
42
44
  });
43
45
  module.exports = __toCommonJS(index_exports);
44
46
 
47
+ // src/errors.ts
48
+ var asRecord = (value) => typeof value === "object" && value !== null ? value : void 0;
49
+ var responseStatus = (cause) => {
50
+ const response = asRecord(asRecord(cause)?.response);
51
+ return typeof response?.status === "number" ? response.status : void 0;
52
+ };
53
+ var retryAfterHeaderToMs = (value) => {
54
+ if (value === void 0) return void 0;
55
+ const seconds = Number(value);
56
+ if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
57
+ const timestamp = Date.parse(value);
58
+ return Number.isNaN(timestamp) ? void 0 : Math.max(0, timestamp - Date.now());
59
+ };
60
+ var retryAfter = (cause) => {
61
+ const response = asRecord(asRecord(cause)?.response);
62
+ const headers = asRecord(response?.headers);
63
+ const value = headers?.["retry-after"];
64
+ return retryAfterHeaderToMs(typeof value === "string" ? value : void 0);
65
+ };
66
+ var errorTag = (cause) => {
67
+ const record = asRecord(cause);
68
+ return [record?._tag, record?.name, record?.reason].filter((value) => typeof value === "string").join(" ").toLowerCase();
69
+ };
70
+ var inferKind = (cause, status) => {
71
+ const tag = errorTag(cause);
72
+ if (tag.includes("timeout")) return "timeout";
73
+ if (tag.includes("parse") || tag.includes("decode")) return "decode";
74
+ if (status !== void 0) return "http";
75
+ if (tag.includes("request") || tag.includes("transport")) return "transport";
76
+ return "unknown";
77
+ };
78
+ var inferRetryable = (kind, status) => kind === "timeout" || kind === "transport" || status === 408 || status === 425 || status === 429 || status !== void 0 && status >= 500;
79
+ var KupmiosError = class extends Error {
80
+ _tag = "KupmiosError";
81
+ provider = "Kupmios";
82
+ protocol;
83
+ operation;
84
+ kind;
85
+ status;
86
+ retryable;
87
+ retryAfterMs;
88
+ cause;
89
+ constructor(options) {
90
+ const status = options.status ?? responseStatus(options.cause);
91
+ const kind = options.kind ?? inferKind(options.cause, status);
92
+ const retryable = options.retryable ?? inferRetryable(kind, status);
93
+ const operation = options.operation ?? "unknown";
94
+ const statusSuffix = status === void 0 ? "" : ` (HTTP ${status})`;
95
+ super(
96
+ options.message ?? `${options.protocol ?? "provider"} ${operation} failed${statusSuffix}`,
97
+ {
98
+ cause: options.cause
99
+ }
100
+ );
101
+ this.name = "KupmiosError";
102
+ this.protocol = options.protocol;
103
+ this.operation = operation;
104
+ this.kind = kind;
105
+ this.status = status;
106
+ this.retryable = retryable;
107
+ this.retryAfterMs = options.retryAfterMs ?? retryAfter(options.cause);
108
+ this.cause = options.cause;
109
+ }
110
+ };
111
+ var OgmiosJsonRpcError = class extends KupmiosError {
112
+ _tag = "OgmiosJsonRpcError";
113
+ code;
114
+ data;
115
+ method;
116
+ id;
117
+ constructor(options) {
118
+ const dataSuffix = options.data === void 0 ? "" : `: ${JSON.stringify(options.data)}`;
119
+ super({
120
+ protocol: "ogmios",
121
+ operation: options.operation ?? options.method ?? "unknown",
122
+ kind: "json_rpc",
123
+ status: options.status,
124
+ retryAfterMs: options.retryAfterMs,
125
+ cause: options.cause,
126
+ message: `Ogmios JSON-RPC error ${options.code}: ${options.message}${dataSuffix}`
127
+ });
128
+ this.name = "OgmiosJsonRpcError";
129
+ this.code = options.code;
130
+ this.data = options.data;
131
+ this.method = options.method;
132
+ this.id = options.id;
133
+ }
134
+ };
135
+ var toKupmiosError = (cause, protocol, operation) => cause instanceof KupmiosError ? cause : new KupmiosError({ cause, protocol, operation });
136
+
45
137
  // src/core.ts
46
138
  var CML = __toESM(require("@anastasia-labs/cardano-multiplatform-lib-nodejs"), 1);
47
139
 
@@ -52,7 +144,7 @@ var import_utils2 = require("@lucid-evolution/utils");
52
144
  // package.json
53
145
  var package_default = {
54
146
  name: "@lucid-evolution/provider",
55
- version: "0.1.96",
147
+ version: "0.2.0",
56
148
  description: "",
57
149
  main: "./dist/index.js",
58
150
  types: "./dist/index.d.ts",
@@ -295,18 +387,29 @@ var Blockfrost = class {
295
387
  )
296
388
  );
297
389
  }
298
- async getDelegation(rewardAddress) {
299
- const result = await fetch(`${this.url}/accounts/${rewardAddress}`, {
390
+ async getRewardAccount(rewardAddress) {
391
+ const response = await fetch(`${this.url}/accounts/${rewardAddress}`, {
300
392
  headers: { project_id: this.projectId, lucid }
301
- }).then((res) => res.json());
302
- if (!result || result.error) {
303
- return { poolId: null, rewards: 0n };
393
+ });
394
+ if (response.status === 404) {
395
+ return { registered: false, poolId: null, rewards: 0n };
304
396
  }
397
+ if (!response.ok) {
398
+ throw new Error(
399
+ `Could not fetch reward account from Blockfrost. Received status code: ${response.status}`
400
+ );
401
+ }
402
+ const result = await response.json();
305
403
  return {
404
+ registered: result.active,
306
405
  poolId: result.pool_id || null,
307
406
  rewards: BigInt(result.withdrawable_amount)
308
407
  };
309
408
  }
409
+ async getDelegation(rewardAddress) {
410
+ const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
411
+ return { poolId, rewards };
412
+ }
310
413
  async getDatum(datumHash) {
311
414
  const datum = await fetch(`${this.url}/scripts/datum/${datumHash}/cbor`, {
312
415
  headers: { project_id: this.projectId, lucid }
@@ -330,6 +433,29 @@ var Blockfrost = class {
330
433
  }, checkInterval);
331
434
  });
332
435
  }
436
+ async getTransactionStatus(txHash, options = {}) {
437
+ const response = await fetch(`${this.url}/txs/${txHash}`, {
438
+ headers: { project_id: this.projectId, lucid },
439
+ signal: options.signal
440
+ });
441
+ if (response.status === 404) return { status: "not_found", txHash };
442
+ if (!response.ok) {
443
+ throw new Error(
444
+ `Could not fetch transaction status from Blockfrost. Received status code: ${response.status}`
445
+ );
446
+ }
447
+ const result = await response.json();
448
+ return {
449
+ status: "confirmed",
450
+ txHash,
451
+ confirmation: {
452
+ txHash,
453
+ blockHash: result.block,
454
+ blockHeight: result.block_height,
455
+ slot: result.slot
456
+ }
457
+ };
458
+ }
333
459
  async submitTx(tx) {
334
460
  const result = await fetch(`${this.url}/tx/submit`, {
335
461
  method: "POST",
@@ -488,12 +614,28 @@ var JSONRPCErrorResponseSchema = import_effect2.Schema.Struct({
488
614
  var JSONRPCResponseSchema = (schema) => import_effect2.Schema.Union(JSONRPCSchema(schema), JSONRPCErrorResponseSchema).annotations({
489
615
  identifier: "JSONRPCResponseSchema"
490
616
  });
491
- var getJSONRPCResult = (response) => {
617
+ var getJSONRPCResult = (response, operation, transport) => {
492
618
  if ("error" in response) {
493
- const data = response.error.data === void 0 ? "" : `: ${JSON.stringify(response.error.data)}`;
494
- throw new Error(
495
- `Ogmios JSON-RPC error ${response.error.code}: ${response.error.message}${data}`
496
- );
619
+ throw new OgmiosJsonRpcError({
620
+ code: response.error.code,
621
+ message: response.error.message,
622
+ data: response.error.data,
623
+ method: response.method,
624
+ id: response.id,
625
+ operation,
626
+ status: transport?.status,
627
+ retryAfterMs: retryAfterHeaderToMs(transport?.headers["retry-after"]),
628
+ cause: transport
629
+ });
630
+ }
631
+ if (transport && (transport.status < 200 || transport.status >= 300)) {
632
+ throw new KupmiosError({
633
+ protocol: "ogmios",
634
+ operation: operation ?? response.method ?? "unknown",
635
+ status: transport.status,
636
+ retryAfterMs: retryAfterHeaderToMs(transport.headers["retry-after"]),
637
+ cause: transport
638
+ });
497
639
  }
498
640
  return response.result;
499
641
  };
@@ -527,6 +669,28 @@ var TupleNumberFromString = import_effect2.Schema.compose(
527
669
  import_effect2.Schema.split("/"),
528
670
  import_effect2.Schema.Array(import_effect2.Schema.NumberFromString)
529
671
  );
672
+ var MaxReferenceScriptsSizeSchema = import_effect2.Schema.Struct({
673
+ bytes: import_effect2.Schema.Number
674
+ });
675
+ function normalizeProtocolParameters(value) {
676
+ const legacy = value.maxReferenceScriptsSize;
677
+ const current = value.maxReferenceScriptsSizePerTransaction;
678
+ if (legacy === void 0 && current === void 0) {
679
+ return value;
680
+ }
681
+ const decode = import_effect2.Schema.decodeUnknownSync(MaxReferenceScriptsSizeSchema);
682
+ const legacyValue = legacy === void 0 ? void 0 : decode(legacy);
683
+ const currentValue = current === void 0 ? void 0 : decode(current);
684
+ if (legacyValue !== void 0 && currentValue !== void 0 && legacyValue.bytes !== currentValue.bytes) {
685
+ throw new Error(
686
+ "Conflicting Ogmios protocol parameters: maxReferenceScriptsSize and maxReferenceScriptsSizePerTransaction differ"
687
+ );
688
+ }
689
+ return {
690
+ ...value,
691
+ maxReferenceScriptsSize: legacyValue ?? currentValue
692
+ };
693
+ }
530
694
  var ProtocolParametersSchema = import_effect2.Schema.Struct({
531
695
  minFeeCoefficient: import_effect2.Schema.Number,
532
696
  minFeeReferenceScripts: import_effect2.Schema.Struct({
@@ -534,9 +698,7 @@ var ProtocolParametersSchema = import_effect2.Schema.Struct({
534
698
  range: import_effect2.Schema.Number,
535
699
  multiplier: import_effect2.Schema.Number
536
700
  }),
537
- maxReferenceScriptsSize: import_effect2.Schema.Struct({
538
- bytes: import_effect2.Schema.Number
539
- }),
701
+ maxReferenceScriptsSize: MaxReferenceScriptsSizeSchema,
540
702
  stakePoolVotingThresholds: import_effect2.Schema.Struct({
541
703
  noConfidence: TupleNumberFromString,
542
704
  constitutionalCommittee: import_effect2.Schema.Struct({
@@ -616,7 +778,7 @@ var LegacyDelegationSummarySchema = import_effect2.Schema.Struct({
616
778
  deposit: RewardAccountAdaSchema
617
779
  });
618
780
  var RewardAccountSummarySchema = import_effect2.Schema.Struct({
619
- from: import_effect2.Schema.optional(import_effect2.Schema.Literal("key", "script")),
781
+ from: import_effect2.Schema.optional(import_effect2.Schema.Literal("key", "verificationKey", "script")),
620
782
  credential: import_effect2.Schema.optional(import_effect2.Schema.String),
621
783
  stakePool: import_effect2.Schema.optional(import_effect2.Schema.NullOr(import_effect2.Schema.Struct({ id: import_effect2.Schema.String }))),
622
784
  rewards: RewardAccountAdaSchema,
@@ -807,6 +969,33 @@ var makePostAsJson = (url, data, schema, headers) => (0, import_effect4.pipe)(
807
969
  // Prevents resource leaks and ensures clean request termination
808
970
  import_effect4.Effect.scoped
809
971
  );
972
+ var makePostAsJsonResponse = (url, data, schema, headers) => (0, import_effect4.pipe)(
973
+ import_platform.HttpClientRequest.post(url),
974
+ headers ? import_platform.HttpClientRequest.setHeaders(headers) : import_effect4.identity,
975
+ import_platform.HttpClientRequest.bodyJson(data),
976
+ import_effect4.Effect.flatMap(import_platform.HttpClient.execute),
977
+ import_effect4.Effect.flatMap(
978
+ (response) => (0, import_effect4.pipe)(
979
+ import_platform.HttpClientResponse.schemaBodyJson(schema)(response),
980
+ import_effect4.Effect.map((body) => ({
981
+ body,
982
+ status: response.status,
983
+ headers: response.headers
984
+ })),
985
+ import_effect4.Effect.catchAll(
986
+ (cause) => response.status >= 200 && response.status < 300 ? import_effect4.Effect.fail(cause) : import_effect4.Effect.fail(
987
+ new import_platform.HttpClientError.ResponseError({
988
+ response,
989
+ request: response.request,
990
+ reason: "StatusCode",
991
+ description: "non 2xx status code with an invalid JSON response"
992
+ })
993
+ )
994
+ )
995
+ )
996
+ ),
997
+ import_effect4.Effect.scoped
998
+ );
810
999
  var makePostAsUint8Array = (url, data, schema, headers) => (0, import_effect4.pipe)(
811
1000
  // Initiate a POST request to the specified URL
812
1001
  import_platform.HttpClientRequest.post(url),
@@ -828,10 +1017,23 @@ var makePostAsUint8Array = (url, data, schema, headers) => (0, import_effect4.pi
828
1017
 
829
1018
  // src/kupmios.ts
830
1019
  var import_platform2 = require("@effect/platform");
831
- var KupmiosError = class extends import_effect6.Data.TaggedError("KupmiosError") {
832
- get message() {
833
- return `${this.cause}`;
1020
+ var catchProviderError = (protocol, operation) => (effect) => import_effect6.Effect.catchAll(
1021
+ effect,
1022
+ (cause) => import_effect6.Effect.fail(toKupmiosError(cause, protocol, operation))
1023
+ );
1024
+ var runProviderEffect = async (effect, protocol, operation, signal) => {
1025
+ const exit = await import_effect6.Effect.runPromiseExit(effect, { signal });
1026
+ if (import_effect6.Exit.isSuccess(exit)) return exit.value;
1027
+ if (signal?.aborted) {
1028
+ throw new KupmiosError({
1029
+ protocol,
1030
+ operation,
1031
+ kind: "aborted",
1032
+ retryable: false,
1033
+ cause: signal.reason ?? import_effect6.Cause.squash(exit.cause)
1034
+ });
834
1035
  }
1036
+ throw toKupmiosError(import_effect6.Cause.squash(exit.cause), protocol, operation);
835
1037
  };
836
1038
  var Kupmios = class {
837
1039
  kupoUrl;
@@ -850,22 +1052,32 @@ var Kupmios = class {
850
1052
  id: null
851
1053
  };
852
1054
  const schema = JSONRPCResponseSchema(
853
- ProtocolParametersSchema
1055
+ import_effect5.Schema.Record({ key: import_effect5.Schema.String, value: import_effect5.Schema.Unknown })
854
1056
  );
855
- const response = await (0, import_effect6.pipe)(
856
- makePostAsJson(
857
- this.ogmiosUrl,
858
- data,
859
- schema,
860
- this.headers?.ogmiosHeader
1057
+ const response = await runProviderEffect(
1058
+ (0, import_effect6.pipe)(
1059
+ makePostAsJsonResponse(
1060
+ this.ogmiosUrl,
1061
+ data,
1062
+ schema,
1063
+ this.headers?.ogmiosHeader
1064
+ ),
1065
+ import_effect6.Effect.timeout(1e4),
1066
+ catchProviderError("ogmios", "queryLedgerState/protocolParameters"),
1067
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
861
1068
  ),
862
- import_effect6.Effect.timeout(1e4),
863
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
864
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
865
- import_effect6.Effect.runPromise
1069
+ "ogmios",
1070
+ "queryLedgerState/protocolParameters"
1071
+ );
1072
+ const result = getJSONRPCResult(
1073
+ response.body,
1074
+ data.method,
1075
+ response
866
1076
  );
867
- const result = getJSONRPCResult(response);
868
- return toProtocolParameters(result);
1077
+ const protocolParameters = import_effect5.Schema.decodeUnknownSync(
1078
+ ProtocolParametersSchema
1079
+ )(normalizeProtocolParameters(result));
1080
+ return toProtocolParameters(protocolParameters);
869
1081
  }
870
1082
  async getTreasury() {
871
1083
  const data = {
@@ -877,19 +1089,26 @@ var Kupmios = class {
877
1089
  const schema = JSONRPCResponseSchema(
878
1090
  TreasuryAndReservesSchema
879
1091
  );
880
- const response = await (0, import_effect6.pipe)(
881
- makePostAsJson(
882
- this.ogmiosUrl,
883
- data,
884
- schema,
885
- this.headers?.ogmiosHeader
1092
+ const response = await runProviderEffect(
1093
+ (0, import_effect6.pipe)(
1094
+ makePostAsJsonResponse(
1095
+ this.ogmiosUrl,
1096
+ data,
1097
+ schema,
1098
+ this.headers?.ogmiosHeader
1099
+ ),
1100
+ import_effect6.Effect.timeout(1e4),
1101
+ catchProviderError("ogmios", "queryLedgerState/treasuryAndReserves"),
1102
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
886
1103
  ),
887
- import_effect6.Effect.timeout(1e4),
888
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
889
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
890
- import_effect6.Effect.runPromise
1104
+ "ogmios",
1105
+ "queryLedgerState/treasuryAndReserves"
1106
+ );
1107
+ const result = getJSONRPCResult(
1108
+ response.body,
1109
+ data.method,
1110
+ response
891
1111
  );
892
- const result = getJSONRPCResult(response);
893
1112
  return lovelaceAmountToBigInt(result.treasury.ada.lovelace);
894
1113
  }
895
1114
  async getUtxos(addressOrCredential) {
@@ -897,15 +1116,18 @@ var Kupmios = class {
897
1116
  const queryPredicate = isAddress ? addressOrCredential : addressOrCredential.hash;
898
1117
  const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent`;
899
1118
  const schema = import_effect5.Schema.Array(UTxOSchema);
900
- const utxos = await (0, import_effect6.pipe)(
901
- makeGet(pattern, schema, this.headers?.kupoHeader),
902
- import_effect6.Effect.flatMap(
903
- (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
1119
+ const utxos = await runProviderEffect(
1120
+ (0, import_effect6.pipe)(
1121
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1122
+ import_effect6.Effect.flatMap(
1123
+ (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
1124
+ ),
1125
+ import_effect6.Effect.timeout(1e4),
1126
+ catchProviderError("kupo", "getUtxos"),
1127
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
904
1128
  ),
905
- import_effect6.Effect.timeout(1e4),
906
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
907
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
908
- import_effect6.Effect.runPromise
1129
+ "kupo",
1130
+ "getUtxos"
909
1131
  );
910
1132
  return utxos;
911
1133
  }
@@ -915,31 +1137,62 @@ var Kupmios = class {
915
1137
  const { policyId, assetName } = (0, import_utils4.fromUnit)(unit);
916
1138
  const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent&policy_id=${policyId}${assetName ? `&asset_name=${assetName}` : ""}`;
917
1139
  const schema = import_effect5.Schema.Array(UTxOSchema);
918
- const utxos = await (0, import_effect6.pipe)(
919
- makeGet(pattern, schema, this.headers?.kupoHeader),
920
- import_effect6.Effect.flatMap(
921
- (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
1140
+ const utxos = await runProviderEffect(
1141
+ (0, import_effect6.pipe)(
1142
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1143
+ import_effect6.Effect.flatMap(
1144
+ (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
1145
+ ),
1146
+ import_effect6.Effect.timeout(1e4),
1147
+ catchProviderError("kupo", "getUtxosWithUnit"),
1148
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
922
1149
  ),
923
- import_effect6.Effect.timeout(1e4),
924
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
925
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
926
- import_effect6.Effect.runPromise
1150
+ "kupo",
1151
+ "getUtxosWithUnit"
1152
+ );
1153
+ return utxos.filter((utxo) => (utxo.assets[unit] ?? 0n) > 0n);
1154
+ }
1155
+ async getUtxosWithPolicy(addressOrCredential, policyId) {
1156
+ if (!/^[0-9a-f]{56}$/i.test(policyId)) {
1157
+ throw new TypeError(
1158
+ "policyId must be a 56-character hexadecimal string."
1159
+ );
1160
+ }
1161
+ const normalizedPolicyId = policyId.toLowerCase();
1162
+ const isAddress = typeof addressOrCredential === "string";
1163
+ const queryPredicate = isAddress ? addressOrCredential : addressOrCredential.hash;
1164
+ const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent&policy_id=${normalizedPolicyId}`;
1165
+ const schema = import_effect5.Schema.Array(UTxOSchema);
1166
+ return runProviderEffect(
1167
+ (0, import_effect6.pipe)(
1168
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1169
+ import_effect6.Effect.flatMap(
1170
+ (utxos) => kupmiosUtxosToUtxos(this.kupoUrl, utxos, this.headers?.kupoHeader)
1171
+ ),
1172
+ import_effect6.Effect.timeout(1e4),
1173
+ catchProviderError("kupo", "getUtxosWithPolicy"),
1174
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
1175
+ ),
1176
+ "kupo",
1177
+ "getUtxosWithPolicy"
927
1178
  );
928
- return utxos;
929
1179
  }
930
1180
  async getUtxoByUnit(unit) {
931
1181
  const { policyId, assetName } = (0, import_utils4.fromUnit)(unit);
932
- const pattern = `${this.kupoUrl}/matches/${policyId}.${assetName ? `${assetName}` : "*"}?unspent`;
1182
+ const pattern = `${this.kupoUrl}/matches/${policyId}.${assetName ?? ""}?unspent`;
933
1183
  const schema = import_effect5.Schema.Array(UTxOSchema);
934
- const utxos = await (0, import_effect6.pipe)(
935
- makeGet(pattern, schema, this.headers?.kupoHeader),
936
- import_effect6.Effect.flatMap(
937
- (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
1184
+ const utxos = await runProviderEffect(
1185
+ (0, import_effect6.pipe)(
1186
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1187
+ import_effect6.Effect.flatMap(
1188
+ (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
1189
+ ),
1190
+ import_effect6.Effect.timeout(1e4),
1191
+ catchProviderError("kupo", "getUtxoByUnit"),
1192
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
938
1193
  ),
939
- import_effect6.Effect.timeout(1e4),
940
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
941
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
942
- import_effect6.Effect.runPromise
1194
+ "kupo",
1195
+ "getUtxoByUnit"
943
1196
  );
944
1197
  if (utxos.length === 0) {
945
1198
  throw new Error("Unit not found.");
@@ -963,11 +1216,13 @@ var Kupmios = class {
963
1216
  (u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
964
1217
  ),
965
1218
  import_effect6.Effect.timeout(1e4),
966
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause }))
1219
+ catchProviderError("kupo", "getUtxosByOutRef")
967
1220
  )
968
1221
  );
969
- const utxos = await import_effect6.Effect.runPromise(
970
- (0, import_effect6.pipe)(program, import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer))
1222
+ const utxos = await runProviderEffect(
1223
+ (0, import_effect6.pipe)(program, import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)),
1224
+ "kupo",
1225
+ "getUtxosByOutRef"
971
1226
  );
972
1227
  return import_effect6.Array.flatten(utxos).filter(
973
1228
  (utxo) => outRefs.some(
@@ -975,7 +1230,7 @@ var Kupmios = class {
975
1230
  )
976
1231
  );
977
1232
  }
978
- async getDelegation(rewardAddress) {
1233
+ async getRewardAccount(rewardAddress) {
979
1234
  const data = {
980
1235
  jsonrpc: "2.0",
981
1236
  method: "queryLedgerState/rewardAccountSummaries",
@@ -983,50 +1238,95 @@ var Kupmios = class {
983
1238
  id: null
984
1239
  };
985
1240
  const schema = JSONRPCResponseSchema(Delegation);
986
- const response = await (0, import_effect6.pipe)(
987
- makePostAsJson(
988
- this.ogmiosUrl,
989
- data,
990
- schema,
991
- this.headers?.ogmiosHeader
1241
+ const response = await runProviderEffect(
1242
+ (0, import_effect6.pipe)(
1243
+ makePostAsJsonResponse(
1244
+ this.ogmiosUrl,
1245
+ data,
1246
+ schema,
1247
+ this.headers?.ogmiosHeader
1248
+ ),
1249
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1250
+ import_effect6.Effect.timeout(1e4),
1251
+ catchProviderError("ogmios", "queryLedgerState/rewardAccountSummaries")
992
1252
  ),
993
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
994
- import_effect6.Effect.timeout(1e4),
995
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
996
- import_effect6.Effect.runPromise
1253
+ "ogmios",
1254
+ "queryLedgerState/rewardAccountSummaries"
997
1255
  );
998
- const result = getJSONRPCResult(response);
999
- return toDelegation(result);
1256
+ const result = getJSONRPCResult(
1257
+ response.body,
1258
+ data.method,
1259
+ response
1260
+ );
1261
+ return toRewardAccountState(result);
1262
+ }
1263
+ async getDelegation(rewardAddress) {
1264
+ const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
1265
+ return { poolId, rewards };
1000
1266
  }
1001
1267
  async getDatum(datumHash) {
1002
1268
  const pattern = `${this.kupoUrl}/datums/${datumHash}`;
1003
1269
  const schema = DatumSchema;
1004
- const result = await (0, import_effect6.pipe)(
1005
- makeGet(pattern, schema, this.headers?.kupoHeader),
1006
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1007
- import_effect6.Effect.timeout(1e4),
1008
- import_effect6.Effect.flatMap(import_effect6.Effect.fromNullable),
1009
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
1010
- import_effect6.Effect.runPromise
1270
+ const result = await runProviderEffect(
1271
+ (0, import_effect6.pipe)(
1272
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1273
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1274
+ import_effect6.Effect.timeout(1e4),
1275
+ import_effect6.Effect.flatMap(import_effect6.Effect.fromNullable),
1276
+ catchProviderError("kupo", "getDatum")
1277
+ ),
1278
+ "kupo",
1279
+ "getDatum"
1011
1280
  );
1012
1281
  return result.datum;
1013
1282
  }
1283
+ async getTransactionStatus(txHash, options = {}) {
1284
+ const pattern = `${this.kupoUrl}/matches/*@${txHash}`;
1285
+ const schema = import_effect5.Schema.Array(UTxOSchema).annotations({
1286
+ identifier: "Array<KupmiosSchema.KupoUTxO>"
1287
+ });
1288
+ const matches = await runProviderEffect(
1289
+ (0, import_effect6.pipe)(
1290
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1291
+ import_effect6.Effect.timeout(1e4),
1292
+ catchProviderError("kupo", "getTransactionStatus"),
1293
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer)
1294
+ ),
1295
+ "kupo",
1296
+ "getTransactionStatus",
1297
+ options.signal
1298
+ );
1299
+ if (matches.length === 0) return { status: "not_found", txHash };
1300
+ const createdAt = matches[0].created_at;
1301
+ return {
1302
+ status: "confirmed",
1303
+ txHash,
1304
+ confirmation: {
1305
+ txHash,
1306
+ blockHash: createdAt.header_hash,
1307
+ slot: createdAt.slot_no
1308
+ }
1309
+ };
1310
+ }
1014
1311
  async awaitTx(txHash, checkInterval = 2e4) {
1015
- const pattern = `${this.kupoUrl}/matches/*@${txHash}?unspent`;
1312
+ const pattern = `${this.kupoUrl}/matches/*@${txHash}`;
1016
1313
  const schema = import_effect5.Schema.Array(UTxOSchema).annotations({
1017
1314
  identifier: "Array<KupmiosSchema.KupoUTxO>"
1018
1315
  });
1019
- const result = await (0, import_effect6.pipe)(
1020
- makeGet(pattern, schema, this.headers?.kupoHeader),
1021
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1022
- import_effect6.Effect.repeat({
1023
- schedule: import_effect6.Schedule.exponential(checkInterval),
1024
- until: (result2) => result2.length > 0
1025
- }),
1026
- import_effect6.Effect.timeout(16e4),
1027
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
1028
- import_effect6.Effect.as(true),
1029
- import_effect6.Effect.runPromise
1316
+ const result = await runProviderEffect(
1317
+ (0, import_effect6.pipe)(
1318
+ makeGet(pattern, schema, this.headers?.kupoHeader),
1319
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1320
+ import_effect6.Effect.repeat({
1321
+ schedule: import_effect6.Schedule.exponential(checkInterval),
1322
+ until: (result2) => result2.length > 0
1323
+ }),
1324
+ import_effect6.Effect.timeout(16e4),
1325
+ catchProviderError("kupo", "awaitTx"),
1326
+ import_effect6.Effect.as(true)
1327
+ ),
1328
+ "kupo",
1329
+ "awaitTx"
1030
1330
  );
1031
1331
  return result;
1032
1332
  }
@@ -1046,19 +1346,26 @@ var Kupmios = class {
1046
1346
  })
1047
1347
  })
1048
1348
  );
1049
- const response = await (0, import_effect6.pipe)(
1050
- makePostAsJson(
1051
- this.ogmiosUrl,
1052
- data,
1053
- schema,
1054
- this.headers?.ogmiosHeader
1349
+ const response = await runProviderEffect(
1350
+ (0, import_effect6.pipe)(
1351
+ makePostAsJsonResponse(
1352
+ this.ogmiosUrl,
1353
+ data,
1354
+ schema,
1355
+ this.headers?.ogmiosHeader
1356
+ ),
1357
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1358
+ import_effect6.Effect.timeout(1e4),
1359
+ catchProviderError("ogmios", "submitTransaction")
1055
1360
  ),
1056
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1057
- import_effect6.Effect.timeout(1e4),
1058
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
1059
- import_effect6.Effect.runPromise
1361
+ "ogmios",
1362
+ "submitTransaction"
1363
+ );
1364
+ const result = getJSONRPCResult(
1365
+ response.body,
1366
+ data.method,
1367
+ response
1060
1368
  );
1061
- const result = getJSONRPCResult(response);
1062
1369
  return result.transaction.id;
1063
1370
  }
1064
1371
  async evaluateTx(tx, additionalUTxOs) {
@@ -1072,19 +1379,26 @@ var Kupmios = class {
1072
1379
  id: null
1073
1380
  };
1074
1381
  const schema = JSONRPCResponseSchema(import_effect5.Schema.Array(RedeemerSchema));
1075
- const response = await (0, import_effect6.pipe)(
1076
- makePostAsJson(
1077
- this.ogmiosUrl,
1078
- data,
1079
- schema,
1080
- this.headers?.ogmiosHeader
1382
+ const response = await runProviderEffect(
1383
+ (0, import_effect6.pipe)(
1384
+ makePostAsJsonResponse(
1385
+ this.ogmiosUrl,
1386
+ data,
1387
+ schema,
1388
+ this.headers?.ogmiosHeader
1389
+ ),
1390
+ import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1391
+ import_effect6.Effect.timeout(1e4),
1392
+ catchProviderError("ogmios", "evaluateTransaction")
1081
1393
  ),
1082
- import_effect6.Effect.provide(import_platform2.FetchHttpClient.layer),
1083
- import_effect6.Effect.timeout(1e4),
1084
- import_effect6.Effect.catchAll((cause) => new KupmiosError({ cause })),
1085
- import_effect6.Effect.runPromise
1394
+ "ogmios",
1395
+ "evaluateTransaction"
1396
+ );
1397
+ const result = getJSONRPCResult(
1398
+ response.body,
1399
+ data.method,
1400
+ response
1086
1401
  );
1087
- const result = getJSONRPCResult(response);
1088
1402
  const evalRedeemers = result.map((item) => ({
1089
1403
  ex_units: {
1090
1404
  mem: item.budget.memory,
@@ -1186,15 +1500,13 @@ var toProtocolParameters = (result) => {
1186
1500
  }
1187
1501
  };
1188
1502
  };
1189
- var toDelegation = (result) => {
1190
- if (!result) {
1191
- return { poolId: null, rewards: 0n };
1192
- }
1193
- const delegation = Array.isArray(result) ? result[0] : Object.values(result)[0];
1503
+ var toRewardAccountState = (result) => {
1504
+ const delegation = result ? Array.isArray(result) ? result[0] : Object.values(result)[0] : void 0;
1194
1505
  if (!delegation) {
1195
- return { poolId: null, rewards: 0n };
1506
+ return { registered: false, poolId: null, rewards: 0n };
1196
1507
  }
1197
1508
  return {
1509
+ registered: true,
1198
1510
  poolId: "stakePool" in delegation ? delegation.stakePool?.id || null : delegation.delegate?.id || null,
1199
1511
  rewards: BigInt(delegation.rewards.ada.lovelace)
1200
1512
  };
@@ -1228,6 +1540,12 @@ var import_utils5 = require("@lucid-evolution/utils");
1228
1540
  var import_utils6 = require("@lucid-evolution/utils");
1229
1541
  var import_core_utils2 = require("@lucid-evolution/core-utils");
1230
1542
  var import_wallet = require("@lucid-evolution/wallet");
1543
+ var EMULATOR_PROVIDER_BRAND = Symbol.for(
1544
+ "@lucid-evolution/provider/Emulator"
1545
+ );
1546
+ var isEmulatorProvider = (provider) => Boolean(
1547
+ provider && provider[EMULATOR_PROVIDER_BRAND]
1548
+ );
1231
1549
  function generateEmulatorAccountFromPrivateKey(assets) {
1232
1550
  const privateKey = CML.PrivateKey.generate_ed25519().to_bech32();
1233
1551
  const priv = CML.PrivateKey.from_bech32(privateKey);
@@ -1257,6 +1575,7 @@ function generateEmulatorAccount(assets) {
1257
1575
  };
1258
1576
  }
1259
1577
  var Emulator = class {
1578
+ [EMULATOR_PROVIDER_BRAND] = true;
1260
1579
  ledger;
1261
1580
  mempool = {};
1262
1581
  /**
@@ -1270,6 +1589,7 @@ var Emulator = class {
1270
1589
  protocolParameters;
1271
1590
  datumTable = {};
1272
1591
  treasury;
1592
+ transactionHistory = {};
1273
1593
  constructor(accounts, protocolParameters = import_utils5.PROTOCOL_PARAMETERS_DEFAULT, treasury = 0n) {
1274
1594
  const GENESIS_HASH = "00".repeat(32);
1275
1595
  this.blockHeight = 0;
@@ -1305,12 +1625,27 @@ var Emulator = class {
1305
1625
  now() {
1306
1626
  return this.time;
1307
1627
  }
1628
+ confirmPendingTransactions(blockHeight, slot) {
1629
+ for (const [txHash, status] of Object.entries(this.transactionHistory)) {
1630
+ if (status.status === "pending") {
1631
+ this.transactionHistory[txHash] = {
1632
+ status: "confirmed",
1633
+ blockHeight,
1634
+ slot
1635
+ };
1636
+ }
1637
+ }
1638
+ }
1308
1639
  awaitSlot(length = 1) {
1309
1640
  this.slot += length;
1310
1641
  this.time += length * 1e3;
1311
1642
  const currentHeight = this.blockHeight;
1312
1643
  this.blockHeight = Math.floor(this.slot / 20);
1313
1644
  if (this.blockHeight > currentHeight) {
1645
+ this.confirmPendingTransactions(
1646
+ currentHeight + 1,
1647
+ (currentHeight + 1) * 20
1648
+ );
1314
1649
  for (const [outRef, { utxo, spent }] of Object.entries(this.mempool)) {
1315
1650
  this.ledger[outRef] = { utxo, spent };
1316
1651
  }
@@ -1321,9 +1656,14 @@ var Emulator = class {
1321
1656
  }
1322
1657
  }
1323
1658
  awaitBlock(height = 1) {
1659
+ const previousHeight = this.blockHeight;
1660
+ const previousSlot = this.slot;
1324
1661
  this.blockHeight += height;
1325
1662
  this.slot += height * 20;
1326
1663
  this.time += height * 20 * 1e3;
1664
+ if (height > 0) {
1665
+ this.confirmPendingTransactions(previousHeight + 1, previousSlot + 20);
1666
+ }
1327
1667
  for (const [outRef, { utxo, spent }] of Object.entries(this.mempool)) {
1328
1668
  this.ledger[outRef] = { utxo, spent };
1329
1669
  }
@@ -1333,14 +1673,17 @@ var Emulator = class {
1333
1673
  this.mempool = {};
1334
1674
  }
1335
1675
  getUtxos(addressOrCredential) {
1336
- const utxos = Object.values(this.ledger).flatMap(({ utxo }) => {
1337
- if (typeof addressOrCredential === "string") {
1338
- return addressOrCredential === utxo.address ? utxo : [];
1339
- } else {
1340
- const { paymentCredential } = (0, import_utils6.getAddressDetails)(utxo.address);
1341
- return paymentCredential?.hash === addressOrCredential.hash ? utxo : [];
1676
+ const utxos = Object.values(this.ledger).flatMap(
1677
+ ({ utxo, spent }) => {
1678
+ if (spent) return [];
1679
+ if (typeof addressOrCredential === "string") {
1680
+ return addressOrCredential === utxo.address ? utxo : [];
1681
+ } else {
1682
+ const { paymentCredential } = (0, import_utils6.getAddressDetails)(utxo.address);
1683
+ return paymentCredential?.hash === addressOrCredential.hash ? utxo : [];
1684
+ }
1342
1685
  }
1343
- });
1686
+ );
1344
1687
  return Promise.resolve(utxos);
1345
1688
  }
1346
1689
  getProtocolParameters() {
@@ -1353,32 +1696,44 @@ var Emulator = class {
1353
1696
  return Promise.resolve(this.datumTable[datumHash]);
1354
1697
  }
1355
1698
  getUtxosWithUnit(addressOrCredential, unit) {
1356
- const utxos = Object.values(this.ledger).flatMap(({ utxo }) => {
1357
- if (typeof addressOrCredential === "string") {
1358
- return addressOrCredential === utxo.address && utxo.assets[unit] > 0n ? utxo : [];
1359
- } else {
1360
- const { paymentCredential } = (0, import_utils6.getAddressDetails)(utxo.address);
1361
- return paymentCredential?.hash === addressOrCredential.hash && utxo.assets[unit] > 0n ? utxo : [];
1699
+ const utxos = Object.values(this.ledger).flatMap(
1700
+ ({ utxo, spent }) => {
1701
+ if (spent) return [];
1702
+ if (typeof addressOrCredential === "string") {
1703
+ return addressOrCredential === utxo.address && utxo.assets[unit] > 0n ? utxo : [];
1704
+ } else {
1705
+ const { paymentCredential } = (0, import_utils6.getAddressDetails)(utxo.address);
1706
+ return paymentCredential?.hash === addressOrCredential.hash && utxo.assets[unit] > 0n ? utxo : [];
1707
+ }
1362
1708
  }
1363
- });
1709
+ );
1364
1710
  return Promise.resolve(utxos);
1365
1711
  }
1366
1712
  getUtxosByOutRef(outRefs) {
1367
1713
  return Promise.resolve(
1368
- outRefs.flatMap(
1369
- (outRef) => this.ledger[outRef.txHash + outRef.outputIndex]?.utxo || []
1370
- )
1714
+ outRefs.flatMap((outRef) => {
1715
+ const entry = this.ledger[outRef.txHash + outRef.outputIndex];
1716
+ return entry && !entry.spent ? entry.utxo : [];
1717
+ })
1371
1718
  );
1372
1719
  }
1373
1720
  getUtxoByUnit(unit) {
1374
1721
  const utxos = Object.values(this.ledger).flatMap(
1375
- ({ utxo }) => utxo.assets[unit] > 0n ? utxo : []
1722
+ ({ utxo, spent }) => !spent && utxo.assets[unit] > 0n ? utxo : []
1376
1723
  );
1377
1724
  if (utxos.length > 1) {
1378
1725
  throw new Error("Unit needs to be an NFT or only held by one address.");
1379
1726
  }
1380
1727
  return Promise.resolve(utxos[0]);
1381
1728
  }
1729
+ getRewardAccount(rewardAddress) {
1730
+ const account = this.chain[rewardAddress];
1731
+ return Promise.resolve({
1732
+ registered: account?.registeredStake ?? false,
1733
+ poolId: account?.delegation.poolId ?? null,
1734
+ rewards: account?.delegation.rewards ?? 0n
1735
+ });
1736
+ }
1382
1737
  getDelegation(rewardAddress) {
1383
1738
  return Promise.resolve({
1384
1739
  poolId: this.chain[rewardAddress]?.delegation?.poolId || null,
@@ -1386,12 +1741,34 @@ var Emulator = class {
1386
1741
  });
1387
1742
  }
1388
1743
  awaitTx(txHash) {
1389
- if (this.mempool[txHash + 0]) {
1744
+ if (this.transactionHistory[txHash]?.status === "pending") {
1390
1745
  this.awaitBlock();
1391
1746
  return Promise.resolve(true);
1392
1747
  }
1393
1748
  return Promise.resolve(true);
1394
1749
  }
1750
+ getTransactionStatus(txHash, options = {}) {
1751
+ if (options.signal?.aborted) {
1752
+ return Promise.reject(
1753
+ options.signal.reason instanceof Error ? options.signal.reason : new DOMException("The operation was aborted.", "AbortError")
1754
+ );
1755
+ }
1756
+ const status = this.transactionHistory[txHash];
1757
+ if (!status) return Promise.resolve({ status: "not_found", txHash });
1758
+ if (status.status === "pending") {
1759
+ return Promise.resolve({ status: "pending", txHash });
1760
+ }
1761
+ return Promise.resolve({
1762
+ status: "confirmed",
1763
+ txHash,
1764
+ confirmation: {
1765
+ txHash,
1766
+ blockHeight: status.blockHeight,
1767
+ slot: status.slot,
1768
+ confirmations: this.blockHeight - status.blockHeight + 1
1769
+ }
1770
+ });
1771
+ }
1395
1772
  /**
1396
1773
  * Emulates the behaviour of the reward distribution at epoch boundaries.
1397
1774
  * Stake keys need to be registered and delegated like on a real chain in order to receive rewards.
@@ -2072,6 +2449,7 @@ It does not exist or was already spent.`
2072
2449
  for (const [datumHash, datum] of Object.entries(datumTable)) {
2073
2450
  this.datumTable[datumHash] = datum;
2074
2451
  }
2452
+ this.transactionHistory[txHash] = { status: "pending" };
2075
2453
  return Promise.resolve(txHash);
2076
2454
  }
2077
2455
  async evaluateTx(tx, additionalUTxOs) {
@@ -2323,21 +2701,30 @@ var Maestro = class {
2323
2701
  );
2324
2702
  return utxos.map(this.maestroUtxoToUtxo);
2325
2703
  }
2326
- async getDelegation(rewardAddress) {
2327
- const timestampedResultResponse = await fetch(
2328
- `${this.url}/accounts/${rewardAddress}`,
2329
- { headers: this.commonHeaders() }
2330
- );
2331
- if (!timestampedResultResponse.ok) {
2332
- return { poolId: null, rewards: 0n };
2704
+ async getRewardAccount(rewardAddress) {
2705
+ const response = await fetch(`${this.url}/accounts/${rewardAddress}`, {
2706
+ headers: this.requireAmountsAsStrings(this.commonHeaders())
2707
+ });
2708
+ if (response.status === 404) {
2709
+ return { registered: false, poolId: null, rewards: 0n };
2333
2710
  }
2334
- const timestampedResult = await timestampedResultResponse.json();
2711
+ if (!response.ok) {
2712
+ throw new Error(
2713
+ `Could not fetch reward account from Maestro. Received status code: ${response.status}`
2714
+ );
2715
+ }
2716
+ const timestampedResult = await response.json();
2335
2717
  const result = timestampedResult.data;
2336
2718
  return {
2719
+ registered: result.registered,
2337
2720
  poolId: result.delegated_pool || null,
2338
2721
  rewards: BigInt(result.rewards_available)
2339
2722
  };
2340
2723
  }
2724
+ async getDelegation(rewardAddress) {
2725
+ const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
2726
+ return { poolId, rewards };
2727
+ }
2341
2728
  async getDatum(datumHash) {
2342
2729
  const timestampedResultResponse = await fetch(
2343
2730
  `${this.url}/datums/${datumHash}`,
@@ -2375,6 +2762,42 @@ var Maestro = class {
2375
2762
  }, checkInterval);
2376
2763
  });
2377
2764
  }
2765
+ async getTransactionStatus(txHash, options = {}) {
2766
+ const response = await fetch(`${this.url}/txmanager/${txHash}/state`, {
2767
+ headers: this.commonHeaders(),
2768
+ signal: options.signal
2769
+ });
2770
+ if (response.status === 404) return { status: "not_found", txHash };
2771
+ if (!response.ok) {
2772
+ throw new Error(
2773
+ `Could not fetch transaction status from Maestro. Received status code: ${response.status}`
2774
+ );
2775
+ }
2776
+ const result = await response.json();
2777
+ switch (result.status) {
2778
+ case "pending":
2779
+ return { status: "pending", txHash };
2780
+ case "confirmed":
2781
+ return {
2782
+ status: "confirmed",
2783
+ txHash,
2784
+ confirmation: {
2785
+ txHash,
2786
+ confirmations: result.confirmations
2787
+ }
2788
+ };
2789
+ case "failed":
2790
+ return {
2791
+ status: "failed",
2792
+ txHash,
2793
+ reason: result.reason ?? result.error
2794
+ };
2795
+ default:
2796
+ throw new Error(
2797
+ `Maestro returned an unknown transaction status: ${String(result.status)}`
2798
+ );
2799
+ }
2800
+ }
2378
2801
  async submitTx(tx) {
2379
2802
  let queryUrl = `${this.url}/txmanager`;
2380
2803
  queryUrl += this.turboSubmit ? "/turbosubmit" : "";
@@ -2724,8 +3147,13 @@ var AssetAddressSchema = import_effect7.Schema.Struct({
2724
3147
  quantity: import_effect7.Schema.String
2725
3148
  });
2726
3149
  var AccountInfoSchema = import_effect7.Schema.Struct({
3150
+ status: import_effect7.Schema.Literal("registered", "not registered"),
2727
3151
  delegated_pool: import_effect7.Schema.NullOr(import_effect7.Schema.String),
2728
- rewards_available: import_effect7.Schema.NumberFromString
3152
+ rewards_available: import_effect7.Schema.String
3153
+ });
3154
+ var TxStatusSchema = import_effect7.Schema.Struct({
3155
+ tx_hash: import_effect7.Schema.String,
3156
+ num_confirmations: import_effect7.Schema.NullOr(import_effect7.Schema.Number)
2729
3157
  });
2730
3158
  var DatumInfo = import_effect7.Schema.Struct({
2731
3159
  bytes: import_effect7.Schema.String
@@ -2962,7 +3390,7 @@ var Koios = class {
2962
3390
  return [];
2963
3391
  }
2964
3392
  }
2965
- async getDelegation(rewardAddress) {
3393
+ async getRewardAccount(rewardAddress) {
2966
3394
  const body = {
2967
3395
  _stake_addresses: [rewardAddress]
2968
3396
  };
@@ -2977,18 +3405,24 @@ var Koios = class {
2977
3405
  ),
2978
3406
  // Allows for dependency injection and easier testing
2979
3407
  import_effect8.Effect.provide(import_platform4.FetchHttpClient.layer),
2980
- import_effect8.Effect.flatMap(
2981
- (result2) => result2.length === 0 ? import_effect8.Effect.fail("No Delegation Found by Reward Address") : import_effect8.Effect.succeed(result2[0])
2982
- ),
2983
3408
  import_effect8.Effect.timeout(1e4),
2984
3409
  import_effect8.Effect.catchAllCause((cause) => new KoiosError({ cause })),
2985
3410
  import_effect8.Effect.runPromise
2986
3411
  );
3412
+ const account = result[0];
3413
+ if (!account) {
3414
+ return { registered: false, poolId: null, rewards: 0n };
3415
+ }
2987
3416
  return {
2988
- poolId: result.delegated_pool || null,
2989
- rewards: BigInt(result.rewards_available)
3417
+ registered: account.status === "registered",
3418
+ poolId: account.delegated_pool || null,
3419
+ rewards: BigInt(account.rewards_available)
2990
3420
  };
2991
3421
  }
3422
+ async getDelegation(rewardAddress) {
3423
+ const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
3424
+ return { poolId, rewards };
3425
+ }
2992
3426
  async getDatum(datumHash) {
2993
3427
  const url = `${this.baseUrl}/datum_info`;
2994
3428
  const body = {
@@ -3035,6 +3469,38 @@ var Koios = class {
3035
3469
  );
3036
3470
  return result;
3037
3471
  }
3472
+ async getTransactionStatus(txHash, options = {}) {
3473
+ const url = `${this.baseUrl}/tx_status`;
3474
+ const body = { _tx_hashes: [txHash] };
3475
+ const bearerToken = this.token ? { Authorization: `Bearer ${this.token}` } : void 0;
3476
+ const response = await fetch(url, {
3477
+ method: "POST",
3478
+ headers: { "Content-Type": "application/json", ...bearerToken },
3479
+ body: JSON.stringify(body),
3480
+ signal: options.signal
3481
+ });
3482
+ if (response.status === 404) return { status: "not_found", txHash };
3483
+ if (!response.ok) {
3484
+ throw new Error(
3485
+ `Could not fetch transaction status from Koios. Received status code: ${response.status}`
3486
+ );
3487
+ }
3488
+ const result = import_effect8.Schema.decodeUnknownSync(import_effect8.Schema.Array(TxStatusSchema))(
3489
+ await response.json()
3490
+ );
3491
+ const status = result[0];
3492
+ if (!status || status.num_confirmations === null) {
3493
+ return { status: "not_found", txHash };
3494
+ }
3495
+ return {
3496
+ status: "confirmed",
3497
+ txHash,
3498
+ confirmation: {
3499
+ txHash,
3500
+ confirmations: status.num_confirmations
3501
+ }
3502
+ };
3503
+ }
3038
3504
  async submitTx(tx) {
3039
3505
  const url = `${this.baseUrl}/submittx`;
3040
3506
  const body = (0, import_core_utils4.fromHex)(tx);
@@ -3091,6 +3557,8 @@ var Koios = class {
3091
3557
  Kupmios,
3092
3558
  KupmiosError,
3093
3559
  Maestro,
3560
+ OgmiosJsonRpcError,
3094
3561
  generateEmulatorAccount,
3095
- generateEmulatorAccountFromPrivateKey
3562
+ generateEmulatorAccountFromPrivateKey,
3563
+ isEmulatorProvider
3096
3564
  });