@lucid-evolution/provider 0.1.97 → 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 +607 -162
- package/dist/index.d.cts +70 -10
- package/dist/index.d.ts +70 -10
- package/dist/index.js +607 -164
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,3 +1,93 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var asRecord = (value) => typeof value === "object" && value !== null ? value : void 0;
|
|
3
|
+
var responseStatus = (cause) => {
|
|
4
|
+
const response = asRecord(asRecord(cause)?.response);
|
|
5
|
+
return typeof response?.status === "number" ? response.status : void 0;
|
|
6
|
+
};
|
|
7
|
+
var retryAfterHeaderToMs = (value) => {
|
|
8
|
+
if (value === void 0) return void 0;
|
|
9
|
+
const seconds = Number(value);
|
|
10
|
+
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
|
|
11
|
+
const timestamp = Date.parse(value);
|
|
12
|
+
return Number.isNaN(timestamp) ? void 0 : Math.max(0, timestamp - Date.now());
|
|
13
|
+
};
|
|
14
|
+
var retryAfter = (cause) => {
|
|
15
|
+
const response = asRecord(asRecord(cause)?.response);
|
|
16
|
+
const headers = asRecord(response?.headers);
|
|
17
|
+
const value = headers?.["retry-after"];
|
|
18
|
+
return retryAfterHeaderToMs(typeof value === "string" ? value : void 0);
|
|
19
|
+
};
|
|
20
|
+
var errorTag = (cause) => {
|
|
21
|
+
const record = asRecord(cause);
|
|
22
|
+
return [record?._tag, record?.name, record?.reason].filter((value) => typeof value === "string").join(" ").toLowerCase();
|
|
23
|
+
};
|
|
24
|
+
var inferKind = (cause, status) => {
|
|
25
|
+
const tag = errorTag(cause);
|
|
26
|
+
if (tag.includes("timeout")) return "timeout";
|
|
27
|
+
if (tag.includes("parse") || tag.includes("decode")) return "decode";
|
|
28
|
+
if (status !== void 0) return "http";
|
|
29
|
+
if (tag.includes("request") || tag.includes("transport")) return "transport";
|
|
30
|
+
return "unknown";
|
|
31
|
+
};
|
|
32
|
+
var inferRetryable = (kind, status) => kind === "timeout" || kind === "transport" || status === 408 || status === 425 || status === 429 || status !== void 0 && status >= 500;
|
|
33
|
+
var KupmiosError = class extends Error {
|
|
34
|
+
_tag = "KupmiosError";
|
|
35
|
+
provider = "Kupmios";
|
|
36
|
+
protocol;
|
|
37
|
+
operation;
|
|
38
|
+
kind;
|
|
39
|
+
status;
|
|
40
|
+
retryable;
|
|
41
|
+
retryAfterMs;
|
|
42
|
+
cause;
|
|
43
|
+
constructor(options) {
|
|
44
|
+
const status = options.status ?? responseStatus(options.cause);
|
|
45
|
+
const kind = options.kind ?? inferKind(options.cause, status);
|
|
46
|
+
const retryable = options.retryable ?? inferRetryable(kind, status);
|
|
47
|
+
const operation = options.operation ?? "unknown";
|
|
48
|
+
const statusSuffix = status === void 0 ? "" : ` (HTTP ${status})`;
|
|
49
|
+
super(
|
|
50
|
+
options.message ?? `${options.protocol ?? "provider"} ${operation} failed${statusSuffix}`,
|
|
51
|
+
{
|
|
52
|
+
cause: options.cause
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
this.name = "KupmiosError";
|
|
56
|
+
this.protocol = options.protocol;
|
|
57
|
+
this.operation = operation;
|
|
58
|
+
this.kind = kind;
|
|
59
|
+
this.status = status;
|
|
60
|
+
this.retryable = retryable;
|
|
61
|
+
this.retryAfterMs = options.retryAfterMs ?? retryAfter(options.cause);
|
|
62
|
+
this.cause = options.cause;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var OgmiosJsonRpcError = class extends KupmiosError {
|
|
66
|
+
_tag = "OgmiosJsonRpcError";
|
|
67
|
+
code;
|
|
68
|
+
data;
|
|
69
|
+
method;
|
|
70
|
+
id;
|
|
71
|
+
constructor(options) {
|
|
72
|
+
const dataSuffix = options.data === void 0 ? "" : `: ${JSON.stringify(options.data)}`;
|
|
73
|
+
super({
|
|
74
|
+
protocol: "ogmios",
|
|
75
|
+
operation: options.operation ?? options.method ?? "unknown",
|
|
76
|
+
kind: "json_rpc",
|
|
77
|
+
status: options.status,
|
|
78
|
+
retryAfterMs: options.retryAfterMs,
|
|
79
|
+
cause: options.cause,
|
|
80
|
+
message: `Ogmios JSON-RPC error ${options.code}: ${options.message}${dataSuffix}`
|
|
81
|
+
});
|
|
82
|
+
this.name = "OgmiosJsonRpcError";
|
|
83
|
+
this.code = options.code;
|
|
84
|
+
this.data = options.data;
|
|
85
|
+
this.method = options.method;
|
|
86
|
+
this.id = options.id;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var toKupmiosError = (cause, protocol, operation) => cause instanceof KupmiosError ? cause : new KupmiosError({ cause, protocol, operation });
|
|
90
|
+
|
|
1
91
|
// src/core.ts
|
|
2
92
|
import * as CML from "@anastasia-labs/cardano-multiplatform-lib-nodejs";
|
|
3
93
|
|
|
@@ -11,7 +101,7 @@ import {
|
|
|
11
101
|
// package.json
|
|
12
102
|
var package_default = {
|
|
13
103
|
name: "@lucid-evolution/provider",
|
|
14
|
-
version: "0.
|
|
104
|
+
version: "0.2.0",
|
|
15
105
|
description: "",
|
|
16
106
|
main: "./dist/index.js",
|
|
17
107
|
types: "./dist/index.d.ts",
|
|
@@ -254,18 +344,29 @@ var Blockfrost = class {
|
|
|
254
344
|
)
|
|
255
345
|
);
|
|
256
346
|
}
|
|
257
|
-
async
|
|
258
|
-
const
|
|
347
|
+
async getRewardAccount(rewardAddress) {
|
|
348
|
+
const response = await fetch(`${this.url}/accounts/${rewardAddress}`, {
|
|
259
349
|
headers: { project_id: this.projectId, lucid }
|
|
260
|
-
})
|
|
261
|
-
if (
|
|
262
|
-
return { poolId: null, rewards: 0n };
|
|
350
|
+
});
|
|
351
|
+
if (response.status === 404) {
|
|
352
|
+
return { registered: false, poolId: null, rewards: 0n };
|
|
263
353
|
}
|
|
354
|
+
if (!response.ok) {
|
|
355
|
+
throw new Error(
|
|
356
|
+
`Could not fetch reward account from Blockfrost. Received status code: ${response.status}`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
const result = await response.json();
|
|
264
360
|
return {
|
|
361
|
+
registered: result.active,
|
|
265
362
|
poolId: result.pool_id || null,
|
|
266
363
|
rewards: BigInt(result.withdrawable_amount)
|
|
267
364
|
};
|
|
268
365
|
}
|
|
366
|
+
async getDelegation(rewardAddress) {
|
|
367
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
368
|
+
return { poolId, rewards };
|
|
369
|
+
}
|
|
269
370
|
async getDatum(datumHash) {
|
|
270
371
|
const datum = await fetch(`${this.url}/scripts/datum/${datumHash}/cbor`, {
|
|
271
372
|
headers: { project_id: this.projectId, lucid }
|
|
@@ -289,6 +390,29 @@ var Blockfrost = class {
|
|
|
289
390
|
}, checkInterval);
|
|
290
391
|
});
|
|
291
392
|
}
|
|
393
|
+
async getTransactionStatus(txHash, options = {}) {
|
|
394
|
+
const response = await fetch(`${this.url}/txs/${txHash}`, {
|
|
395
|
+
headers: { project_id: this.projectId, lucid },
|
|
396
|
+
signal: options.signal
|
|
397
|
+
});
|
|
398
|
+
if (response.status === 404) return { status: "not_found", txHash };
|
|
399
|
+
if (!response.ok) {
|
|
400
|
+
throw new Error(
|
|
401
|
+
`Could not fetch transaction status from Blockfrost. Received status code: ${response.status}`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
const result = await response.json();
|
|
405
|
+
return {
|
|
406
|
+
status: "confirmed",
|
|
407
|
+
txHash,
|
|
408
|
+
confirmation: {
|
|
409
|
+
txHash,
|
|
410
|
+
blockHash: result.block,
|
|
411
|
+
blockHeight: result.block_height,
|
|
412
|
+
slot: result.slot
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
}
|
|
292
416
|
async submitTx(tx) {
|
|
293
417
|
const result = await fetch(`${this.url}/tx/submit`, {
|
|
294
418
|
method: "POST",
|
|
@@ -422,7 +546,7 @@ var lucid = package_default.version;
|
|
|
422
546
|
// src/kupmios.ts
|
|
423
547
|
import { applyDoubleCborEncoding as applyDoubleCborEncoding2, fromUnit as fromUnit2 } from "@lucid-evolution/utils";
|
|
424
548
|
import { Schema as S3 } from "effect";
|
|
425
|
-
import { Effect as Effect2, pipe as pipe3, Array as _Array, Schedule
|
|
549
|
+
import { Cause, Effect as Effect2, Exit, pipe as pipe3, Array as _Array, Schedule } from "effect";
|
|
426
550
|
|
|
427
551
|
// src/internal/ogmios.ts
|
|
428
552
|
import { Schema as S } from "effect";
|
|
@@ -447,12 +571,28 @@ var JSONRPCErrorResponseSchema = S.Struct({
|
|
|
447
571
|
var JSONRPCResponseSchema = (schema) => S.Union(JSONRPCSchema(schema), JSONRPCErrorResponseSchema).annotations({
|
|
448
572
|
identifier: "JSONRPCResponseSchema"
|
|
449
573
|
});
|
|
450
|
-
var getJSONRPCResult = (response) => {
|
|
574
|
+
var getJSONRPCResult = (response, operation, transport) => {
|
|
451
575
|
if ("error" in response) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
576
|
+
throw new OgmiosJsonRpcError({
|
|
577
|
+
code: response.error.code,
|
|
578
|
+
message: response.error.message,
|
|
579
|
+
data: response.error.data,
|
|
580
|
+
method: response.method,
|
|
581
|
+
id: response.id,
|
|
582
|
+
operation,
|
|
583
|
+
status: transport?.status,
|
|
584
|
+
retryAfterMs: retryAfterHeaderToMs(transport?.headers["retry-after"]),
|
|
585
|
+
cause: transport
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
if (transport && (transport.status < 200 || transport.status >= 300)) {
|
|
589
|
+
throw new KupmiosError({
|
|
590
|
+
protocol: "ogmios",
|
|
591
|
+
operation: operation ?? response.method ?? "unknown",
|
|
592
|
+
status: transport.status,
|
|
593
|
+
retryAfterMs: retryAfterHeaderToMs(transport.headers["retry-after"]),
|
|
594
|
+
cause: transport
|
|
595
|
+
});
|
|
456
596
|
}
|
|
457
597
|
return response.result;
|
|
458
598
|
};
|
|
@@ -595,7 +735,7 @@ var LegacyDelegationSummarySchema = S.Struct({
|
|
|
595
735
|
deposit: RewardAccountAdaSchema
|
|
596
736
|
});
|
|
597
737
|
var RewardAccountSummarySchema = S.Struct({
|
|
598
|
-
from: S.optional(S.Literal("key", "script")),
|
|
738
|
+
from: S.optional(S.Literal("key", "verificationKey", "script")),
|
|
599
739
|
credential: S.optional(S.String),
|
|
600
740
|
stakePool: S.optional(S.NullOr(S.Struct({ id: S.String }))),
|
|
601
741
|
rewards: RewardAccountAdaSchema,
|
|
@@ -791,6 +931,33 @@ var makePostAsJson = (url, data, schema, headers) => pipe2(
|
|
|
791
931
|
// Prevents resource leaks and ensures clean request termination
|
|
792
932
|
Effect.scoped
|
|
793
933
|
);
|
|
934
|
+
var makePostAsJsonResponse = (url, data, schema, headers) => pipe2(
|
|
935
|
+
HttpClientRequest.post(url),
|
|
936
|
+
headers ? HttpClientRequest.setHeaders(headers) : identity,
|
|
937
|
+
HttpClientRequest.bodyJson(data),
|
|
938
|
+
Effect.flatMap(HttpClient.execute),
|
|
939
|
+
Effect.flatMap(
|
|
940
|
+
(response) => pipe2(
|
|
941
|
+
HttpClientResponse.schemaBodyJson(schema)(response),
|
|
942
|
+
Effect.map((body) => ({
|
|
943
|
+
body,
|
|
944
|
+
status: response.status,
|
|
945
|
+
headers: response.headers
|
|
946
|
+
})),
|
|
947
|
+
Effect.catchAll(
|
|
948
|
+
(cause) => response.status >= 200 && response.status < 300 ? Effect.fail(cause) : Effect.fail(
|
|
949
|
+
new HttpClientError.ResponseError({
|
|
950
|
+
response,
|
|
951
|
+
request: response.request,
|
|
952
|
+
reason: "StatusCode",
|
|
953
|
+
description: "non 2xx status code with an invalid JSON response"
|
|
954
|
+
})
|
|
955
|
+
)
|
|
956
|
+
)
|
|
957
|
+
)
|
|
958
|
+
),
|
|
959
|
+
Effect.scoped
|
|
960
|
+
);
|
|
794
961
|
var makePostAsUint8Array = (url, data, schema, headers) => pipe2(
|
|
795
962
|
// Initiate a POST request to the specified URL
|
|
796
963
|
HttpClientRequest.post(url),
|
|
@@ -812,10 +979,23 @@ var makePostAsUint8Array = (url, data, schema, headers) => pipe2(
|
|
|
812
979
|
|
|
813
980
|
// src/kupmios.ts
|
|
814
981
|
import { FetchHttpClient } from "@effect/platform";
|
|
815
|
-
var
|
|
816
|
-
|
|
817
|
-
|
|
982
|
+
var catchProviderError = (protocol, operation) => (effect) => Effect2.catchAll(
|
|
983
|
+
effect,
|
|
984
|
+
(cause) => Effect2.fail(toKupmiosError(cause, protocol, operation))
|
|
985
|
+
);
|
|
986
|
+
var runProviderEffect = async (effect, protocol, operation, signal) => {
|
|
987
|
+
const exit = await Effect2.runPromiseExit(effect, { signal });
|
|
988
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
989
|
+
if (signal?.aborted) {
|
|
990
|
+
throw new KupmiosError({
|
|
991
|
+
protocol,
|
|
992
|
+
operation,
|
|
993
|
+
kind: "aborted",
|
|
994
|
+
retryable: false,
|
|
995
|
+
cause: signal.reason ?? Cause.squash(exit.cause)
|
|
996
|
+
});
|
|
818
997
|
}
|
|
998
|
+
throw toKupmiosError(Cause.squash(exit.cause), protocol, operation);
|
|
819
999
|
};
|
|
820
1000
|
var Kupmios = class {
|
|
821
1001
|
kupoUrl;
|
|
@@ -836,19 +1016,26 @@ var Kupmios = class {
|
|
|
836
1016
|
const schema = JSONRPCResponseSchema(
|
|
837
1017
|
S3.Record({ key: S3.String, value: S3.Unknown })
|
|
838
1018
|
);
|
|
839
|
-
const response = await
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1019
|
+
const response = await runProviderEffect(
|
|
1020
|
+
pipe3(
|
|
1021
|
+
makePostAsJsonResponse(
|
|
1022
|
+
this.ogmiosUrl,
|
|
1023
|
+
data,
|
|
1024
|
+
schema,
|
|
1025
|
+
this.headers?.ogmiosHeader
|
|
1026
|
+
),
|
|
1027
|
+
Effect2.timeout(1e4),
|
|
1028
|
+
catchProviderError("ogmios", "queryLedgerState/protocolParameters"),
|
|
1029
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
845
1030
|
),
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
1031
|
+
"ogmios",
|
|
1032
|
+
"queryLedgerState/protocolParameters"
|
|
1033
|
+
);
|
|
1034
|
+
const result = getJSONRPCResult(
|
|
1035
|
+
response.body,
|
|
1036
|
+
data.method,
|
|
1037
|
+
response
|
|
850
1038
|
);
|
|
851
|
-
const result = getJSONRPCResult(response);
|
|
852
1039
|
const protocolParameters = S3.decodeUnknownSync(
|
|
853
1040
|
ProtocolParametersSchema
|
|
854
1041
|
)(normalizeProtocolParameters(result));
|
|
@@ -864,19 +1051,26 @@ var Kupmios = class {
|
|
|
864
1051
|
const schema = JSONRPCResponseSchema(
|
|
865
1052
|
TreasuryAndReservesSchema
|
|
866
1053
|
);
|
|
867
|
-
const response = await
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1054
|
+
const response = await runProviderEffect(
|
|
1055
|
+
pipe3(
|
|
1056
|
+
makePostAsJsonResponse(
|
|
1057
|
+
this.ogmiosUrl,
|
|
1058
|
+
data,
|
|
1059
|
+
schema,
|
|
1060
|
+
this.headers?.ogmiosHeader
|
|
1061
|
+
),
|
|
1062
|
+
Effect2.timeout(1e4),
|
|
1063
|
+
catchProviderError("ogmios", "queryLedgerState/treasuryAndReserves"),
|
|
1064
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
873
1065
|
),
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1066
|
+
"ogmios",
|
|
1067
|
+
"queryLedgerState/treasuryAndReserves"
|
|
1068
|
+
);
|
|
1069
|
+
const result = getJSONRPCResult(
|
|
1070
|
+
response.body,
|
|
1071
|
+
data.method,
|
|
1072
|
+
response
|
|
878
1073
|
);
|
|
879
|
-
const result = getJSONRPCResult(response);
|
|
880
1074
|
return lovelaceAmountToBigInt(result.treasury.ada.lovelace);
|
|
881
1075
|
}
|
|
882
1076
|
async getUtxos(addressOrCredential) {
|
|
@@ -884,15 +1078,18 @@ var Kupmios = class {
|
|
|
884
1078
|
const queryPredicate = isAddress ? addressOrCredential : addressOrCredential.hash;
|
|
885
1079
|
const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent`;
|
|
886
1080
|
const schema = S3.Array(UTxOSchema);
|
|
887
|
-
const utxos = await
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
(
|
|
1081
|
+
const utxos = await runProviderEffect(
|
|
1082
|
+
pipe3(
|
|
1083
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1084
|
+
Effect2.flatMap(
|
|
1085
|
+
(u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
|
|
1086
|
+
),
|
|
1087
|
+
Effect2.timeout(1e4),
|
|
1088
|
+
catchProviderError("kupo", "getUtxos"),
|
|
1089
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
891
1090
|
),
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
Effect2.provide(FetchHttpClient.layer),
|
|
895
|
-
Effect2.runPromise
|
|
1091
|
+
"kupo",
|
|
1092
|
+
"getUtxos"
|
|
896
1093
|
);
|
|
897
1094
|
return utxos;
|
|
898
1095
|
}
|
|
@@ -902,31 +1099,62 @@ var Kupmios = class {
|
|
|
902
1099
|
const { policyId, assetName } = fromUnit2(unit);
|
|
903
1100
|
const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent&policy_id=${policyId}${assetName ? `&asset_name=${assetName}` : ""}`;
|
|
904
1101
|
const schema = S3.Array(UTxOSchema);
|
|
905
|
-
const utxos = await
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
(
|
|
1102
|
+
const utxos = await runProviderEffect(
|
|
1103
|
+
pipe3(
|
|
1104
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1105
|
+
Effect2.flatMap(
|
|
1106
|
+
(u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
|
|
1107
|
+
),
|
|
1108
|
+
Effect2.timeout(1e4),
|
|
1109
|
+
catchProviderError("kupo", "getUtxosWithUnit"),
|
|
1110
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
909
1111
|
),
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1112
|
+
"kupo",
|
|
1113
|
+
"getUtxosWithUnit"
|
|
1114
|
+
);
|
|
1115
|
+
return utxos.filter((utxo) => (utxo.assets[unit] ?? 0n) > 0n);
|
|
1116
|
+
}
|
|
1117
|
+
async getUtxosWithPolicy(addressOrCredential, policyId) {
|
|
1118
|
+
if (!/^[0-9a-f]{56}$/i.test(policyId)) {
|
|
1119
|
+
throw new TypeError(
|
|
1120
|
+
"policyId must be a 56-character hexadecimal string."
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
const normalizedPolicyId = policyId.toLowerCase();
|
|
1124
|
+
const isAddress = typeof addressOrCredential === "string";
|
|
1125
|
+
const queryPredicate = isAddress ? addressOrCredential : addressOrCredential.hash;
|
|
1126
|
+
const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent&policy_id=${normalizedPolicyId}`;
|
|
1127
|
+
const schema = S3.Array(UTxOSchema);
|
|
1128
|
+
return runProviderEffect(
|
|
1129
|
+
pipe3(
|
|
1130
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1131
|
+
Effect2.flatMap(
|
|
1132
|
+
(utxos) => kupmiosUtxosToUtxos(this.kupoUrl, utxos, this.headers?.kupoHeader)
|
|
1133
|
+
),
|
|
1134
|
+
Effect2.timeout(1e4),
|
|
1135
|
+
catchProviderError("kupo", "getUtxosWithPolicy"),
|
|
1136
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
1137
|
+
),
|
|
1138
|
+
"kupo",
|
|
1139
|
+
"getUtxosWithPolicy"
|
|
914
1140
|
);
|
|
915
|
-
return utxos;
|
|
916
1141
|
}
|
|
917
1142
|
async getUtxoByUnit(unit) {
|
|
918
1143
|
const { policyId, assetName } = fromUnit2(unit);
|
|
919
|
-
const pattern = `${this.kupoUrl}/matches/${policyId}.${assetName
|
|
1144
|
+
const pattern = `${this.kupoUrl}/matches/${policyId}.${assetName ?? ""}?unspent`;
|
|
920
1145
|
const schema = S3.Array(UTxOSchema);
|
|
921
|
-
const utxos = await
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
(
|
|
1146
|
+
const utxos = await runProviderEffect(
|
|
1147
|
+
pipe3(
|
|
1148
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1149
|
+
Effect2.flatMap(
|
|
1150
|
+
(u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
|
|
1151
|
+
),
|
|
1152
|
+
Effect2.timeout(1e4),
|
|
1153
|
+
catchProviderError("kupo", "getUtxoByUnit"),
|
|
1154
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
925
1155
|
),
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
Effect2.provide(FetchHttpClient.layer),
|
|
929
|
-
Effect2.runPromise
|
|
1156
|
+
"kupo",
|
|
1157
|
+
"getUtxoByUnit"
|
|
930
1158
|
);
|
|
931
1159
|
if (utxos.length === 0) {
|
|
932
1160
|
throw new Error("Unit not found.");
|
|
@@ -950,11 +1178,13 @@ var Kupmios = class {
|
|
|
950
1178
|
(u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
|
|
951
1179
|
),
|
|
952
1180
|
Effect2.timeout(1e4),
|
|
953
|
-
|
|
1181
|
+
catchProviderError("kupo", "getUtxosByOutRef")
|
|
954
1182
|
)
|
|
955
1183
|
);
|
|
956
|
-
const utxos = await
|
|
957
|
-
pipe3(program, Effect2.provide(FetchHttpClient.layer))
|
|
1184
|
+
const utxos = await runProviderEffect(
|
|
1185
|
+
pipe3(program, Effect2.provide(FetchHttpClient.layer)),
|
|
1186
|
+
"kupo",
|
|
1187
|
+
"getUtxosByOutRef"
|
|
958
1188
|
);
|
|
959
1189
|
return _Array.flatten(utxos).filter(
|
|
960
1190
|
(utxo) => outRefs.some(
|
|
@@ -962,7 +1192,7 @@ var Kupmios = class {
|
|
|
962
1192
|
)
|
|
963
1193
|
);
|
|
964
1194
|
}
|
|
965
|
-
async
|
|
1195
|
+
async getRewardAccount(rewardAddress) {
|
|
966
1196
|
const data = {
|
|
967
1197
|
jsonrpc: "2.0",
|
|
968
1198
|
method: "queryLedgerState/rewardAccountSummaries",
|
|
@@ -970,50 +1200,95 @@ var Kupmios = class {
|
|
|
970
1200
|
id: null
|
|
971
1201
|
};
|
|
972
1202
|
const schema = JSONRPCResponseSchema(Delegation);
|
|
973
|
-
const response = await
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1203
|
+
const response = await runProviderEffect(
|
|
1204
|
+
pipe3(
|
|
1205
|
+
makePostAsJsonResponse(
|
|
1206
|
+
this.ogmiosUrl,
|
|
1207
|
+
data,
|
|
1208
|
+
schema,
|
|
1209
|
+
this.headers?.ogmiosHeader
|
|
1210
|
+
),
|
|
1211
|
+
Effect2.provide(FetchHttpClient.layer),
|
|
1212
|
+
Effect2.timeout(1e4),
|
|
1213
|
+
catchProviderError("ogmios", "queryLedgerState/rewardAccountSummaries")
|
|
979
1214
|
),
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1215
|
+
"ogmios",
|
|
1216
|
+
"queryLedgerState/rewardAccountSummaries"
|
|
1217
|
+
);
|
|
1218
|
+
const result = getJSONRPCResult(
|
|
1219
|
+
response.body,
|
|
1220
|
+
data.method,
|
|
1221
|
+
response
|
|
984
1222
|
);
|
|
985
|
-
|
|
986
|
-
|
|
1223
|
+
return toRewardAccountState(result);
|
|
1224
|
+
}
|
|
1225
|
+
async getDelegation(rewardAddress) {
|
|
1226
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
1227
|
+
return { poolId, rewards };
|
|
987
1228
|
}
|
|
988
1229
|
async getDatum(datumHash) {
|
|
989
1230
|
const pattern = `${this.kupoUrl}/datums/${datumHash}`;
|
|
990
1231
|
const schema = DatumSchema;
|
|
991
|
-
const result = await
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1232
|
+
const result = await runProviderEffect(
|
|
1233
|
+
pipe3(
|
|
1234
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1235
|
+
Effect2.provide(FetchHttpClient.layer),
|
|
1236
|
+
Effect2.timeout(1e4),
|
|
1237
|
+
Effect2.flatMap(Effect2.fromNullable),
|
|
1238
|
+
catchProviderError("kupo", "getDatum")
|
|
1239
|
+
),
|
|
1240
|
+
"kupo",
|
|
1241
|
+
"getDatum"
|
|
998
1242
|
);
|
|
999
1243
|
return result.datum;
|
|
1000
1244
|
}
|
|
1245
|
+
async getTransactionStatus(txHash, options = {}) {
|
|
1246
|
+
const pattern = `${this.kupoUrl}/matches/*@${txHash}`;
|
|
1247
|
+
const schema = S3.Array(UTxOSchema).annotations({
|
|
1248
|
+
identifier: "Array<KupmiosSchema.KupoUTxO>"
|
|
1249
|
+
});
|
|
1250
|
+
const matches = await runProviderEffect(
|
|
1251
|
+
pipe3(
|
|
1252
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1253
|
+
Effect2.timeout(1e4),
|
|
1254
|
+
catchProviderError("kupo", "getTransactionStatus"),
|
|
1255
|
+
Effect2.provide(FetchHttpClient.layer)
|
|
1256
|
+
),
|
|
1257
|
+
"kupo",
|
|
1258
|
+
"getTransactionStatus",
|
|
1259
|
+
options.signal
|
|
1260
|
+
);
|
|
1261
|
+
if (matches.length === 0) return { status: "not_found", txHash };
|
|
1262
|
+
const createdAt = matches[0].created_at;
|
|
1263
|
+
return {
|
|
1264
|
+
status: "confirmed",
|
|
1265
|
+
txHash,
|
|
1266
|
+
confirmation: {
|
|
1267
|
+
txHash,
|
|
1268
|
+
blockHash: createdAt.header_hash,
|
|
1269
|
+
slot: createdAt.slot_no
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1001
1273
|
async awaitTx(txHash, checkInterval = 2e4) {
|
|
1002
|
-
const pattern = `${this.kupoUrl}/matches/*@${txHash}
|
|
1274
|
+
const pattern = `${this.kupoUrl}/matches/*@${txHash}`;
|
|
1003
1275
|
const schema = S3.Array(UTxOSchema).annotations({
|
|
1004
1276
|
identifier: "Array<KupmiosSchema.KupoUTxO>"
|
|
1005
1277
|
});
|
|
1006
|
-
const result = await
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1278
|
+
const result = await runProviderEffect(
|
|
1279
|
+
pipe3(
|
|
1280
|
+
makeGet(pattern, schema, this.headers?.kupoHeader),
|
|
1281
|
+
Effect2.provide(FetchHttpClient.layer),
|
|
1282
|
+
Effect2.repeat({
|
|
1283
|
+
schedule: Schedule.exponential(checkInterval),
|
|
1284
|
+
until: (result2) => result2.length > 0
|
|
1285
|
+
}),
|
|
1286
|
+
Effect2.timeout(16e4),
|
|
1287
|
+
catchProviderError("kupo", "awaitTx"),
|
|
1288
|
+
Effect2.as(true)
|
|
1289
|
+
),
|
|
1290
|
+
"kupo",
|
|
1291
|
+
"awaitTx"
|
|
1017
1292
|
);
|
|
1018
1293
|
return result;
|
|
1019
1294
|
}
|
|
@@ -1033,19 +1308,26 @@ var Kupmios = class {
|
|
|
1033
1308
|
})
|
|
1034
1309
|
})
|
|
1035
1310
|
);
|
|
1036
|
-
const response = await
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1311
|
+
const response = await runProviderEffect(
|
|
1312
|
+
pipe3(
|
|
1313
|
+
makePostAsJsonResponse(
|
|
1314
|
+
this.ogmiosUrl,
|
|
1315
|
+
data,
|
|
1316
|
+
schema,
|
|
1317
|
+
this.headers?.ogmiosHeader
|
|
1318
|
+
),
|
|
1319
|
+
Effect2.provide(FetchHttpClient.layer),
|
|
1320
|
+
Effect2.timeout(1e4),
|
|
1321
|
+
catchProviderError("ogmios", "submitTransaction")
|
|
1042
1322
|
),
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1323
|
+
"ogmios",
|
|
1324
|
+
"submitTransaction"
|
|
1325
|
+
);
|
|
1326
|
+
const result = getJSONRPCResult(
|
|
1327
|
+
response.body,
|
|
1328
|
+
data.method,
|
|
1329
|
+
response
|
|
1047
1330
|
);
|
|
1048
|
-
const result = getJSONRPCResult(response);
|
|
1049
1331
|
return result.transaction.id;
|
|
1050
1332
|
}
|
|
1051
1333
|
async evaluateTx(tx, additionalUTxOs) {
|
|
@@ -1059,19 +1341,26 @@ var Kupmios = class {
|
|
|
1059
1341
|
id: null
|
|
1060
1342
|
};
|
|
1061
1343
|
const schema = JSONRPCResponseSchema(S3.Array(RedeemerSchema));
|
|
1062
|
-
const response = await
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1344
|
+
const response = await runProviderEffect(
|
|
1345
|
+
pipe3(
|
|
1346
|
+
makePostAsJsonResponse(
|
|
1347
|
+
this.ogmiosUrl,
|
|
1348
|
+
data,
|
|
1349
|
+
schema,
|
|
1350
|
+
this.headers?.ogmiosHeader
|
|
1351
|
+
),
|
|
1352
|
+
Effect2.provide(FetchHttpClient.layer),
|
|
1353
|
+
Effect2.timeout(1e4),
|
|
1354
|
+
catchProviderError("ogmios", "evaluateTransaction")
|
|
1068
1355
|
),
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1356
|
+
"ogmios",
|
|
1357
|
+
"evaluateTransaction"
|
|
1358
|
+
);
|
|
1359
|
+
const result = getJSONRPCResult(
|
|
1360
|
+
response.body,
|
|
1361
|
+
data.method,
|
|
1362
|
+
response
|
|
1073
1363
|
);
|
|
1074
|
-
const result = getJSONRPCResult(response);
|
|
1075
1364
|
const evalRedeemers = result.map((item) => ({
|
|
1076
1365
|
ex_units: {
|
|
1077
1366
|
mem: item.budget.memory,
|
|
@@ -1173,15 +1462,13 @@ var toProtocolParameters = (result) => {
|
|
|
1173
1462
|
}
|
|
1174
1463
|
};
|
|
1175
1464
|
};
|
|
1176
|
-
var
|
|
1177
|
-
|
|
1178
|
-
return { poolId: null, rewards: 0n };
|
|
1179
|
-
}
|
|
1180
|
-
const delegation = Array.isArray(result) ? result[0] : Object.values(result)[0];
|
|
1465
|
+
var toRewardAccountState = (result) => {
|
|
1466
|
+
const delegation = result ? Array.isArray(result) ? result[0] : Object.values(result)[0] : void 0;
|
|
1181
1467
|
if (!delegation) {
|
|
1182
|
-
return { poolId: null, rewards: 0n };
|
|
1468
|
+
return { registered: false, poolId: null, rewards: 0n };
|
|
1183
1469
|
}
|
|
1184
1470
|
return {
|
|
1471
|
+
registered: true,
|
|
1185
1472
|
poolId: "stakePool" in delegation ? delegation.stakePool?.id || null : delegation.delegate?.id || null,
|
|
1186
1473
|
rewards: BigInt(delegation.rewards.ada.lovelace)
|
|
1187
1474
|
};
|
|
@@ -1219,6 +1506,12 @@ import {
|
|
|
1219
1506
|
import { coreToUtxo, getAddressDetails } from "@lucid-evolution/utils";
|
|
1220
1507
|
import { fromHex as fromHex2 } from "@lucid-evolution/core-utils";
|
|
1221
1508
|
import { walletFromSeed } from "@lucid-evolution/wallet";
|
|
1509
|
+
var EMULATOR_PROVIDER_BRAND = Symbol.for(
|
|
1510
|
+
"@lucid-evolution/provider/Emulator"
|
|
1511
|
+
);
|
|
1512
|
+
var isEmulatorProvider = (provider) => Boolean(
|
|
1513
|
+
provider && provider[EMULATOR_PROVIDER_BRAND]
|
|
1514
|
+
);
|
|
1222
1515
|
function generateEmulatorAccountFromPrivateKey(assets) {
|
|
1223
1516
|
const privateKey = CML.PrivateKey.generate_ed25519().to_bech32();
|
|
1224
1517
|
const priv = CML.PrivateKey.from_bech32(privateKey);
|
|
@@ -1248,6 +1541,7 @@ function generateEmulatorAccount(assets) {
|
|
|
1248
1541
|
};
|
|
1249
1542
|
}
|
|
1250
1543
|
var Emulator = class {
|
|
1544
|
+
[EMULATOR_PROVIDER_BRAND] = true;
|
|
1251
1545
|
ledger;
|
|
1252
1546
|
mempool = {};
|
|
1253
1547
|
/**
|
|
@@ -1261,6 +1555,7 @@ var Emulator = class {
|
|
|
1261
1555
|
protocolParameters;
|
|
1262
1556
|
datumTable = {};
|
|
1263
1557
|
treasury;
|
|
1558
|
+
transactionHistory = {};
|
|
1264
1559
|
constructor(accounts, protocolParameters = PROTOCOL_PARAMETERS_DEFAULT, treasury = 0n) {
|
|
1265
1560
|
const GENESIS_HASH = "00".repeat(32);
|
|
1266
1561
|
this.blockHeight = 0;
|
|
@@ -1296,12 +1591,27 @@ var Emulator = class {
|
|
|
1296
1591
|
now() {
|
|
1297
1592
|
return this.time;
|
|
1298
1593
|
}
|
|
1594
|
+
confirmPendingTransactions(blockHeight, slot) {
|
|
1595
|
+
for (const [txHash, status] of Object.entries(this.transactionHistory)) {
|
|
1596
|
+
if (status.status === "pending") {
|
|
1597
|
+
this.transactionHistory[txHash] = {
|
|
1598
|
+
status: "confirmed",
|
|
1599
|
+
blockHeight,
|
|
1600
|
+
slot
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1299
1605
|
awaitSlot(length = 1) {
|
|
1300
1606
|
this.slot += length;
|
|
1301
1607
|
this.time += length * 1e3;
|
|
1302
1608
|
const currentHeight = this.blockHeight;
|
|
1303
1609
|
this.blockHeight = Math.floor(this.slot / 20);
|
|
1304
1610
|
if (this.blockHeight > currentHeight) {
|
|
1611
|
+
this.confirmPendingTransactions(
|
|
1612
|
+
currentHeight + 1,
|
|
1613
|
+
(currentHeight + 1) * 20
|
|
1614
|
+
);
|
|
1305
1615
|
for (const [outRef, { utxo, spent }] of Object.entries(this.mempool)) {
|
|
1306
1616
|
this.ledger[outRef] = { utxo, spent };
|
|
1307
1617
|
}
|
|
@@ -1312,9 +1622,14 @@ var Emulator = class {
|
|
|
1312
1622
|
}
|
|
1313
1623
|
}
|
|
1314
1624
|
awaitBlock(height = 1) {
|
|
1625
|
+
const previousHeight = this.blockHeight;
|
|
1626
|
+
const previousSlot = this.slot;
|
|
1315
1627
|
this.blockHeight += height;
|
|
1316
1628
|
this.slot += height * 20;
|
|
1317
1629
|
this.time += height * 20 * 1e3;
|
|
1630
|
+
if (height > 0) {
|
|
1631
|
+
this.confirmPendingTransactions(previousHeight + 1, previousSlot + 20);
|
|
1632
|
+
}
|
|
1318
1633
|
for (const [outRef, { utxo, spent }] of Object.entries(this.mempool)) {
|
|
1319
1634
|
this.ledger[outRef] = { utxo, spent };
|
|
1320
1635
|
}
|
|
@@ -1324,14 +1639,17 @@ var Emulator = class {
|
|
|
1324
1639
|
this.mempool = {};
|
|
1325
1640
|
}
|
|
1326
1641
|
getUtxos(addressOrCredential) {
|
|
1327
|
-
const utxos = Object.values(this.ledger).flatMap(
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1642
|
+
const utxos = Object.values(this.ledger).flatMap(
|
|
1643
|
+
({ utxo, spent }) => {
|
|
1644
|
+
if (spent) return [];
|
|
1645
|
+
if (typeof addressOrCredential === "string") {
|
|
1646
|
+
return addressOrCredential === utxo.address ? utxo : [];
|
|
1647
|
+
} else {
|
|
1648
|
+
const { paymentCredential } = getAddressDetails(utxo.address);
|
|
1649
|
+
return paymentCredential?.hash === addressOrCredential.hash ? utxo : [];
|
|
1650
|
+
}
|
|
1333
1651
|
}
|
|
1334
|
-
|
|
1652
|
+
);
|
|
1335
1653
|
return Promise.resolve(utxos);
|
|
1336
1654
|
}
|
|
1337
1655
|
getProtocolParameters() {
|
|
@@ -1344,32 +1662,44 @@ var Emulator = class {
|
|
|
1344
1662
|
return Promise.resolve(this.datumTable[datumHash]);
|
|
1345
1663
|
}
|
|
1346
1664
|
getUtxosWithUnit(addressOrCredential, unit) {
|
|
1347
|
-
const utxos = Object.values(this.ledger).flatMap(
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1665
|
+
const utxos = Object.values(this.ledger).flatMap(
|
|
1666
|
+
({ utxo, spent }) => {
|
|
1667
|
+
if (spent) return [];
|
|
1668
|
+
if (typeof addressOrCredential === "string") {
|
|
1669
|
+
return addressOrCredential === utxo.address && utxo.assets[unit] > 0n ? utxo : [];
|
|
1670
|
+
} else {
|
|
1671
|
+
const { paymentCredential } = getAddressDetails(utxo.address);
|
|
1672
|
+
return paymentCredential?.hash === addressOrCredential.hash && utxo.assets[unit] > 0n ? utxo : [];
|
|
1673
|
+
}
|
|
1353
1674
|
}
|
|
1354
|
-
|
|
1675
|
+
);
|
|
1355
1676
|
return Promise.resolve(utxos);
|
|
1356
1677
|
}
|
|
1357
1678
|
getUtxosByOutRef(outRefs) {
|
|
1358
1679
|
return Promise.resolve(
|
|
1359
|
-
outRefs.flatMap(
|
|
1360
|
-
|
|
1361
|
-
|
|
1680
|
+
outRefs.flatMap((outRef) => {
|
|
1681
|
+
const entry = this.ledger[outRef.txHash + outRef.outputIndex];
|
|
1682
|
+
return entry && !entry.spent ? entry.utxo : [];
|
|
1683
|
+
})
|
|
1362
1684
|
);
|
|
1363
1685
|
}
|
|
1364
1686
|
getUtxoByUnit(unit) {
|
|
1365
1687
|
const utxos = Object.values(this.ledger).flatMap(
|
|
1366
|
-
({ utxo }) => utxo.assets[unit] > 0n ? utxo : []
|
|
1688
|
+
({ utxo, spent }) => !spent && utxo.assets[unit] > 0n ? utxo : []
|
|
1367
1689
|
);
|
|
1368
1690
|
if (utxos.length > 1) {
|
|
1369
1691
|
throw new Error("Unit needs to be an NFT or only held by one address.");
|
|
1370
1692
|
}
|
|
1371
1693
|
return Promise.resolve(utxos[0]);
|
|
1372
1694
|
}
|
|
1695
|
+
getRewardAccount(rewardAddress) {
|
|
1696
|
+
const account = this.chain[rewardAddress];
|
|
1697
|
+
return Promise.resolve({
|
|
1698
|
+
registered: account?.registeredStake ?? false,
|
|
1699
|
+
poolId: account?.delegation.poolId ?? null,
|
|
1700
|
+
rewards: account?.delegation.rewards ?? 0n
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1373
1703
|
getDelegation(rewardAddress) {
|
|
1374
1704
|
return Promise.resolve({
|
|
1375
1705
|
poolId: this.chain[rewardAddress]?.delegation?.poolId || null,
|
|
@@ -1377,12 +1707,34 @@ var Emulator = class {
|
|
|
1377
1707
|
});
|
|
1378
1708
|
}
|
|
1379
1709
|
awaitTx(txHash) {
|
|
1380
|
-
if (this.
|
|
1710
|
+
if (this.transactionHistory[txHash]?.status === "pending") {
|
|
1381
1711
|
this.awaitBlock();
|
|
1382
1712
|
return Promise.resolve(true);
|
|
1383
1713
|
}
|
|
1384
1714
|
return Promise.resolve(true);
|
|
1385
1715
|
}
|
|
1716
|
+
getTransactionStatus(txHash, options = {}) {
|
|
1717
|
+
if (options.signal?.aborted) {
|
|
1718
|
+
return Promise.reject(
|
|
1719
|
+
options.signal.reason instanceof Error ? options.signal.reason : new DOMException("The operation was aborted.", "AbortError")
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
const status = this.transactionHistory[txHash];
|
|
1723
|
+
if (!status) return Promise.resolve({ status: "not_found", txHash });
|
|
1724
|
+
if (status.status === "pending") {
|
|
1725
|
+
return Promise.resolve({ status: "pending", txHash });
|
|
1726
|
+
}
|
|
1727
|
+
return Promise.resolve({
|
|
1728
|
+
status: "confirmed",
|
|
1729
|
+
txHash,
|
|
1730
|
+
confirmation: {
|
|
1731
|
+
txHash,
|
|
1732
|
+
blockHeight: status.blockHeight,
|
|
1733
|
+
slot: status.slot,
|
|
1734
|
+
confirmations: this.blockHeight - status.blockHeight + 1
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1386
1738
|
/**
|
|
1387
1739
|
* Emulates the behaviour of the reward distribution at epoch boundaries.
|
|
1388
1740
|
* Stake keys need to be registered and delegated like on a real chain in order to receive rewards.
|
|
@@ -2063,6 +2415,7 @@ It does not exist or was already spent.`
|
|
|
2063
2415
|
for (const [datumHash, datum] of Object.entries(datumTable)) {
|
|
2064
2416
|
this.datumTable[datumHash] = datum;
|
|
2065
2417
|
}
|
|
2418
|
+
this.transactionHistory[txHash] = { status: "pending" };
|
|
2066
2419
|
return Promise.resolve(txHash);
|
|
2067
2420
|
}
|
|
2068
2421
|
async evaluateTx(tx, additionalUTxOs) {
|
|
@@ -2318,21 +2671,30 @@ var Maestro = class {
|
|
|
2318
2671
|
);
|
|
2319
2672
|
return utxos.map(this.maestroUtxoToUtxo);
|
|
2320
2673
|
}
|
|
2321
|
-
async
|
|
2322
|
-
const
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
)
|
|
2326
|
-
|
|
2327
|
-
return { poolId: null, rewards: 0n };
|
|
2674
|
+
async getRewardAccount(rewardAddress) {
|
|
2675
|
+
const response = await fetch(`${this.url}/accounts/${rewardAddress}`, {
|
|
2676
|
+
headers: this.requireAmountsAsStrings(this.commonHeaders())
|
|
2677
|
+
});
|
|
2678
|
+
if (response.status === 404) {
|
|
2679
|
+
return { registered: false, poolId: null, rewards: 0n };
|
|
2328
2680
|
}
|
|
2329
|
-
|
|
2681
|
+
if (!response.ok) {
|
|
2682
|
+
throw new Error(
|
|
2683
|
+
`Could not fetch reward account from Maestro. Received status code: ${response.status}`
|
|
2684
|
+
);
|
|
2685
|
+
}
|
|
2686
|
+
const timestampedResult = await response.json();
|
|
2330
2687
|
const result = timestampedResult.data;
|
|
2331
2688
|
return {
|
|
2689
|
+
registered: result.registered,
|
|
2332
2690
|
poolId: result.delegated_pool || null,
|
|
2333
2691
|
rewards: BigInt(result.rewards_available)
|
|
2334
2692
|
};
|
|
2335
2693
|
}
|
|
2694
|
+
async getDelegation(rewardAddress) {
|
|
2695
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
2696
|
+
return { poolId, rewards };
|
|
2697
|
+
}
|
|
2336
2698
|
async getDatum(datumHash) {
|
|
2337
2699
|
const timestampedResultResponse = await fetch(
|
|
2338
2700
|
`${this.url}/datums/${datumHash}`,
|
|
@@ -2370,6 +2732,42 @@ var Maestro = class {
|
|
|
2370
2732
|
}, checkInterval);
|
|
2371
2733
|
});
|
|
2372
2734
|
}
|
|
2735
|
+
async getTransactionStatus(txHash, options = {}) {
|
|
2736
|
+
const response = await fetch(`${this.url}/txmanager/${txHash}/state`, {
|
|
2737
|
+
headers: this.commonHeaders(),
|
|
2738
|
+
signal: options.signal
|
|
2739
|
+
});
|
|
2740
|
+
if (response.status === 404) return { status: "not_found", txHash };
|
|
2741
|
+
if (!response.ok) {
|
|
2742
|
+
throw new Error(
|
|
2743
|
+
`Could not fetch transaction status from Maestro. Received status code: ${response.status}`
|
|
2744
|
+
);
|
|
2745
|
+
}
|
|
2746
|
+
const result = await response.json();
|
|
2747
|
+
switch (result.status) {
|
|
2748
|
+
case "pending":
|
|
2749
|
+
return { status: "pending", txHash };
|
|
2750
|
+
case "confirmed":
|
|
2751
|
+
return {
|
|
2752
|
+
status: "confirmed",
|
|
2753
|
+
txHash,
|
|
2754
|
+
confirmation: {
|
|
2755
|
+
txHash,
|
|
2756
|
+
confirmations: result.confirmations
|
|
2757
|
+
}
|
|
2758
|
+
};
|
|
2759
|
+
case "failed":
|
|
2760
|
+
return {
|
|
2761
|
+
status: "failed",
|
|
2762
|
+
txHash,
|
|
2763
|
+
reason: result.reason ?? result.error
|
|
2764
|
+
};
|
|
2765
|
+
default:
|
|
2766
|
+
throw new Error(
|
|
2767
|
+
`Maestro returned an unknown transaction status: ${String(result.status)}`
|
|
2768
|
+
);
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2373
2771
|
async submitTx(tx) {
|
|
2374
2772
|
let queryUrl = `${this.url}/txmanager`;
|
|
2375
2773
|
queryUrl += this.turboSubmit ? "/turbosubmit" : "";
|
|
@@ -2719,8 +3117,13 @@ var AssetAddressSchema = S4.Struct({
|
|
|
2719
3117
|
quantity: S4.String
|
|
2720
3118
|
});
|
|
2721
3119
|
var AccountInfoSchema = S4.Struct({
|
|
3120
|
+
status: S4.Literal("registered", "not registered"),
|
|
2722
3121
|
delegated_pool: S4.NullOr(S4.String),
|
|
2723
|
-
rewards_available: S4.
|
|
3122
|
+
rewards_available: S4.String
|
|
3123
|
+
});
|
|
3124
|
+
var TxStatusSchema = S4.Struct({
|
|
3125
|
+
tx_hash: S4.String,
|
|
3126
|
+
num_confirmations: S4.NullOr(S4.Number)
|
|
2724
3127
|
});
|
|
2725
3128
|
var DatumInfo = S4.Struct({
|
|
2726
3129
|
bytes: S4.String
|
|
@@ -2786,9 +3189,9 @@ var getUtxosEffect = (baseUrl, addressOrCredential, headers) => {
|
|
|
2786
3189
|
};
|
|
2787
3190
|
|
|
2788
3191
|
// src/koios.ts
|
|
2789
|
-
import { Data
|
|
3192
|
+
import { Data, Effect as Effect4, pipe as pipe5, Schedule as Schedule2, Schema as S5 } from "effect";
|
|
2790
3193
|
import { FetchHttpClient as FetchHttpClient3 } from "@effect/platform";
|
|
2791
|
-
var KoiosError = class extends
|
|
3194
|
+
var KoiosError = class extends Data.TaggedError("KoiosError") {
|
|
2792
3195
|
get message() {
|
|
2793
3196
|
return `${this.cause}`;
|
|
2794
3197
|
}
|
|
@@ -2957,7 +3360,7 @@ var Koios = class {
|
|
|
2957
3360
|
return [];
|
|
2958
3361
|
}
|
|
2959
3362
|
}
|
|
2960
|
-
async
|
|
3363
|
+
async getRewardAccount(rewardAddress) {
|
|
2961
3364
|
const body = {
|
|
2962
3365
|
_stake_addresses: [rewardAddress]
|
|
2963
3366
|
};
|
|
@@ -2972,18 +3375,24 @@ var Koios = class {
|
|
|
2972
3375
|
),
|
|
2973
3376
|
// Allows for dependency injection and easier testing
|
|
2974
3377
|
Effect4.provide(FetchHttpClient3.layer),
|
|
2975
|
-
Effect4.flatMap(
|
|
2976
|
-
(result2) => result2.length === 0 ? Effect4.fail("No Delegation Found by Reward Address") : Effect4.succeed(result2[0])
|
|
2977
|
-
),
|
|
2978
3378
|
Effect4.timeout(1e4),
|
|
2979
3379
|
Effect4.catchAllCause((cause) => new KoiosError({ cause })),
|
|
2980
3380
|
Effect4.runPromise
|
|
2981
3381
|
);
|
|
3382
|
+
const account = result[0];
|
|
3383
|
+
if (!account) {
|
|
3384
|
+
return { registered: false, poolId: null, rewards: 0n };
|
|
3385
|
+
}
|
|
2982
3386
|
return {
|
|
2983
|
-
|
|
2984
|
-
|
|
3387
|
+
registered: account.status === "registered",
|
|
3388
|
+
poolId: account.delegated_pool || null,
|
|
3389
|
+
rewards: BigInt(account.rewards_available)
|
|
2985
3390
|
};
|
|
2986
3391
|
}
|
|
3392
|
+
async getDelegation(rewardAddress) {
|
|
3393
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
3394
|
+
return { poolId, rewards };
|
|
3395
|
+
}
|
|
2987
3396
|
async getDatum(datumHash) {
|
|
2988
3397
|
const url = `${this.baseUrl}/datum_info`;
|
|
2989
3398
|
const body = {
|
|
@@ -3030,6 +3439,38 @@ var Koios = class {
|
|
|
3030
3439
|
);
|
|
3031
3440
|
return result;
|
|
3032
3441
|
}
|
|
3442
|
+
async getTransactionStatus(txHash, options = {}) {
|
|
3443
|
+
const url = `${this.baseUrl}/tx_status`;
|
|
3444
|
+
const body = { _tx_hashes: [txHash] };
|
|
3445
|
+
const bearerToken = this.token ? { Authorization: `Bearer ${this.token}` } : void 0;
|
|
3446
|
+
const response = await fetch(url, {
|
|
3447
|
+
method: "POST",
|
|
3448
|
+
headers: { "Content-Type": "application/json", ...bearerToken },
|
|
3449
|
+
body: JSON.stringify(body),
|
|
3450
|
+
signal: options.signal
|
|
3451
|
+
});
|
|
3452
|
+
if (response.status === 404) return { status: "not_found", txHash };
|
|
3453
|
+
if (!response.ok) {
|
|
3454
|
+
throw new Error(
|
|
3455
|
+
`Could not fetch transaction status from Koios. Received status code: ${response.status}`
|
|
3456
|
+
);
|
|
3457
|
+
}
|
|
3458
|
+
const result = S5.decodeUnknownSync(S5.Array(TxStatusSchema))(
|
|
3459
|
+
await response.json()
|
|
3460
|
+
);
|
|
3461
|
+
const status = result[0];
|
|
3462
|
+
if (!status || status.num_confirmations === null) {
|
|
3463
|
+
return { status: "not_found", txHash };
|
|
3464
|
+
}
|
|
3465
|
+
return {
|
|
3466
|
+
status: "confirmed",
|
|
3467
|
+
txHash,
|
|
3468
|
+
confirmation: {
|
|
3469
|
+
txHash,
|
|
3470
|
+
confirmations: status.num_confirmations
|
|
3471
|
+
}
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3033
3474
|
async submitTx(tx) {
|
|
3034
3475
|
const url = `${this.baseUrl}/submittx`;
|
|
3035
3476
|
const body = fromHex4(tx);
|
|
@@ -3085,6 +3526,8 @@ export {
|
|
|
3085
3526
|
Kupmios,
|
|
3086
3527
|
KupmiosError,
|
|
3087
3528
|
Maestro,
|
|
3529
|
+
OgmiosJsonRpcError,
|
|
3088
3530
|
generateEmulatorAccount,
|
|
3089
|
-
generateEmulatorAccountFromPrivateKey
|
|
3531
|
+
generateEmulatorAccountFromPrivateKey,
|
|
3532
|
+
isEmulatorProvider
|
|
3090
3533
|
};
|