@midnight-ntwrk/wallet-sdk-capabilities 4.0.0-beta.2 → 4.0.0-beta.3

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.
Files changed (68) hide show
  1. package/README.md +27 -3
  2. package/dist/chainVersion/chainVersionProbe.d.ts +95 -0
  3. package/dist/chainVersion/chainVersionProbe.js +83 -0
  4. package/dist/chainVersion/index.d.ts +1 -0
  5. package/dist/chainVersion/index.js +13 -0
  6. package/dist/codecs/index.d.ts +1 -0
  7. package/dist/codecs/index.js +13 -0
  8. package/dist/codecs/ledgerParameters.d.ts +81 -0
  9. package/dist/codecs/ledgerParameters.js +63 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.js +3 -0
  12. package/dist/pendingTransactions/pendingTransactions.d.ts +113 -9
  13. package/dist/pendingTransactions/pendingTransactions.js +147 -30
  14. package/dist/pendingTransactions/pendingTransactionsService.d.ts +25 -9
  15. package/dist/pendingTransactions/pendingTransactionsService.js +33 -21
  16. package/dist/proving/index.d.ts +2 -0
  17. package/dist/proving/index.js +2 -0
  18. package/dist/proving/provingService.d.ts +175 -15
  19. package/dist/proving/provingService.js +104 -11
  20. package/dist/proving/v8ProvingService.d.ts +53 -0
  21. package/dist/proving/v8ProvingService.js +71 -0
  22. package/dist/proving/versionedProving.d.ts +42 -0
  23. package/dist/proving/versionedProving.js +103 -0
  24. package/dist/signatures/index.d.ts +2 -0
  25. package/dist/signatures/index.js +14 -0
  26. package/dist/signatures/signing.d.ts +37 -0
  27. package/dist/signatures/signing.js +13 -0
  28. package/dist/signatures/v8Signatures.d.ts +54 -0
  29. package/dist/signatures/v8Signatures.js +62 -0
  30. package/dist/simulation/ForkSimulator.d.ts +114 -0
  31. package/dist/simulation/ForkSimulator.js +209 -0
  32. package/dist/simulation/LedgerTranslation.d.ts +53 -0
  33. package/dist/simulation/LedgerTranslation.js +56 -0
  34. package/dist/simulation/core/VersionTimeline.d.ts +54 -0
  35. package/dist/simulation/core/VersionTimeline.js +56 -0
  36. package/dist/simulation/core/blocks.d.ts +38 -0
  37. package/dist/simulation/core/blocks.js +52 -0
  38. package/dist/simulation/core/index.d.ts +13 -0
  39. package/dist/simulation/core/index.js +25 -0
  40. package/dist/simulation/core/strictness.d.ts +29 -0
  41. package/dist/simulation/core/strictness.js +39 -0
  42. package/dist/simulation/index.d.ts +22 -2
  43. package/dist/simulation/index.js +25 -14
  44. package/dist/simulation/v8/Simulator.d.ts +231 -0
  45. package/dist/simulation/v8/Simulator.js +503 -0
  46. package/dist/simulation/{SimulatorState.d.ts → v8/SimulatorState.d.ts} +31 -44
  47. package/dist/simulation/v8/SimulatorState.js +290 -0
  48. package/dist/simulation/v8/index.d.ts +2 -0
  49. package/dist/simulation/v8/index.js +26 -0
  50. package/dist/simulation/{Simulator.d.ts → v9/Simulator.d.ts} +57 -6
  51. package/dist/simulation/{Simulator.js → v9/Simulator.js} +68 -18
  52. package/dist/simulation/v9/SimulatorState.d.ts +336 -0
  53. package/dist/simulation/{SimulatorState.js → v9/SimulatorState.js} +34 -67
  54. package/dist/simulation/v9/index.d.ts +2 -0
  55. package/dist/simulation/v9/index.js +26 -0
  56. package/dist/submission/submissionService.d.ts +2 -1
  57. package/dist/submission/submissionService.js +1 -1
  58. package/dist/validation/blockData.d.ts +42 -2
  59. package/dist/validation/blockData.js +55 -8
  60. package/dist/validation/index.d.ts +2 -0
  61. package/dist/validation/index.js +2 -0
  62. package/dist/validation/v8ValidationService.d.ts +29 -0
  63. package/dist/validation/v8ValidationService.js +48 -0
  64. package/dist/validation/validationService.d.ts +132 -17
  65. package/dist/validation/validationService.js +88 -42
  66. package/dist/validation/versionedValidation.d.ts +46 -0
  67. package/dist/validation/versionedValidation.js +55 -0
  68. package/package.json +23 -9
