@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 +635 -167
- package/dist/index.d.cts +70 -10
- package/dist/index.d.ts +70 -10
- package/dist/index.js +635 -169
- 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
|
};
|
|
@@ -486,6 +626,28 @@ var TupleNumberFromString = S.compose(
|
|
|
486
626
|
S.split("/"),
|
|
487
627
|
S.Array(S.NumberFromString)
|
|
488
628
|
);
|
|
629
|
+
var MaxReferenceScriptsSizeSchema = S.Struct({
|
|
630
|
+
bytes: S.Number
|
|
631
|
+
});
|
|
632
|
+
function normalizeProtocolParameters(value) {
|
|
633
|
+
const legacy = value.maxReferenceScriptsSize;
|
|
634
|
+
const current = value.maxReferenceScriptsSizePerTransaction;
|
|
635
|
+
if (legacy === void 0 && current === void 0) {
|
|
636
|
+
return value;
|
|
637
|
+
}
|
|
638
|
+
const decode = S.decodeUnknownSync(MaxReferenceScriptsSizeSchema);
|
|
639
|
+
const legacyValue = legacy === void 0 ? void 0 : decode(legacy);
|
|
640
|
+
const currentValue = current === void 0 ? void 0 : decode(current);
|
|
641
|
+
if (legacyValue !== void 0 && currentValue !== void 0 && legacyValue.bytes !== currentValue.bytes) {
|
|
642
|
+
throw new Error(
|
|
643
|
+
"Conflicting Ogmios protocol parameters: maxReferenceScriptsSize and maxReferenceScriptsSizePerTransaction differ"
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
return {
|
|
647
|
+
...value,
|
|
648
|
+
maxReferenceScriptsSize: legacyValue ?? currentValue
|
|
649
|
+
};
|
|
650
|
+
}
|
|
489
651
|
var ProtocolParametersSchema = S.Struct({
|
|
490
652
|
minFeeCoefficient: S.Number,
|
|
491
653
|
minFeeReferenceScripts: S.Struct({
|
|
@@ -493,9 +655,7 @@ var ProtocolParametersSchema = S.Struct({
|
|
|
493
655
|
range: S.Number,
|
|
494
656
|
multiplier: S.Number
|
|
495
657
|
}),
|
|
496
|
-
maxReferenceScriptsSize:
|
|
497
|
-
bytes: S.Number
|
|
498
|
-
}),
|
|
658
|
+
maxReferenceScriptsSize: MaxReferenceScriptsSizeSchema,
|
|
499
659
|
stakePoolVotingThresholds: S.Struct({
|
|
500
660
|
noConfidence: TupleNumberFromString,
|
|
501
661
|
constitutionalCommittee: S.Struct({
|
|
@@ -575,7 +735,7 @@ var LegacyDelegationSummarySchema = S.Struct({
|
|
|
575
735
|
deposit: RewardAccountAdaSchema
|
|
576
736
|
});
|
|
577
737
|
var RewardAccountSummarySchema = S.Struct({
|
|
578
|
-
from: S.optional(S.Literal("key", "script")),
|
|
738
|
+
from: S.optional(S.Literal("key", "verificationKey", "script")),
|
|
579
739
|
credential: S.optional(S.String),
|
|
580
740
|
stakePool: S.optional(S.NullOr(S.Struct({ id: S.String }))),
|
|
581
741
|
rewards: RewardAccountAdaSchema,
|
|
@@ -771,6 +931,33 @@ var makePostAsJson = (url, data, schema, headers) => pipe2(
|
|
|
771
931
|
// Prevents resource leaks and ensures clean request termination
|
|
772
932
|
Effect.scoped
|
|
773
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
|
+
);
|
|
774
961
|
var makePostAsUint8Array = (url, data, schema, headers) => pipe2(
|
|
775
962
|
// Initiate a POST request to the specified URL
|
|
776
963
|
HttpClientRequest.post(url),
|
|
@@ -792,10 +979,23 @@ var makePostAsUint8Array = (url, data, schema, headers) => pipe2(
|
|
|
792
979
|
|
|
793
980
|
// src/kupmios.ts
|
|
794
981
|
import { FetchHttpClient } from "@effect/platform";
|
|
795
|
-
var
|
|
796
|
-
|
|
797
|
-
|
|
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
|
+
});
|
|
798
997
|
}
|
|
998
|
+
throw toKupmiosError(Cause.squash(exit.cause), protocol, operation);
|
|
799
999
|
};
|
|
800
1000
|
var Kupmios = class {
|
|
801
1001
|
kupoUrl;
|
|
@@ -814,22 +1014,32 @@ var Kupmios = class {
|
|
|
814
1014
|
id: null
|
|
815
1015
|
};
|
|
816
1016
|
const schema = JSONRPCResponseSchema(
|
|
817
|
-
|
|
1017
|
+
S3.Record({ key: S3.String, value: S3.Unknown })
|
|
818
1018
|
);
|
|
819
|
-
const response = await
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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)
|
|
825
1030
|
),
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1031
|
+
"ogmios",
|
|
1032
|
+
"queryLedgerState/protocolParameters"
|
|
1033
|
+
);
|
|
1034
|
+
const result = getJSONRPCResult(
|
|
1035
|
+
response.body,
|
|
1036
|
+
data.method,
|
|
1037
|
+
response
|
|
830
1038
|
);
|
|
831
|
-
const
|
|
832
|
-
|
|
1039
|
+
const protocolParameters = S3.decodeUnknownSync(
|
|
1040
|
+
ProtocolParametersSchema
|
|
1041
|
+
)(normalizeProtocolParameters(result));
|
|
1042
|
+
return toProtocolParameters(protocolParameters);
|
|
833
1043
|
}
|
|
834
1044
|
async getTreasury() {
|
|
835
1045
|
const data = {
|
|
@@ -841,19 +1051,26 @@ var Kupmios = class {
|
|
|
841
1051
|
const schema = JSONRPCResponseSchema(
|
|
842
1052
|
TreasuryAndReservesSchema
|
|
843
1053
|
);
|
|
844
|
-
const response = await
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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)
|
|
850
1065
|
),
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
1066
|
+
"ogmios",
|
|
1067
|
+
"queryLedgerState/treasuryAndReserves"
|
|
1068
|
+
);
|
|
1069
|
+
const result = getJSONRPCResult(
|
|
1070
|
+
response.body,
|
|
1071
|
+
data.method,
|
|
1072
|
+
response
|
|
855
1073
|
);
|
|
856
|
-
const result = getJSONRPCResult(response);
|
|
857
1074
|
return lovelaceAmountToBigInt(result.treasury.ada.lovelace);
|
|
858
1075
|
}
|
|
859
1076
|
async getUtxos(addressOrCredential) {
|
|
@@ -861,15 +1078,18 @@ var Kupmios = class {
|
|
|
861
1078
|
const queryPredicate = isAddress ? addressOrCredential : addressOrCredential.hash;
|
|
862
1079
|
const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent`;
|
|
863
1080
|
const schema = S3.Array(UTxOSchema);
|
|
864
|
-
const utxos = await
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
(
|
|
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)
|
|
868
1090
|
),
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
Effect2.provide(FetchHttpClient.layer),
|
|
872
|
-
Effect2.runPromise
|
|
1091
|
+
"kupo",
|
|
1092
|
+
"getUtxos"
|
|
873
1093
|
);
|
|
874
1094
|
return utxos;
|
|
875
1095
|
}
|
|
@@ -879,31 +1099,62 @@ var Kupmios = class {
|
|
|
879
1099
|
const { policyId, assetName } = fromUnit2(unit);
|
|
880
1100
|
const pattern = `${this.kupoUrl}/matches/${queryPredicate}${isAddress ? "" : "/*"}?unspent&policy_id=${policyId}${assetName ? `&asset_name=${assetName}` : ""}`;
|
|
881
1101
|
const schema = S3.Array(UTxOSchema);
|
|
882
|
-
const utxos = await
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
(
|
|
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)
|
|
886
1111
|
),
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
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"
|
|
891
1140
|
);
|
|
892
|
-
return utxos;
|
|
893
1141
|
}
|
|
894
1142
|
async getUtxoByUnit(unit) {
|
|
895
1143
|
const { policyId, assetName } = fromUnit2(unit);
|
|
896
|
-
const pattern = `${this.kupoUrl}/matches/${policyId}.${assetName
|
|
1144
|
+
const pattern = `${this.kupoUrl}/matches/${policyId}.${assetName ?? ""}?unspent`;
|
|
897
1145
|
const schema = S3.Array(UTxOSchema);
|
|
898
|
-
const utxos = await
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
(
|
|
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)
|
|
902
1155
|
),
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
Effect2.provide(FetchHttpClient.layer),
|
|
906
|
-
Effect2.runPromise
|
|
1156
|
+
"kupo",
|
|
1157
|
+
"getUtxoByUnit"
|
|
907
1158
|
);
|
|
908
1159
|
if (utxos.length === 0) {
|
|
909
1160
|
throw new Error("Unit not found.");
|
|
@@ -927,11 +1178,13 @@ var Kupmios = class {
|
|
|
927
1178
|
(u) => kupmiosUtxosToUtxos(this.kupoUrl, u, this.headers?.kupoHeader)
|
|
928
1179
|
),
|
|
929
1180
|
Effect2.timeout(1e4),
|
|
930
|
-
|
|
1181
|
+
catchProviderError("kupo", "getUtxosByOutRef")
|
|
931
1182
|
)
|
|
932
1183
|
);
|
|
933
|
-
const utxos = await
|
|
934
|
-
pipe3(program, Effect2.provide(FetchHttpClient.layer))
|
|
1184
|
+
const utxos = await runProviderEffect(
|
|
1185
|
+
pipe3(program, Effect2.provide(FetchHttpClient.layer)),
|
|
1186
|
+
"kupo",
|
|
1187
|
+
"getUtxosByOutRef"
|
|
935
1188
|
);
|
|
936
1189
|
return _Array.flatten(utxos).filter(
|
|
937
1190
|
(utxo) => outRefs.some(
|
|
@@ -939,7 +1192,7 @@ var Kupmios = class {
|
|
|
939
1192
|
)
|
|
940
1193
|
);
|
|
941
1194
|
}
|
|
942
|
-
async
|
|
1195
|
+
async getRewardAccount(rewardAddress) {
|
|
943
1196
|
const data = {
|
|
944
1197
|
jsonrpc: "2.0",
|
|
945
1198
|
method: "queryLedgerState/rewardAccountSummaries",
|
|
@@ -947,50 +1200,95 @@ var Kupmios = class {
|
|
|
947
1200
|
id: null
|
|
948
1201
|
};
|
|
949
1202
|
const schema = JSONRPCResponseSchema(Delegation);
|
|
950
|
-
const response = await
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
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")
|
|
956
1214
|
),
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
Effect2.catchAll((cause) => new KupmiosError({ cause })),
|
|
960
|
-
Effect2.runPromise
|
|
1215
|
+
"ogmios",
|
|
1216
|
+
"queryLedgerState/rewardAccountSummaries"
|
|
961
1217
|
);
|
|
962
|
-
const result = getJSONRPCResult(
|
|
963
|
-
|
|
1218
|
+
const result = getJSONRPCResult(
|
|
1219
|
+
response.body,
|
|
1220
|
+
data.method,
|
|
1221
|
+
response
|
|
1222
|
+
);
|
|
1223
|
+
return toRewardAccountState(result);
|
|
1224
|
+
}
|
|
1225
|
+
async getDelegation(rewardAddress) {
|
|
1226
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
1227
|
+
return { poolId, rewards };
|
|
964
1228
|
}
|
|
965
1229
|
async getDatum(datumHash) {
|
|
966
1230
|
const pattern = `${this.kupoUrl}/datums/${datumHash}`;
|
|
967
1231
|
const schema = DatumSchema;
|
|
968
|
-
const result = await
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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"
|
|
975
1242
|
);
|
|
976
1243
|
return result.datum;
|
|
977
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
|
+
}
|
|
978
1273
|
async awaitTx(txHash, checkInterval = 2e4) {
|
|
979
|
-
const pattern = `${this.kupoUrl}/matches/*@${txHash}
|
|
1274
|
+
const pattern = `${this.kupoUrl}/matches/*@${txHash}`;
|
|
980
1275
|
const schema = S3.Array(UTxOSchema).annotations({
|
|
981
1276
|
identifier: "Array<KupmiosSchema.KupoUTxO>"
|
|
982
1277
|
});
|
|
983
|
-
const result = await
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
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"
|
|
994
1292
|
);
|
|
995
1293
|
return result;
|
|
996
1294
|
}
|
|
@@ -1010,19 +1308,26 @@ var Kupmios = class {
|
|
|
1010
1308
|
})
|
|
1011
1309
|
})
|
|
1012
1310
|
);
|
|
1013
|
-
const response = await
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
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")
|
|
1019
1322
|
),
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1323
|
+
"ogmios",
|
|
1324
|
+
"submitTransaction"
|
|
1325
|
+
);
|
|
1326
|
+
const result = getJSONRPCResult(
|
|
1327
|
+
response.body,
|
|
1328
|
+
data.method,
|
|
1329
|
+
response
|
|
1024
1330
|
);
|
|
1025
|
-
const result = getJSONRPCResult(response);
|
|
1026
1331
|
return result.transaction.id;
|
|
1027
1332
|
}
|
|
1028
1333
|
async evaluateTx(tx, additionalUTxOs) {
|
|
@@ -1036,19 +1341,26 @@ var Kupmios = class {
|
|
|
1036
1341
|
id: null
|
|
1037
1342
|
};
|
|
1038
1343
|
const schema = JSONRPCResponseSchema(S3.Array(RedeemerSchema));
|
|
1039
|
-
const response = await
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
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")
|
|
1045
1355
|
),
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1356
|
+
"ogmios",
|
|
1357
|
+
"evaluateTransaction"
|
|
1358
|
+
);
|
|
1359
|
+
const result = getJSONRPCResult(
|
|
1360
|
+
response.body,
|
|
1361
|
+
data.method,
|
|
1362
|
+
response
|
|
1050
1363
|
);
|
|
1051
|
-
const result = getJSONRPCResult(response);
|
|
1052
1364
|
const evalRedeemers = result.map((item) => ({
|
|
1053
1365
|
ex_units: {
|
|
1054
1366
|
mem: item.budget.memory,
|
|
@@ -1150,15 +1462,13 @@ var toProtocolParameters = (result) => {
|
|
|
1150
1462
|
}
|
|
1151
1463
|
};
|
|
1152
1464
|
};
|
|
1153
|
-
var
|
|
1154
|
-
|
|
1155
|
-
return { poolId: null, rewards: 0n };
|
|
1156
|
-
}
|
|
1157
|
-
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;
|
|
1158
1467
|
if (!delegation) {
|
|
1159
|
-
return { poolId: null, rewards: 0n };
|
|
1468
|
+
return { registered: false, poolId: null, rewards: 0n };
|
|
1160
1469
|
}
|
|
1161
1470
|
return {
|
|
1471
|
+
registered: true,
|
|
1162
1472
|
poolId: "stakePool" in delegation ? delegation.stakePool?.id || null : delegation.delegate?.id || null,
|
|
1163
1473
|
rewards: BigInt(delegation.rewards.ada.lovelace)
|
|
1164
1474
|
};
|
|
@@ -1196,6 +1506,12 @@ import {
|
|
|
1196
1506
|
import { coreToUtxo, getAddressDetails } from "@lucid-evolution/utils";
|
|
1197
1507
|
import { fromHex as fromHex2 } from "@lucid-evolution/core-utils";
|
|
1198
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
|
+
);
|
|
1199
1515
|
function generateEmulatorAccountFromPrivateKey(assets) {
|
|
1200
1516
|
const privateKey = CML.PrivateKey.generate_ed25519().to_bech32();
|
|
1201
1517
|
const priv = CML.PrivateKey.from_bech32(privateKey);
|
|
@@ -1225,6 +1541,7 @@ function generateEmulatorAccount(assets) {
|
|
|
1225
1541
|
};
|
|
1226
1542
|
}
|
|
1227
1543
|
var Emulator = class {
|
|
1544
|
+
[EMULATOR_PROVIDER_BRAND] = true;
|
|
1228
1545
|
ledger;
|
|
1229
1546
|
mempool = {};
|
|
1230
1547
|
/**
|
|
@@ -1238,6 +1555,7 @@ var Emulator = class {
|
|
|
1238
1555
|
protocolParameters;
|
|
1239
1556
|
datumTable = {};
|
|
1240
1557
|
treasury;
|
|
1558
|
+
transactionHistory = {};
|
|
1241
1559
|
constructor(accounts, protocolParameters = PROTOCOL_PARAMETERS_DEFAULT, treasury = 0n) {
|
|
1242
1560
|
const GENESIS_HASH = "00".repeat(32);
|
|
1243
1561
|
this.blockHeight = 0;
|
|
@@ -1273,12 +1591,27 @@ var Emulator = class {
|
|
|
1273
1591
|
now() {
|
|
1274
1592
|
return this.time;
|
|
1275
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
|
+
}
|
|
1276
1605
|
awaitSlot(length = 1) {
|
|
1277
1606
|
this.slot += length;
|
|
1278
1607
|
this.time += length * 1e3;
|
|
1279
1608
|
const currentHeight = this.blockHeight;
|
|
1280
1609
|
this.blockHeight = Math.floor(this.slot / 20);
|
|
1281
1610
|
if (this.blockHeight > currentHeight) {
|
|
1611
|
+
this.confirmPendingTransactions(
|
|
1612
|
+
currentHeight + 1,
|
|
1613
|
+
(currentHeight + 1) * 20
|
|
1614
|
+
);
|
|
1282
1615
|
for (const [outRef, { utxo, spent }] of Object.entries(this.mempool)) {
|
|
1283
1616
|
this.ledger[outRef] = { utxo, spent };
|
|
1284
1617
|
}
|
|
@@ -1289,9 +1622,14 @@ var Emulator = class {
|
|
|
1289
1622
|
}
|
|
1290
1623
|
}
|
|
1291
1624
|
awaitBlock(height = 1) {
|
|
1625
|
+
const previousHeight = this.blockHeight;
|
|
1626
|
+
const previousSlot = this.slot;
|
|
1292
1627
|
this.blockHeight += height;
|
|
1293
1628
|
this.slot += height * 20;
|
|
1294
1629
|
this.time += height * 20 * 1e3;
|
|
1630
|
+
if (height > 0) {
|
|
1631
|
+
this.confirmPendingTransactions(previousHeight + 1, previousSlot + 20);
|
|
1632
|
+
}
|
|
1295
1633
|
for (const [outRef, { utxo, spent }] of Object.entries(this.mempool)) {
|
|
1296
1634
|
this.ledger[outRef] = { utxo, spent };
|
|
1297
1635
|
}
|
|
@@ -1301,14 +1639,17 @@ var Emulator = class {
|
|
|
1301
1639
|
this.mempool = {};
|
|
1302
1640
|
}
|
|
1303
1641
|
getUtxos(addressOrCredential) {
|
|
1304
|
-
const utxos = Object.values(this.ledger).flatMap(
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
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
|
+
}
|
|
1310
1651
|
}
|
|
1311
|
-
|
|
1652
|
+
);
|
|
1312
1653
|
return Promise.resolve(utxos);
|
|
1313
1654
|
}
|
|
1314
1655
|
getProtocolParameters() {
|
|
@@ -1321,32 +1662,44 @@ var Emulator = class {
|
|
|
1321
1662
|
return Promise.resolve(this.datumTable[datumHash]);
|
|
1322
1663
|
}
|
|
1323
1664
|
getUtxosWithUnit(addressOrCredential, unit) {
|
|
1324
|
-
const utxos = Object.values(this.ledger).flatMap(
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
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
|
+
}
|
|
1330
1674
|
}
|
|
1331
|
-
|
|
1675
|
+
);
|
|
1332
1676
|
return Promise.resolve(utxos);
|
|
1333
1677
|
}
|
|
1334
1678
|
getUtxosByOutRef(outRefs) {
|
|
1335
1679
|
return Promise.resolve(
|
|
1336
|
-
outRefs.flatMap(
|
|
1337
|
-
|
|
1338
|
-
|
|
1680
|
+
outRefs.flatMap((outRef) => {
|
|
1681
|
+
const entry = this.ledger[outRef.txHash + outRef.outputIndex];
|
|
1682
|
+
return entry && !entry.spent ? entry.utxo : [];
|
|
1683
|
+
})
|
|
1339
1684
|
);
|
|
1340
1685
|
}
|
|
1341
1686
|
getUtxoByUnit(unit) {
|
|
1342
1687
|
const utxos = Object.values(this.ledger).flatMap(
|
|
1343
|
-
({ utxo }) => utxo.assets[unit] > 0n ? utxo : []
|
|
1688
|
+
({ utxo, spent }) => !spent && utxo.assets[unit] > 0n ? utxo : []
|
|
1344
1689
|
);
|
|
1345
1690
|
if (utxos.length > 1) {
|
|
1346
1691
|
throw new Error("Unit needs to be an NFT or only held by one address.");
|
|
1347
1692
|
}
|
|
1348
1693
|
return Promise.resolve(utxos[0]);
|
|
1349
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
|
+
}
|
|
1350
1703
|
getDelegation(rewardAddress) {
|
|
1351
1704
|
return Promise.resolve({
|
|
1352
1705
|
poolId: this.chain[rewardAddress]?.delegation?.poolId || null,
|
|
@@ -1354,12 +1707,34 @@ var Emulator = class {
|
|
|
1354
1707
|
});
|
|
1355
1708
|
}
|
|
1356
1709
|
awaitTx(txHash) {
|
|
1357
|
-
if (this.
|
|
1710
|
+
if (this.transactionHistory[txHash]?.status === "pending") {
|
|
1358
1711
|
this.awaitBlock();
|
|
1359
1712
|
return Promise.resolve(true);
|
|
1360
1713
|
}
|
|
1361
1714
|
return Promise.resolve(true);
|
|
1362
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
|
+
}
|
|
1363
1738
|
/**
|
|
1364
1739
|
* Emulates the behaviour of the reward distribution at epoch boundaries.
|
|
1365
1740
|
* Stake keys need to be registered and delegated like on a real chain in order to receive rewards.
|
|
@@ -2040,6 +2415,7 @@ It does not exist or was already spent.`
|
|
|
2040
2415
|
for (const [datumHash, datum] of Object.entries(datumTable)) {
|
|
2041
2416
|
this.datumTable[datumHash] = datum;
|
|
2042
2417
|
}
|
|
2418
|
+
this.transactionHistory[txHash] = { status: "pending" };
|
|
2043
2419
|
return Promise.resolve(txHash);
|
|
2044
2420
|
}
|
|
2045
2421
|
async evaluateTx(tx, additionalUTxOs) {
|
|
@@ -2295,21 +2671,30 @@ var Maestro = class {
|
|
|
2295
2671
|
);
|
|
2296
2672
|
return utxos.map(this.maestroUtxoToUtxo);
|
|
2297
2673
|
}
|
|
2298
|
-
async
|
|
2299
|
-
const
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
)
|
|
2303
|
-
|
|
2304
|
-
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 };
|
|
2305
2680
|
}
|
|
2306
|
-
|
|
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();
|
|
2307
2687
|
const result = timestampedResult.data;
|
|
2308
2688
|
return {
|
|
2689
|
+
registered: result.registered,
|
|
2309
2690
|
poolId: result.delegated_pool || null,
|
|
2310
2691
|
rewards: BigInt(result.rewards_available)
|
|
2311
2692
|
};
|
|
2312
2693
|
}
|
|
2694
|
+
async getDelegation(rewardAddress) {
|
|
2695
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
2696
|
+
return { poolId, rewards };
|
|
2697
|
+
}
|
|
2313
2698
|
async getDatum(datumHash) {
|
|
2314
2699
|
const timestampedResultResponse = await fetch(
|
|
2315
2700
|
`${this.url}/datums/${datumHash}`,
|
|
@@ -2347,6 +2732,42 @@ var Maestro = class {
|
|
|
2347
2732
|
}, checkInterval);
|
|
2348
2733
|
});
|
|
2349
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
|
+
}
|
|
2350
2771
|
async submitTx(tx) {
|
|
2351
2772
|
let queryUrl = `${this.url}/txmanager`;
|
|
2352
2773
|
queryUrl += this.turboSubmit ? "/turbosubmit" : "";
|
|
@@ -2696,8 +3117,13 @@ var AssetAddressSchema = S4.Struct({
|
|
|
2696
3117
|
quantity: S4.String
|
|
2697
3118
|
});
|
|
2698
3119
|
var AccountInfoSchema = S4.Struct({
|
|
3120
|
+
status: S4.Literal("registered", "not registered"),
|
|
2699
3121
|
delegated_pool: S4.NullOr(S4.String),
|
|
2700
|
-
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)
|
|
2701
3127
|
});
|
|
2702
3128
|
var DatumInfo = S4.Struct({
|
|
2703
3129
|
bytes: S4.String
|
|
@@ -2763,9 +3189,9 @@ var getUtxosEffect = (baseUrl, addressOrCredential, headers) => {
|
|
|
2763
3189
|
};
|
|
2764
3190
|
|
|
2765
3191
|
// src/koios.ts
|
|
2766
|
-
import { Data
|
|
3192
|
+
import { Data, Effect as Effect4, pipe as pipe5, Schedule as Schedule2, Schema as S5 } from "effect";
|
|
2767
3193
|
import { FetchHttpClient as FetchHttpClient3 } from "@effect/platform";
|
|
2768
|
-
var KoiosError = class extends
|
|
3194
|
+
var KoiosError = class extends Data.TaggedError("KoiosError") {
|
|
2769
3195
|
get message() {
|
|
2770
3196
|
return `${this.cause}`;
|
|
2771
3197
|
}
|
|
@@ -2934,7 +3360,7 @@ var Koios = class {
|
|
|
2934
3360
|
return [];
|
|
2935
3361
|
}
|
|
2936
3362
|
}
|
|
2937
|
-
async
|
|
3363
|
+
async getRewardAccount(rewardAddress) {
|
|
2938
3364
|
const body = {
|
|
2939
3365
|
_stake_addresses: [rewardAddress]
|
|
2940
3366
|
};
|
|
@@ -2949,18 +3375,24 @@ var Koios = class {
|
|
|
2949
3375
|
),
|
|
2950
3376
|
// Allows for dependency injection and easier testing
|
|
2951
3377
|
Effect4.provide(FetchHttpClient3.layer),
|
|
2952
|
-
Effect4.flatMap(
|
|
2953
|
-
(result2) => result2.length === 0 ? Effect4.fail("No Delegation Found by Reward Address") : Effect4.succeed(result2[0])
|
|
2954
|
-
),
|
|
2955
3378
|
Effect4.timeout(1e4),
|
|
2956
3379
|
Effect4.catchAllCause((cause) => new KoiosError({ cause })),
|
|
2957
3380
|
Effect4.runPromise
|
|
2958
3381
|
);
|
|
3382
|
+
const account = result[0];
|
|
3383
|
+
if (!account) {
|
|
3384
|
+
return { registered: false, poolId: null, rewards: 0n };
|
|
3385
|
+
}
|
|
2959
3386
|
return {
|
|
2960
|
-
|
|
2961
|
-
|
|
3387
|
+
registered: account.status === "registered",
|
|
3388
|
+
poolId: account.delegated_pool || null,
|
|
3389
|
+
rewards: BigInt(account.rewards_available)
|
|
2962
3390
|
};
|
|
2963
3391
|
}
|
|
3392
|
+
async getDelegation(rewardAddress) {
|
|
3393
|
+
const { poolId, rewards } = await this.getRewardAccount(rewardAddress);
|
|
3394
|
+
return { poolId, rewards };
|
|
3395
|
+
}
|
|
2964
3396
|
async getDatum(datumHash) {
|
|
2965
3397
|
const url = `${this.baseUrl}/datum_info`;
|
|
2966
3398
|
const body = {
|
|
@@ -3007,6 +3439,38 @@ var Koios = class {
|
|
|
3007
3439
|
);
|
|
3008
3440
|
return result;
|
|
3009
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
|
+
}
|
|
3010
3474
|
async submitTx(tx) {
|
|
3011
3475
|
const url = `${this.baseUrl}/submittx`;
|
|
3012
3476
|
const body = fromHex4(tx);
|
|
@@ -3062,6 +3526,8 @@ export {
|
|
|
3062
3526
|
Kupmios,
|
|
3063
3527
|
KupmiosError,
|
|
3064
3528
|
Maestro,
|
|
3529
|
+
OgmiosJsonRpcError,
|
|
3065
3530
|
generateEmulatorAccount,
|
|
3066
|
-
generateEmulatorAccountFromPrivateKey
|
|
3531
|
+
generateEmulatorAccountFromPrivateKey,
|
|
3532
|
+
isEmulatorProvider
|
|
3067
3533
|
};
|