@@ -12,16 +12,76 @@
12
12
  * See the License for the specific language governing permissions and
13
13
  * limitations under the License.
14
14
  */
15
- import { Array as Arr, Either, Order, pipe, Schema } from 'effect';
16
- export const has = (transactions, transaction, txTrait) => {
17
- return transactions.all.some((item) => txTrait.areAllTxIdsIncluded(transaction, txTrait.ids(item.tx)));
18
- };
15
+ import { ProtocolVersion } from '@midnight-ntwrk/wallet-sdk-abstractions';
16
+ import { Buffer } from 'buffer';
17
+ import { Array as Arr, Either, Option, Order, ParseResult, pipe, Schema } from 'effect';
18
+ /** Registers one trait for every protocol version: the shape a wallet that speaks a single ledger version has. */
19
+ export const singleTrait = (trait) => ({
20
+ entries: [
21
+ {
22
+ range: ProtocolVersion.makeRange(ProtocolVersion.MinSupportedVersion, ProtocolVersion.MaxSupportedVersion),
23
+ value: trait,
24
+ },
25
+ ],
26
+ });
27
+ /** The oldest registered trait: what an envelope that carries no version stamp is read with. */
28
+ export const headTrait = (traits) => Option.fromNullable(traits.entries.at(0)).pipe(Option.map((entry) => entry.value));
29
+ /**
30
+ * The trait registered for a protocol version, or the oldest trait when nothing says which version applies.
31
+ *
32
+ * @remarks
33
+ * Falling back to the oldest trait is the same convention snapshot restore uses for an envelope written before versions
34
+ * were recorded: the only envelopes without a stamp are ones written before stamping existed, and those necessarily
35
+ * predate every version boundary since.
36
+ * @param traits The registered traits.
37
+ * @param protocolVersion The version the transaction was authored for, when one is known.
38
+ * @returns The trait to read with, or `Option.none()` when the version falls outside every registered range.
39
+ */
40
+ export const traitForVersion = (traits, protocolVersion) => Option.match(protocolVersion, {
41
+ onNone: () => headTrait(traits),
42
+ onSome: (version) => ProtocolVersion.select(traits, version),
43
+ });
44
+ /** The registered trait that recognises a transaction object as its own, if any does. */
45
+ export const recognisingTrait = (traits, tx) => Option.fromNullable(traits.entries.find((entry) => entry.value.isTx(tx))).pipe(Option.map((entry) => entry.value));
46
+ /**
47
+ * The trait to read an incoming transaction with: the one that recognises it, or the oldest as a last resort.
48
+ *
49
+ * @param traits The registered traits.
50
+ * @param tx The transaction to place.
51
+ * @returns The trait that owns `tx`, the oldest trait when none claims it, or `Option.none()` when nothing is
52
+ * registered at all.
53
+ */
54
+ export const traitForTx = (traits, tx) => Option.orElse(recognisingTrait(traits, tx), () => headTrait(traits));
55
+ const traitOfItem = (traits, item) => traitForVersion(traits, item.protocolVersion);
56
+ /** Two versions are in the same epoch when the registry answers them with the same trait. */
57
+ const sameEpoch = (a, b) => Option.getEquivalence((left, right) => left === right)(a, b);
58
+ const idsOf = (traits, tx) => traitForTx(traits, tx).pipe(Option.map((trait) => trait.ids(tx)), Option.getOrElse(() => []));
59
+ /** A stored item's identifiers, read with the trait registered for the version it was stamped with. */
60
+ const idsOfItem = (traits, item) => traitOfItem(traits, item).pipe(Option.map((trait) => trait.ids(item.tx)), Option.getOrElse(() => []));
61
+ /** Whether a stored item is covered by the identifiers of an incoming transaction, each read with its own trait. */
62
+ const isCoveredBy = (traits, item, txIds) => traitOfItem(traits, item).pipe(Option.map((trait) => trait.areAllTxIdsIncluded(item.tx, txIds)), Option.getOrElse(() => false));
63
+ export const has = (transactions, transaction, traits) => traitForTx(traits, transaction).pipe(Option.map((trait) => transactions.all.some((item) => trait.areAllTxIdsIncluded(transaction, idsOfItem(traits, item)))), Option.getOrElse(() => false));
19
64
  export const all = (transactions) => {
20
65
  return transactions.all.map((item) => item.tx);
21
66
  };
67
+ const resultOf = (item) => 'result' in item ? Option.fromNullable(item.result) : Option.none();
22
68
  export const allFailed = (transactions) => {
23
69
  return transactions.all.filter((item) => 'result' in item && (item.result?.status === 'FAILURE' || item.result?.status === 'PARTIAL_SUCCESS'));
24
70
  };
71
+ /** Transactions a protocol upgrade stranded: they were authored for a version the chain has moved past. */
72
+ export const allOrphaned = (transactions) => {
73
+ return transactions.all.filter((item) => 'result' in item && item.result?.status === 'ORPHANED_BY_FORK');
74
+ };
75
+ /**
76
+ * Everything the wallet has given up on, in the order it was added: reported failures and orphaned transactions alike.
77
+ * Both need the same treatment — unbook the coins, record the rejection — so both belong on one list.
78
+ */
79
+ export const allRejected = (transactions) => {
80
+ return transactions.all.filter((item) => 'result' in item &&
81
+ (item.result?.status === 'FAILURE' ||
82
+ item.result?.status === 'PARTIAL_SUCCESS' ||
83
+ item.result?.status === 'ORPHANED_BY_FORK'));
84
+ };
25
85
  export const allPending = (state) => {
26
86
  return state.all.filter((item) => !('result' in item) || item.result === undefined);
27
87
  };
@@ -30,47 +90,104 @@ export const empty = () => {
30
90
  all: [],
31
91
  };
32
92
  };
33
- export const addPendingTransaction = (state, tx, now, txTrait) => {
34
- const [rest, foundMatching] = pipe(state.all, Arr.partition((item) => txTrait.isOneIncludedInOther(tx, item.tx)));
35
- const allMatchingTransactions = Arr.append(foundMatching, { tx, creationTime: now });
36
- const theBiggestMatchingTx = Arr.max(allMatchingTransactions, pipe(Order.number, Order.mapInput((input) => txTrait.ids(input).length), Order.mapInput((input) => input.tx)));
93
+ /**
94
+ * Records a transaction as pending, stamped with the protocol version it was authored for.
95
+ *
96
+ * @param state The pending transactions.
97
+ * @param tx The transaction to record.
98
+ * @param now The time it was authored.
99
+ * @param traits The traits pending transactions are read with.
100
+ * @param protocolVersion The version the chain had reached when it was authored, when the wallet knew one.
101
+ * @returns The pending transactions including `tx`, with any superseded entry from the same version epoch replaced.
102
+ */
103
+ export const addPendingTransaction = (state, tx, now, traits, protocolVersion) => {
104
+ const trait = traitForVersion(traits, protocolVersion);
105
+ const item = { tx, creationTime: now, protocolVersion };
106
+ // Whether one transaction supersedes another is a question only a single ledger version can answer — across a
107
+ // version boundary the two were authored against different rules, so they are simply different transactions.
108
+ const [rest, foundMatching] = pipe(state.all, Arr.partition((existing) => sameEpoch(traitOfItem(traits, existing), trait) &&
109
+ Option.match(trait, {
110
+ onNone: () => false,
111
+ onSome: (found) => found.isOneIncludedInOther(tx, existing.tx),
112
+ })));
113
+ const idCount = (candidate) => Option.match(trait, { onNone: () => 0, onSome: (found) => found.ids(candidate.tx).length });
114
+ const theBiggestMatchingTx = Arr.max(Arr.append(foundMatching, item), pipe(Order.number, Order.mapInput(idCount)));
37
115
  return {
38
116
  ...state,
39
117
  all: Arr.append(rest, theBiggestMatchingTx),
40
118
  };
41
119
  };
42
- export const clear = (state, tx, txTrait) => {
120
+ export const clear = (state, tx, traits) => {
121
+ const txIds = idsOf(traits, tx);
43
122
  return {
44
123
  ...state,
45
- all: Arr.filter(state.all, (item) => !txTrait.areAllTxIdsIncluded(item.tx, txTrait.ids(tx))),
124
+ all: Arr.filter(state.all, (item) => !isCoveredBy(traits, item, txIds)),
46
125
  };
47
126
  };
48
- export const saveResult = (state, tx, result, txTrait) => {
127
+ export const saveResult = (state, tx, result, traits) => {
128
+ const txIds = idsOf(traits, tx);
49
129
  return {
50
130
  ...state,
51
- all: Arr.map(state.all, (item) => {
52
- return txTrait.areAllTxIdsIncluded(item.tx, txTrait.ids(tx)) ? { ...item, result } : item;
53
- }),
131
+ all: Arr.map(state.all, (item) => (isCoveredBy(traits, item, txIds) ? { ...item, result } : item)),
54
132
  };
55
133
  };
56
- export const SerializedSchema = (txTrait) => {
57
- const TxSchema = Schema.declare((tx) => txTrait.isTx(tx));
58
- const TxFromHex = Schema.transform(Schema.Uint8ArrayFromHex, TxSchema, {
59
- encode: (tx) => txTrait.serialize(tx),
60
- decode: (bytes) => txTrait.deserialize(bytes),
61
- });
62
- const TxItemSchema = Schema.Struct({
63
- tx: TxFromHex,
134
+ /**
135
+ * Gives up on every unresolved transaction whose version epoch the chain has moved past.
136
+ *
137
+ * @remarks
138
+ * The epochs are the registry's own ranges, so "the chain has moved past" means exactly "a different trait answers for
139
+ * the chain now than answered for this transaction". A transaction authored under the previous protocol version can
140
+ * never be included afterwards, so waiting for its TTL only delays the inevitable and holds its coins hostage
141
+ * meanwhile.
142
+ * @param state The pending transactions.
143
+ * @param traits The traits pending transactions are read with, whose ranges define the epochs.
144
+ * @param chainNow The protocol version the wallets have reached.
145
+ * @returns The pending transactions with the stranded ones given an {@link OrphanedByForkResult}.
146
+ */
147
+ export const orphanBeyond = (state, traits, chainNow) => ({
148
+ ...state,
149
+ all: Arr.map(state.all, (item) => Option.isSome(resultOf(item))
150
+ ? item
151
+ : Option.match(item.protocolVersion, {
152
+ onNone: () => item,
153
+ onSome: (authoredFor) => hasEpochEnded(traits, authoredFor, chainNow)
154
+ ? { ...item, result: { status: 'ORPHANED_BY_FORK', authoredFor, chainNow } }
155
+ : item,
156
+ })),
157
+ });
158
+ const hasEpochEnded = (traits, authoredFor, chainNow) => ProtocolVersion.selectEntry(traits, authoredFor).pipe(Option.map((entry) => chainNow >= entry.range[1]), Option.getOrElse(() => false));
159
+ const WireItemSchema = Schema.Struct({
160
+ tx: Schema.String,
161
+ creationTime: Schema.DateTimeUtc,
162
+ // Additive: envelopes written before transactions were stamped simply omit it, and decode to `Option.none()`.
163
+ protocolVersion: Schema.optionalWith(ProtocolVersion.ProtocolVersionSchema, { as: 'Option' }),
164
+ });
165
+ const PendingItemSchema = (traits) => {
166
+ const TxSchema = Schema.declare((tx) => Option.isSome(recognisingTrait(traits, tx)));
167
+ const DomainSchema = Schema.typeSchema(Schema.Struct({
168
+ tx: TxSchema,
64
169
  creationTime: Schema.DateTimeUtc,
65
- });
66
- return Schema.Struct({
67
- version: Schema.Literal('v1'),
68
- transactions: Schema.Array(TxItemSchema),
69
- });
170
+ protocolVersion: Schema.OptionFromSelf(ProtocolVersion.ProtocolVersionSchema),
171
+ }));
172
+ return Schema.asSchema(Schema.transformOrFail(WireItemSchema, DomainSchema, {
173
+ strict: true,
174
+ decode: (wire, _options, ast) => pipe(traitForVersion(traits, wire.protocolVersion), Either.fromOption(() => new ParseResult.Type(ast, wire, `No transaction trait is registered for protocol version ${Option.getOrElse(wire.protocolVersion, () => 'unknown')}.`)), Either.flatMap((trait) => Either.try({
175
+ try: () => trait.deserialize(Buffer.from(wire.tx, 'hex')),
176
+ catch: (cause) => new ParseResult.Type(ast, wire, `Could not read the pending transaction: ${String(cause)}`),
177
+ })), Either.map((tx) => ({ tx, creationTime: wire.creationTime, protocolVersion: wire.protocolVersion }))),
178
+ encode: (item, _options, ast) => pipe(traitForTx(traits, item.tx), Either.fromOption(() => new ParseResult.Type(ast, item, 'No transaction trait is registered.')), Either.flatMap((trait) => Either.try({
179
+ try: () => Buffer.from(trait.serialize(item.tx)).toString('hex'),
180
+ catch: (cause) => new ParseResult.Type(ast, item, `Could not write the pending transaction: ${String(cause)}`),
181
+ })), Either.map((tx) => ({ tx, creationTime: item.creationTime, protocolVersion: item.protocolVersion }))),
182
+ }));
70
183
  };
71
- export const serialize = (state, txTrait) => pipe(state, toSerialized, Schema.encodeSync(SerializedSchema(txTrait)), JSON.stringify);
72
- export const deserialize = (serialized, txTrait) => {
73
- return pipe(serialized, Schema.decodeUnknownEither(Schema.parseJson(SerializedSchema(txTrait))), Either.map((data) => fromSerialized(data)));
184
+ export const SerializedSchema = (traits) => Schema.Struct({
185
+ version: Schema.Literal('v1'),
186
+ transactions: Schema.Array(PendingItemSchema(traits)),
187
+ });
188
+ export const serialize = (state, traits) => pipe(state, toSerialized, Schema.encodeSync(SerializedSchema(traits)), JSON.stringify);
189
+ export const deserialize = (serialized, traits) => {
190
+ return pipe(serialized, Schema.decodeUnknownEither(Schema.parseJson(SerializedSchema(traits))), Either.map((data) => fromSerialized(data)));
74
191
  };
75
192
  export const toSerialized = (pendingTransactions) => {
76
193
  return {
@@ -1,13 +1,26 @@
1
- import { type Clock, Effect, type ParseResult, Scope, Stream } from 'effect';
1
+ import { type Clock, Effect, Option, type ParseResult, Scope, Stream } from 'effect';
2
2
  import * as PendingTransactions from './pendingTransactions.js';
3
+ import { type ProtocolVersion } from '@midnight-ntwrk/wallet-sdk-abstractions';
3
4
  import type * as rx from 'rxjs';
4
5
  import { type QueryClient } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
5
6
  export type PendingTransactionsService<TTransaction> = {
6
7
  start: () => Promise<void>;
7
8
  stop: () => Promise<void>;
8
9
  state: () => rx.Observable<PendingTransactions.PendingTransactions<TTransaction>>;
9
- addPendingTransaction: (tx: TTransaction) => Promise<void>;
10
+ /**
11
+ * Records a transaction as pending, stamped with the protocol version the chain had reached when it was authored.
12
+ *
13
+ * @param tx The transaction.
14
+ * @param protocolVersion The observed chain version, or `Option.none()` when no wallet has reported one yet.
15
+ */
16
+ addPendingTransaction: (tx: TTransaction, protocolVersion: Option.Option<ProtocolVersion.ProtocolVersion>) => Promise<void>;
10
17
  clear: (tx: TTransaction) => Promise<void>;
18
+ /**
19
+ * Gives up on every pending transaction whose protocol version epoch the chain has moved past.
20
+ *
21
+ * @param chainNow The protocol version the wallets have reached.
22
+ */
23
+ orphanBeyond: (chainNow: ProtocolVersion.ProtocolVersion) => Promise<void>;
11
24
  };
12
25
  export type IndexerClientConnection = {
13
26
  indexerHttpUrl: string;
@@ -17,18 +30,19 @@ export type DefaultPendingTransactionsServiceConfiguration = {
17
30
  indexerClientConnection: IndexerClientConnection;
18
31
  };
19
32
  export type InitParams<TTransaction> = {
20
- txTrait: PendingTransactions.TransactionTrait<TTransaction>;
33
+ txTraits: PendingTransactions.VersionedTransactionTrait<TTransaction>;
21
34
  initialState?: PendingTransactions.PendingTransactions<TTransaction>;
22
35
  configuration: DefaultPendingTransactionsServiceConfiguration;
23
36
  };
24
37
  export declare class PendingTransactionsServiceImpl<TTransaction> implements PendingTransactionsService<TTransaction> {
25
38
  #private;
26
39
  static init<TTransaction>(initParams: InitParams<TTransaction>): Promise<PendingTransactionsServiceImpl<TTransaction>>;
27
- static restore<TTransaction>(data: string, txTrait: PendingTransactions.TransactionTrait<TTransaction>, configuration: DefaultPendingTransactionsServiceConfiguration): Promise<PendingTransactionsServiceImpl<TTransaction>>;
40
+ static restore<TTransaction>(data: string, txTraits: PendingTransactions.VersionedTransactionTrait<TTransaction>, configuration: DefaultPendingTransactionsServiceConfiguration): Promise<PendingTransactionsServiceImpl<TTransaction>>;
28
41
  private static initEffect;
29
42
  constructor(effectService: PendingTransactionsServiceEffect<TTransaction>, scope: Scope.CloseableScope, configuration: DefaultPendingTransactionsServiceConfiguration);
30
- addPendingTransaction(tx: TTransaction): Promise<void>;
43
+ addPendingTransaction(tx: TTransaction, protocolVersion: Option.Option<ProtocolVersion.ProtocolVersion>): Promise<void>;
31
44
  clear(tx: TTransaction): Promise<void>;
45
+ orphanBeyond(chainNow: ProtocolVersion.ProtocolVersion): Promise<void>;
32
46
  start(): Promise<void>;
33
47
  state(): rx.Observable<PendingTransactions.PendingTransactions<TTransaction>>;
34
48
  stop(): Promise<void>;
@@ -36,17 +50,19 @@ export declare class PendingTransactionsServiceImpl<TTransaction> implements Pen
36
50
  export type PendingTransactionsServiceEffect<TTransaction> = {
37
51
  startPolling: (ticks: Stream.Stream<unknown>) => Effect.Effect<void, Error, QueryClient | Scope.Scope | Clock.Clock>;
38
52
  state: () => Stream.Stream<PendingTransactions.PendingTransactions<TTransaction>>;
39
- addPendingTransaction: (tx: TTransaction) => Effect.Effect<void, never, never>;
53
+ addPendingTransaction: (tx: TTransaction, protocolVersion: Option.Option<ProtocolVersion.ProtocolVersion>) => Effect.Effect<void, never, never>;
40
54
  clear: (tx: TTransaction) => Effect.Effect<void, never, never>;
55
+ orphanBeyond: (chainNow: ProtocolVersion.ProtocolVersion) => Effect.Effect<void, never, never>;
41
56
  };
42
57
  export declare class PendingTransactionsServiceEffectImpl<TTransaction> implements PendingTransactionsServiceEffect<TTransaction> {
43
58
  #private;
44
- static restore<TTransaction>(data: string, txTrait: PendingTransactions.TransactionTrait<TTransaction>): Effect.Effect<PendingTransactionsServiceEffectImpl<TTransaction>, ParseResult.ParseError>;
45
- constructor(txTrait: PendingTransactions.TransactionTrait<TTransaction>, initialState?: PendingTransactions.PendingTransactions<TTransaction>);
59
+ static restore<TTransaction>(data: string, txTraits: PendingTransactions.VersionedTransactionTrait<TTransaction>): Effect.Effect<PendingTransactionsServiceEffectImpl<TTransaction>, ParseResult.ParseError>;
60
+ constructor(txTraits: PendingTransactions.VersionedTransactionTrait<TTransaction>, initialState?: PendingTransactions.PendingTransactions<TTransaction>);
46
61
  state(): Stream.Stream<PendingTransactions.PendingTransactions<TTransaction>>;
47
62
  startPolling(ticks: Stream.Stream<unknown>): Effect.Effect<void, Error, QueryClient | Scope.Scope>;
48
- addPendingTransaction(tx: TTransaction): Effect.Effect<void>;
63
+ addPendingTransaction(tx: TTransaction, protocolVersion: Option.Option<ProtocolVersion.ProtocolVersion>): Effect.Effect<void>;
49
64
  clear(tx: TTransaction): Effect.Effect<void>;
65
+ orphanBeyond(chainNow: ProtocolVersion.ProtocolVersion): Effect.Effect<void>;
50
66
  private saveResult;
51
67
  private queryForStatus;
52
68
  }
@@ -21,12 +21,12 @@ export class PendingTransactionsServiceImpl {
21
21
  static init(initParams) {
22
22
  return PendingTransactionsServiceImpl.initEffect(initParams).pipe(Effect.runPromise);
23
23
  }
24
- static restore(data, txTrait, configuration) {
25
- return pipe(PendingTransactions.deserialize(data, txTrait), EitherOps.toEffect, Effect.andThen((state) => PendingTransactionsServiceImpl.initEffect({ txTrait, initialState: state, configuration })), Effect.runPromise);
24
+ static restore(data, txTraits, configuration) {
25
+ return pipe(PendingTransactions.deserialize(data, txTraits), EitherOps.toEffect, Effect.andThen((state) => PendingTransactionsServiceImpl.initEffect({ txTraits, initialState: state, configuration })), Effect.runPromise);
26
26
  }
27
27
  static initEffect(initParams) {
28
28
  return Effect.gen(function* () {
29
- const service = new PendingTransactionsServiceEffectImpl(initParams.txTrait, initParams.initialState);
29
+ const service = new PendingTransactionsServiceEffectImpl(initParams.txTraits, initParams.initialState);
30
30
  const scope = yield* Scope.make();
31
31
  return new PendingTransactionsServiceImpl(service, scope, initParams.configuration);
32
32
  });
@@ -39,12 +39,15 @@ export class PendingTransactionsServiceImpl {
39
39
  this.#scope = scope;
40
40
  this.#configuration = configuration;
41
41
  }
42
- addPendingTransaction(tx) {
43
- return this.#effectService.addPendingTransaction(tx).pipe(Effect.runPromise);
42
+ addPendingTransaction(tx, protocolVersion) {
43
+ return this.#effectService.addPendingTransaction(tx, protocolVersion).pipe(Effect.runPromise);
44
44
  }
45
45
  clear(tx) {
46
46
  return this.#effectService.clear(tx).pipe(Effect.runPromise);
47
47
  }
48
+ orphanBeyond(chainNow) {
49
+ return this.#effectService.orphanBeyond(chainNow).pipe(Effect.runPromise);
50
+ }
48
51
  start() {
49
52
  return this.#effectService.startPolling(Stream.tick(Duration.seconds(1))).pipe(Effect.provide(HttpQueryClient.layer({
50
53
  url: this.#configuration.indexerClientConnection.indexerHttpUrl,
@@ -59,12 +62,12 @@ export class PendingTransactionsServiceImpl {
59
62
  }
60
63
  export class PendingTransactionsServiceEffectImpl {
61
64
  #state;
62
- #txTrait;
63
- static restore(data, txTrait) {
64
- return pipe(data, (data) => PendingTransactions.deserialize(data, txTrait), EitherOps.toEffect, Effect.map((state) => new PendingTransactionsServiceEffectImpl(txTrait, state)));
65
+ #txTraits;
66
+ static restore(data, txTraits) {
67
+ return pipe(data, (data) => PendingTransactions.deserialize(data, txTraits), EitherOps.toEffect, Effect.map((state) => new PendingTransactionsServiceEffectImpl(txTraits, state)));
65
68
  }
66
- constructor(txTrait, initialState) {
67
- this.#txTrait = txTrait;
69
+ constructor(txTraits, initialState) {
70
+ this.#txTraits = txTraits;
68
71
  this.#state = SubscriptionRef.make(initialState ?? PendingTransactions.empty()).pipe(Effect.runSync); // Should not be here, but otherwise initialization would be too involved
69
72
  }
70
73
  state() {
@@ -74,7 +77,10 @@ export class PendingTransactionsServiceEffectImpl {
74
77
  return ticks.pipe(Stream.mapEffect(() => SubscriptionRef.get(this.#state)), Stream.mapConcat(PendingTransactions.allPending), Stream.mapConcatEffect((item) => {
75
78
  return Effect.gen(this, function* () {
76
79
  const now = yield* DateTime.now;
77
- const result = yield* this.queryForStatus(item.tx);
80
+ const trait = PendingTransactions.traitForVersion(this.#txTraits, item.protocolVersion);
81
+ if (Option.isNone(trait))
82
+ return [];
83
+ const result = yield* this.queryForStatus(item.tx, trait.value);
78
84
  return Option.match(result, {
79
85
  onSome: (status) => [{ ...item, result: status }],
80
86
  onNone: () => {
@@ -82,7 +88,7 @@ export class PendingTransactionsServiceEffectImpl {
82
88
  status: 'FAILURE',
83
89
  segments: [],
84
90
  };
85
- return this.#txTrait.hasTTLExpired(item.tx, item.creationTime, now)
91
+ return trait.value.hasTTLExpired(item.tx, item.creationTime, now)
86
92
  ? [{ ...item, result: failedResult }]
87
93
  : [];
88
94
  },
@@ -94,14 +100,19 @@ export class PendingTransactionsServiceEffectImpl {
94
100
  return this.saveResult(item.tx, item.result);
95
101
  }));
96
102
  }
97
- addPendingTransaction(tx) {
103
+ addPendingTransaction(tx, protocolVersion) {
98
104
  return SubscriptionRef.updateEffect(this.#state, (state) => {
99
- return DateTime.now.pipe(Effect.andThen((now) => PendingTransactions.addPendingTransaction(state, tx, now, this.#txTrait)));
105
+ return DateTime.now.pipe(Effect.andThen((now) => PendingTransactions.addPendingTransaction(state, tx, now, this.#txTraits, protocolVersion)));
100
106
  });
101
107
  }
102
108
  clear(tx) {
103
109
  return SubscriptionRef.update(this.#state, (state) => {
104
- return PendingTransactions.clear(state, tx, this.#txTrait);
110
+ return PendingTransactions.clear(state, tx, this.#txTraits);
111
+ });
112
+ }
113
+ orphanBeyond(chainNow) {
114
+ return SubscriptionRef.update(this.#state, (state) => {
115
+ return PendingTransactions.orphanBeyond(state, this.#txTraits, chainNow);
105
116
  });
106
117
  }
107
118
  saveResult(tx, result) {
@@ -110,20 +121,21 @@ export class PendingTransactionsServiceEffectImpl {
110
121
  return this.clear(tx);
111
122
  case 'FAILURE':
112
123
  case 'PARTIAL_SUCCESS':
124
+ case 'ORPHANED_BY_FORK':
113
125
  return SubscriptionRef.update(this.#state, (state) => {
114
- return PendingTransactions.saveResult(state, tx, result, this.#txTrait);
126
+ return PendingTransactions.saveResult(state, tx, result, this.#txTraits);
115
127
  });
116
128
  }
117
129
  }
118
- queryForStatus(tx) {
119
- return Effect.gen(this, function* () {
130
+ queryForStatus(tx, txTrait) {
131
+ return Effect.gen(function* () {
120
132
  const statusQuery = yield* TransactionStatus;
121
- const result = yield* statusQuery({ transactionId: this.#txTrait.firstId(tx) }).pipe(Effect.catchAll((error) => {
133
+ const result = yield* statusQuery({ transactionId: txTrait.firstId(tx) }).pipe(Effect.catchAll((error) => {
122
134
  const fallback = { transactions: [] };
123
135
  return pipe(Effect.logWarning(error, 'Observed error in PendingTransactionsService, retrying'), Effect.as(fallback));
124
136
  }));
125
137
  return pipe(result.transactions, Iterable.filterMap((res) => {
126
- if (res.__typename == 'SystemTransaction') {
138
+ if (res.__typename !== 'RegularTransaction') {
127
139
  return Option.none();
128
140
  }
129
141
  if (res.transactionResult.status != 'SUCCESS' &&
@@ -131,7 +143,7 @@ export class PendingTransactionsServiceEffectImpl {
131
143
  res.transactionResult.status != 'PARTIAL_SUCCESS') {
132
144
  return Option.none();
133
145
  }
134
- if (this.#txTrait.areAllTxIdsIncluded(tx, res.identifiers)) {
146
+ if (txTrait.areAllTxIdsIncluded(tx, res.identifiers)) {
135
147
  return Option.some({
136
148
  status: res.transactionResult.status,
137
149
  segments: res.transactionResult.segments ?? [],
@@ -1 +1,3 @@
1
+ export * from './v8ProvingService.js';
1
2
  export * from './provingService.js';
3
+ export * from './versionedProving.js';
@@ -12,4 +12,6 @@
12
12
  * See the License for the specific language governing permissions and
13
13
  * limitations under the License.
14
14
  */
15
+ export * from './v8ProvingService.js';
15
16
  export * from './provingService.js';
17
+ export * from './versionedProving.js';