@layerzerolabs/gated-transaction 0.0.29 → 0.0.31

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 (51) hide show
  1. package/.turbo/turbo-build.log +34 -34
  2. package/.turbo/turbo-test.log +4 -4
  3. package/dist/{AYIRG6WY.cjs → 3SOQJCDG.cjs} +16 -4
  4. package/dist/3SOQJCDG.cjs.map +1 -0
  5. package/dist/{QGZD4SJ4.cjs → 422FLJZW.cjs} +5 -5
  6. package/dist/422FLJZW.cjs.map +1 -0
  7. package/dist/{6NWNACVT.cjs → 4ND4S3IS.cjs} +23 -24
  8. package/dist/4ND4S3IS.cjs.map +1 -0
  9. package/dist/{CG43CWKE.js → BCFOKBQQ.js} +105 -51
  10. package/dist/BCFOKBQQ.js.map +1 -0
  11. package/dist/{GMAAYDJ4.js → PGJAXI5M.js} +23 -25
  12. package/dist/PGJAXI5M.js.map +1 -0
  13. package/dist/{DBJG544E.js → TLPNG7S6.js} +3 -3
  14. package/dist/TLPNG7S6.js.map +1 -0
  15. package/dist/{XYULD3ZM.cjs → TYY6L3E5.cjs} +109 -55
  16. package/dist/TYY6L3E5.cjs.map +1 -0
  17. package/dist/WWHK47IY.js +25 -0
  18. package/dist/WWHK47IY.js.map +1 -0
  19. package/dist/gatedTransactionSignalLock.cjs +5 -5
  20. package/dist/gatedTransactionSignalLock.d.ts +2 -4
  21. package/dist/gatedTransactionSignalLock.d.ts.map +1 -1
  22. package/dist/gatedTransactionSignalLock.js +2 -2
  23. package/dist/gatedTx.cjs +7 -3
  24. package/dist/gatedTx.d.ts +28 -5
  25. package/dist/gatedTx.d.ts.map +1 -1
  26. package/dist/gatedTx.js +1 -1
  27. package/dist/index.cjs +25 -17
  28. package/dist/index.js +4 -4
  29. package/dist/resolver.cjs +5 -5
  30. package/dist/resolver.d.ts +6 -10
  31. package/dist/resolver.d.ts.map +1 -1
  32. package/dist/resolver.js +3 -3
  33. package/dist/types.cjs +11 -7
  34. package/dist/types.d.ts +52 -72
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js +1 -1
  37. package/package.json +9 -8
  38. package/src/gatedTransactionSignalLock.ts +3 -6
  39. package/src/gatedTx.ts +53 -6
  40. package/src/resolver.ts +150 -57
  41. package/src/types.ts +134 -76
  42. package/test/resolver.test.ts +151 -6
  43. package/dist/5INFRBMB.js +0 -14
  44. package/dist/5INFRBMB.js.map +0 -1
  45. package/dist/6NWNACVT.cjs.map +0 -1
  46. package/dist/AYIRG6WY.cjs.map +0 -1
  47. package/dist/CG43CWKE.js.map +0 -1
  48. package/dist/DBJG544E.js.map +0 -1
  49. package/dist/GMAAYDJ4.js.map +0 -1
  50. package/dist/QGZD4SJ4.cjs.map +0 -1
  51. package/dist/XYULD3ZM.cjs.map +0 -1
package/src/resolver.ts CHANGED
@@ -1,16 +1,22 @@
1
1
  import isEqual from 'lodash.isequal';
2
2
 
3
3
  import type { ActivityRegistry } from '@layerzerolabs/common-activities';
4
- import type { Transaction } from '@layerzerolabs/common-chain-model';
4
+ import type {
5
+ Transaction,
6
+ TransactionResult,
7
+ TransactionWithResult,
8
+ } from '@layerzerolabs/common-chain-model';
5
9
  import type { WorkflowFunctions } from '@layerzerolabs/common-workflow';
6
10
 
7
11
  import { getIdForGatedTransaction } from './gatedTx';
8
12
  import type {
13
+ BaseGatedTransactionFor,
9
14
  GatedTransaction,
10
15
  GatedTransactionId,
11
- GatedTransactionResult,
12
16
  IGatedTransactionCache,
13
17
  InferOnChainDataTypeFromGatedTransaction,
18
+ ResolvedGatedTransaction,
19
+ ResolvedGatedTransactionDependencies,
14
20
  UserInteractionCallbacks,
15
21
  } from './types';
16
22
  import { GatedTransactionStatus } from './types';
@@ -20,16 +26,19 @@ type OnChainCheckResult<DataType = any> = {
20
26
  onChainData: DataType;
21
27
  };
22
28
 
23
- const checkGatedTransaction = async <GatedTx extends GatedTransaction>({
29
+ const checkGatedTransaction = async <
30
+ GatedTx extends GatedTransaction,
31
+ TxWithResult extends TransactionWithResult,
32
+ >({
24
33
  registry,
25
34
  gatedTransaction,
26
35
  cachedCheckResult,
27
- processedTransaction,
36
+ submittedTransaction,
28
37
  }: {
29
38
  registry: ActivityRegistry;
30
39
  gatedTransaction: GatedTx;
31
40
  cachedCheckResult?: InferOnChainDataTypeFromGatedTransaction<GatedTx>;
32
- processedTransaction?: any;
41
+ submittedTransaction?: TxWithResult;
33
42
  }): Promise<OnChainCheckResult<InferOnChainDataTypeFromGatedTransaction<GatedTx>>> => {
34
43
  let onChainData: InferOnChainDataTypeFromGatedTransaction<GatedTx>;
35
44
  if (cachedCheckResult !== undefined) {
@@ -37,8 +46,8 @@ const checkGatedTransaction = async <GatedTx extends GatedTransaction>({
37
46
  } else {
38
47
  // Always inject the processed transaction as the last parameter when available
39
48
  let params = gatedTransaction.check.params;
40
- if (processedTransaction !== undefined) {
41
- params = [...gatedTransaction.check.params, processedTransaction];
49
+ if (submittedTransaction !== undefined) {
50
+ params = [...gatedTransaction.check.params, submittedTransaction];
42
51
  }
43
52
 
44
53
  onChainData = await registry.callByPointer(gatedTransaction.check.functionPointer, params);
@@ -91,15 +100,33 @@ const checkGatedTransaction = async <GatedTx extends GatedTransaction>({
91
100
  };
92
101
  };
93
102
 
103
+ const extractGatedTransactionUnderlyingTransaction = async <
104
+ GatedTx extends GatedTransaction,
105
+ TxType extends Transaction,
106
+ >({
107
+ registry,
108
+ gatedTransaction,
109
+ deps,
110
+ }: {
111
+ registry: ActivityRegistry;
112
+ gatedTransaction: GatedTx;
113
+ deps: ResolvedGatedTransactionDependencies<GatedTx>;
114
+ }): Promise<TxType> => {
115
+ if (gatedTransaction.transactionType === 'literal') {
116
+ return gatedTransaction.transaction as TxType;
117
+ } else {
118
+ return await registry.callByPointer(gatedTransaction.getTransactionPointer, [deps]);
119
+ }
120
+ };
121
+
94
122
  const resolveGatedTransaction = async <
95
123
  TxType extends Transaction,
96
- ProcessedTxType extends Transaction,
97
124
  GatedTx extends GatedTransaction<string, TxType, any>,
98
- ProcessTx extends (transaction: TxType) => Promise<ProcessedTxType>,
125
+ ProcessTx extends (transaction: TxType) => Promise<TransactionResult>,
99
126
  >({
100
127
  activityRegistry,
101
128
  gatedTx,
102
- isTransactionSuccessful,
129
+ getTransactionResult,
103
130
  processTx,
104
131
  confirmationCallback,
105
132
  fn,
@@ -108,27 +135,49 @@ const resolveGatedTransaction = async <
108
135
  activityRegistry: ActivityRegistry;
109
136
  gatedTx: GatedTx;
110
137
  processTx: ProcessTx;
111
- isTransactionSuccessful: (gtxId: GatedTransactionId) => boolean | undefined;
138
+ getTransactionResult: (gtxId: GatedTransactionId) =>
139
+ | {
140
+ resolved?: ResolvedGatedTransaction;
141
+ checkResult: { onChainData?: any; expectationMet: boolean };
142
+ }
143
+ | undefined;
112
144
  confirmationCallback: NonNullable<UserInteractionCallbacks['confirmationCallback']>;
113
145
  fn: WorkflowFunctions;
114
146
  cache?: IGatedTransactionCache;
115
- }): Promise<GatedTx & { result: GatedTransactionResult<GatedTx, ProcessedTxType> }> => {
147
+ }): Promise<{
148
+ resolvedGatedTransaction: ResolvedGatedTransaction<GatedTx>;
149
+ lastCheckResult: OnChainCheckResult | null;
150
+ }> => {
151
+ const baseGatedTx = {
152
+ name: gatedTx.name,
153
+ chainName: gatedTx.chainName,
154
+ bundleName: gatedTx.bundleName,
155
+ check: gatedTx.check,
156
+ dependencies: gatedTx.dependencies,
157
+ cacheable: gatedTx.cacheable,
158
+ uniqueIdKeys: gatedTx.uniqueIdKeys,
159
+ } as BaseGatedTransactionFor<GatedTx>;
160
+
116
161
  const dependencyIds = (gatedTx.dependencies ?? []).map((tx) => getIdForGatedTransaction(tx));
117
162
 
118
- const dependenciesAreAllProcessed = () =>
119
- dependencyIds.every((id) => isTransactionSuccessful(id) != null);
163
+ const dependenciesAreAllProcessed = () => dependencyIds.every((id) => getTransactionResult(id));
120
164
 
121
165
  await fn.condition(dependenciesAreAllProcessed);
122
166
 
123
167
  //check that the dependencies succeeded
124
- const dependenciesWereSuccessful = dependencyIds.every((id) => isTransactionSuccessful(id));
168
+ const dependenciesWereSuccessful = dependencyIds.every(
169
+ (id) => getTransactionResult(id)?.checkResult.expectationMet,
170
+ );
125
171
 
126
172
  if (!dependenciesWereSuccessful) {
127
173
  return {
128
- ...gatedTx,
129
- result: {
130
- status: GatedTransactionStatus.DEPENDENCY_FAILED,
174
+ resolvedGatedTransaction: {
175
+ ...baseGatedTx,
176
+ result: {
177
+ status: GatedTransactionStatus.DEPENDENCY_FAILED,
178
+ },
131
179
  },
180
+ lastCheckResult: null,
132
181
  };
133
182
  }
134
183
 
@@ -143,10 +192,13 @@ const resolveGatedTransaction = async <
143
192
  if (initialCheckResult.expectationMet) {
144
193
  //already met
145
194
  return {
146
- ...gatedTx,
147
- result: {
148
- status: GatedTransactionStatus.NO_OP,
195
+ resolvedGatedTransaction: {
196
+ ...baseGatedTx,
197
+ result: {
198
+ status: GatedTransactionStatus.NO_OP,
199
+ },
149
200
  },
201
+ lastCheckResult: initialCheckResult,
150
202
  };
151
203
  }
152
204
 
@@ -154,20 +206,33 @@ const resolveGatedTransaction = async <
154
206
  const confirmation = await confirmationCallback(gatedTx);
155
207
  if (!confirmation) {
156
208
  return {
157
- ...gatedTx,
158
- result: {
159
- status: GatedTransactionStatus.DENIED,
209
+ resolvedGatedTransaction: {
210
+ ...baseGatedTx,
211
+ result: {
212
+ status: GatedTransactionStatus.DENIED,
213
+ },
160
214
  },
215
+ lastCheckResult: initialCheckResult,
161
216
  };
162
217
  }
163
218
 
164
219
  //send the tx
165
220
  try {
166
- const processed = await processTx(gatedTx.transaction);
221
+ const depsResults = gatedTx.dependencies.map(
222
+ (dep) => getTransactionResult(getIdForGatedTransaction(dep))!.resolved!,
223
+ ) as ResolvedGatedTransactionDependencies<GatedTx>;
224
+ // get the underlying calldata
225
+ const underlying = await extractGatedTransactionUnderlyingTransaction<GatedTx, TxType>({
226
+ registry: activityRegistry,
227
+ gatedTransaction: gatedTx,
228
+ deps: depsResults,
229
+ });
230
+ const processResult = await processTx(underlying);
231
+ const submittedTransaction = { ...underlying, result: processResult };
167
232
  const finalCheckResult = await checkGatedTransaction({
168
233
  registry: activityRegistry,
169
234
  gatedTransaction: gatedTx,
170
- processedTransaction: processed,
235
+ submittedTransaction,
171
236
  });
172
237
 
173
238
  await cache?.cacheSuccessfulTxCheckData?.(gatedTx, finalCheckResult.onChainData);
@@ -175,11 +240,14 @@ const resolveGatedTransaction = async <
175
240
  if (finalCheckResult.expectationMet) {
176
241
  //sent and successful
177
242
  return {
178
- ...gatedTx,
179
- result: {
180
- status: GatedTransactionStatus.SUCCESS,
181
- submittedTransaction: processed,
243
+ resolvedGatedTransaction: {
244
+ ...baseGatedTx,
245
+ result: {
246
+ status: GatedTransactionStatus.SUCCESS,
247
+ submittedTransaction,
248
+ },
182
249
  },
250
+ lastCheckResult: finalCheckResult,
183
251
  };
184
252
  } else {
185
253
  //sent and unsuccessful
@@ -189,31 +257,36 @@ const resolveGatedTransaction = async <
189
257
  `Gated transaction ${gatedTx.name} final check failed:\nExpected result ${stringify(gatedTx.check.expectedResult.comparisonValue)}, but got:\n${stringify(finalCheckResult.onChainData)}`,
190
258
  );
191
259
  return {
192
- ...gatedTx,
193
- result: {
194
- status: GatedTransactionStatus.FINAL_CHECK_FAILED,
195
- submittedTransaction: processed,
196
- finalOnChainState: finalCheckResult.onChainData,
260
+ resolvedGatedTransaction: {
261
+ ...baseGatedTx,
262
+ result: {
263
+ status: GatedTransactionStatus.FINAL_CHECK_FAILED,
264
+ submittedTransaction,
265
+ finalOnChainState: finalCheckResult.onChainData,
266
+ },
197
267
  },
268
+ lastCheckResult: finalCheckResult,
198
269
  };
199
270
  }
200
271
  } catch (e) {
201
272
  //sent and failed
202
273
  return {
203
- ...gatedTx,
204
- result: {
205
- status: GatedTransactionStatus.TRANSACTION_FAILED,
206
- transactionError: e,
274
+ resolvedGatedTransaction: {
275
+ ...baseGatedTx,
276
+ result: {
277
+ status: GatedTransactionStatus.TRANSACTION_FAILED,
278
+ transactionError: e,
279
+ },
207
280
  },
281
+ lastCheckResult: initialCheckResult,
208
282
  };
209
283
  }
210
284
  };
211
285
 
212
286
  export const resolveGatedTransactions = async <
213
287
  TxType extends Transaction,
214
- ProcessedTxType extends Transaction,
215
288
  GatedTx extends GatedTransaction<string, TxType, any>,
216
- ProcessTx extends (transaction: TxType) => Promise<ProcessedTxType>,
289
+ ProcessTx extends (transaction: TxType) => Promise<TransactionResult>,
217
290
  >({
218
291
  activityRegistry,
219
292
  gatedTxes,
@@ -228,7 +301,7 @@ export const resolveGatedTransactions = async <
228
301
  fn: WorkflowFunctions;
229
302
  cache?: IGatedTransactionCache;
230
303
  userInteractionCallbacks?: UserInteractionCallbacks;
231
- }): Promise<(GatedTx & { result: GatedTransactionResult })[]> => {
304
+ }): Promise<ResolvedGatedTransaction[]> => {
232
305
  //compute deps
233
306
  const allInternalIds = gatedTxes.map((tx) => getIdForGatedTransaction(tx));
234
307
  const allDeps = gatedTxes.flatMap((tx) => tx.dependencies ?? []);
@@ -238,8 +311,13 @@ export const resolveGatedTransactions = async <
238
311
 
239
312
  //prepopulate results for external dependencies
240
313
  //this map is only used for internal status tracking
241
- //map id -> was successful
242
- const results: Record<GatedTransactionId, boolean> = Object.fromEntries(
314
+ const results: Record<
315
+ GatedTransactionId,
316
+ {
317
+ resolved?: ResolvedGatedTransaction;
318
+ checkResult: { onChainData?: any; expectationMet: boolean };
319
+ }
320
+ > = Object.fromEntries(
243
321
  await Promise.all(
244
322
  allExternalDeps.map(async (tx) => {
245
323
  const checkResult = await checkGatedTransaction({
@@ -248,18 +326,27 @@ export const resolveGatedTransactions = async <
248
326
  cachedCheckResult: await cache?.getCachedTxCheckData?.(tx),
249
327
  });
250
328
 
251
- return [getIdForGatedTransaction(tx), checkResult.expectationMet];
329
+ return [
330
+ getIdForGatedTransaction(tx),
331
+ {
332
+ checkResult,
333
+ },
334
+ ];
252
335
  }),
253
336
  ),
254
337
  );
255
338
 
256
- const isTransactionSuccessful = (gtxId: GatedTransactionId) => results[gtxId];
339
+ const getTransactionResult = (gtxId: GatedTransactionId) => results[gtxId];
257
340
 
258
341
  const txFunctions = gatedTxes.map((tx) => async () => {
259
- const res = await resolveGatedTransaction<TxType, ProcessedTxType, GatedTx, ProcessTx>({
342
+ const { resolvedGatedTransaction, lastCheckResult } = await resolveGatedTransaction<
343
+ TxType,
344
+ GatedTx,
345
+ ProcessTx
346
+ >({
260
347
  gatedTx: tx,
261
348
  activityRegistry,
262
- isTransactionSuccessful,
349
+ getTransactionResult,
263
350
  processTx,
264
351
  confirmationCallback:
265
352
  userInteractionCallbacks?.confirmationCallback ?? (async () => true),
@@ -267,13 +354,20 @@ export const resolveGatedTransactions = async <
267
354
  cache,
268
355
  });
269
356
 
270
- const resId = getIdForGatedTransaction(res);
271
- results[resId] = [GatedTransactionStatus.SUCCESS, GatedTransactionStatus.NO_OP].includes(
272
- res.result.status,
273
- );
357
+ const resId = getIdForGatedTransaction(resolvedGatedTransaction);
358
+ results[resId] = {
359
+ resolved: resolvedGatedTransaction,
360
+ checkResult: {
361
+ expectationMet: [
362
+ GatedTransactionStatus.SUCCESS,
363
+ GatedTransactionStatus.NO_OP,
364
+ ].includes(resolvedGatedTransaction.result.status),
365
+ onChainData: lastCheckResult?.onChainData ?? undefined,
366
+ },
367
+ };
274
368
 
275
- userInteractionCallbacks?.onResultCallback?.(res);
276
- return res;
369
+ userInteractionCallbacks?.onResultCallback?.(resolvedGatedTransaction);
370
+ return resolvedGatedTransaction;
277
371
  });
278
372
 
279
373
  return await Promise.all(txFunctions.map((func) => func()));
@@ -281,9 +375,8 @@ export const resolveGatedTransactions = async <
281
375
 
282
376
  export const resolveSequencedGatedTransactions = async <
283
377
  TxType extends Transaction,
284
- ProcessedTxType extends Transaction,
285
378
  GatedTx extends GatedTransaction<string, TxType, any>,
286
- ProcessTx extends (transaction: TxType) => Promise<ProcessedTxType>,
379
+ ProcessTx extends (transaction: TxType) => Promise<TransactionResult>,
287
380
  >({
288
381
  activityRegistry,
289
382
  gatedTxes,
@@ -301,7 +394,7 @@ export const resolveSequencedGatedTransactions = async <
301
394
  }) => {
302
395
  const results = [];
303
396
  for (const seq of gatedTxes) {
304
- const result = await resolveGatedTransactions<TxType, ProcessedTxType, GatedTx, ProcessTx>({
397
+ const result = await resolveGatedTransactions<TxType, GatedTx, ProcessTx>({
305
398
  gatedTxes: seq,
306
399
  activityRegistry,
307
400
  processTx,
package/src/types.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  import z from 'zod/v4';
2
2
 
3
- import type {
4
- Transaction,
5
- transactionSchema as _transactionSchema,
3
+ import {
4
+ type Transaction,
5
+ type transactionSchema as _transactionSchema,
6
+ type TransactionWithResultFor,
7
+ type transactionWithResultSchema as _transactionWithResultSchema,
6
8
  } from '@layerzerolabs/common-chain-model';
7
9
  import type { FunctionPointer } from '@layerzerolabs/common-utils';
8
- import { functionSchema } from '@layerzerolabs/zod-utils';
10
+ import type { BuildTuple } from '@layerzerolabs/typescript-utils';
11
+ import { customSchema, functionSchema } from '@layerzerolabs/zod-utils';
9
12
 
10
13
  export type OnChainDataComparisonOperator<OnChainDataType> = OnChainDataType extends number
11
14
  ? '<' | '<=' | '=' | '!=' | '>' | '>='
@@ -17,39 +20,19 @@ export type OnChainDataComparison<OnChainDataType> = {
17
20
  };
18
21
 
19
22
  export type GatedTransactionCheck<
20
- Method extends (...args: any[]) => any = (...args: any[]) => unknown,
23
+ Method extends (...args: any[]) => Promise<any> = (...args: any[]) => Promise<unknown>,
21
24
  > = {
22
25
  functionPointer: FunctionPointer<Method>;
23
- params: any[];
26
+ params: Parameters<Method>;
24
27
  expectedResult: OnChainDataComparison<Awaited<ReturnType<Method>>>;
25
28
  };
26
29
 
27
- export const gatedTransactionSchema = <TransactionSchema extends typeof _transactionSchema>({
28
- transactionSchema,
29
- name,
30
- }: {
31
- transactionSchema: TransactionSchema;
32
- name: z.ZodString | z.ZodLiteral<string>;
33
- }) =>
34
- z.object({
35
- name,
36
- transaction: transactionSchema,
37
- check: z.object({
38
- functionPointer: z.any(),
39
- params: z.array(z.any()),
40
- expectedResult: z.object({
41
- operator: z.custom<OnChainDataComparisonOperator<any>>(),
42
- comparisonValue: z.any(),
43
- }),
44
- }),
45
- });
46
-
47
30
  // Schema for gated transaction results
48
31
  export const gatedTransactionResultSchema = <
49
- TransactionSchema extends typeof _transactionSchema,
32
+ TxWithResultSchema extends typeof _transactionWithResultSchema,
50
33
  OnchainDataSchema extends z.ZodType,
51
34
  >(
52
- transactionSchema: TransactionSchema,
35
+ txWithResultSchema: TxWithResultSchema,
53
36
  onchainDataSchema: OnchainDataSchema,
54
37
  ) =>
55
38
  z.union([
@@ -58,7 +41,7 @@ export const gatedTransactionResultSchema = <
58
41
  }),
59
42
  z.object({
60
43
  status: z.literal(GatedTransactionStatus.SUCCESS),
61
- submittedTransaction: transactionSchema,
44
+ submittedTransaction: txWithResultSchema,
62
45
  }),
63
46
  z.object({
64
47
  status: z.literal(GatedTransactionStatus.TRANSACTION_FAILED),
@@ -66,7 +49,7 @@ export const gatedTransactionResultSchema = <
66
49
  }),
67
50
  z.object({
68
51
  status: z.literal(GatedTransactionStatus.FINAL_CHECK_FAILED),
69
- submittedTransaction: transactionSchema,
52
+ submittedTransaction: txWithResultSchema,
70
53
  finalOnChainState: onchainDataSchema,
71
54
  }),
72
55
  z.object({
@@ -77,55 +60,62 @@ export const gatedTransactionResultSchema = <
77
60
  }),
78
61
  ]);
79
62
 
80
- // Schema for processed gated transactions (with results)
81
- export const processedGatedTransactionSchema = <
82
- TransactionSchema extends typeof _transactionSchema,
83
- OnchainDataSchema extends z.ZodType,
84
- >({
85
- transactionSchema,
86
- onchainDataSchema,
87
- name,
88
- }: {
89
- transactionSchema: TransactionSchema;
90
- onchainDataSchema: OnchainDataSchema;
91
- name: z.ZodString | z.ZodLiteral<string>;
92
- }) =>
93
- gatedTransactionSchema({
94
- transactionSchema,
95
- name,
96
- }).and(
97
- z.object({
98
- result: gatedTransactionResultSchema(transactionSchema, onchainDataSchema),
99
- }),
100
- );
101
-
102
- type GatedTransactionDependencies = GatedTransaction[];
63
+ export type InferOnChainDataTypeFromCheck<Check> = Check extends (...args: any[]) => infer Ret
64
+ ? Awaited<Ret>
65
+ : unknown;
66
+ export type InferOnChainDataTypeFromGatedTransaction<GatedTx extends GatedTransaction> =
67
+ InferOnChainDataTypeFromCheck<GatedTx['check']>;
103
68
 
104
- export type GatedTransaction<
69
+ export type GatedTransactionDependencies = GatedTransaction[];
70
+ export type BaseGatedTransaction<
105
71
  Name extends string = string,
106
- TxType extends Transaction = Transaction,
107
72
  CheckMethod extends (...args: any[]) => any = (...args: any[]) => any,
108
- Dependencies extends GatedTransactionDependencies = GatedTransactionDependencies,
73
+ _Dependencies extends GatedTransactionDependencies = GatedTransactionDependencies,
109
74
  > = {
110
- bundleName?: string;
111
75
  name: Name;
112
- transaction: TxType;
76
+ bundleName?: string;
77
+ chainName: string;
113
78
  check: GatedTransactionCheck<CheckMethod>;
79
+ dependencies: _Dependencies;
114
80
  cacheable?: boolean;
115
81
  uniqueIdKeys?: Record<string, string | number | boolean>;
116
- dependencies?: Dependencies;
117
82
  };
118
83
 
119
- export type ProcessedGatedTransaction<
84
+ export type LiteralGatedTransaction<
120
85
  Name extends string = string,
121
86
  TxType extends Transaction = Transaction,
122
87
  CheckMethod extends (...args: any[]) => any = (...args: any[]) => any,
123
- > = GatedTransaction<Name, TxType, CheckMethod> & {
124
- result: GatedTransactionResult<GatedTransaction<Name, TxType, CheckMethod>, TxType>;
88
+ _Dependencies extends GatedTransactionDependencies = GatedTransactionDependencies,
89
+ > = BaseGatedTransaction<Name, CheckMethod, _Dependencies> & {
90
+ transactionType: 'literal';
91
+ transaction: TxType;
125
92
  };
126
93
 
127
- export type InferOnChainDataTypeFromGatedTransaction<GatedTx extends GatedTransaction> =
128
- GatedTx extends GatedTransaction<any, any, infer Check> ? Awaited<ReturnType<Check>> : unknown;
94
+ export type FunctionalGatedTransaction<
95
+ Name extends string = string,
96
+ TxType extends Transaction = Transaction,
97
+ CheckMethod extends (...args: any[]) => any = (...args: any[]) => any,
98
+ DepMethod extends (txs: any) => Promise<TxType> = (txs: any) => Promise<any>,
99
+ _Dependencies extends GatedTransactionDependencies = GatedTransactionDependencies,
100
+ > = BaseGatedTransaction<Name, CheckMethod, _Dependencies> & {
101
+ transactionType: 'functional';
102
+ getTransactionPointer: FunctionPointer<DepMethod>;
103
+ };
104
+
105
+ export type GatedTransaction<
106
+ Name extends string = string,
107
+ TxType extends Transaction = Transaction,
108
+ CheckMethod extends (...args: any[]) => any = (...args: any[]) => any,
109
+ DepMethod extends (txs: any) => Promise<TxType> = (txs: any) => Promise<any>,
110
+ _Dependencies extends GatedTransactionDependencies = GatedTransactionDependencies,
111
+ > =
112
+ | LiteralGatedTransaction<Name, TxType, CheckMethod, _Dependencies>
113
+ | FunctionalGatedTransaction<Name, TxType, CheckMethod, DepMethod, _Dependencies>;
114
+
115
+ export type BaseGatedTransactionFor<GatedTx extends GatedTransaction> =
116
+ GatedTx extends GatedTransaction<infer Name, any, infer CheckMethod, any, infer _Dependencies>
117
+ ? BaseGatedTransaction<Name, CheckMethod, _Dependencies>
118
+ : never;
129
119
 
130
120
  export enum GatedTransactionStatus {
131
121
  NO_OP = 'no_op',
@@ -140,9 +130,9 @@ type NoOpGatedTransaction = {
140
130
  status: GatedTransactionStatus.NO_OP;
141
131
  };
142
132
 
143
- type SuccessfulGatedTransaction<ProcessedTx extends Transaction> = {
133
+ type SuccessfulGatedTransaction<TxType extends Transaction> = {
144
134
  status: GatedTransactionStatus.SUCCESS;
145
- submittedTransaction: ProcessedTx;
135
+ submittedTransaction: TransactionWithResultFor<TxType>;
146
136
  };
147
137
 
148
138
  type TxFailedGatedTransaction = {
@@ -150,10 +140,10 @@ type TxFailedGatedTransaction = {
150
140
  transactionError: any;
151
141
  };
152
142
 
153
- type CheckFailedGatedTransaction<ProcessedTx extends Transaction, State> = {
143
+ type CheckFailedGatedTransaction<GatedTx extends GatedTransaction, TxType extends Transaction> = {
154
144
  status: GatedTransactionStatus.FINAL_CHECK_FAILED;
155
- submittedTransaction: ProcessedTx;
156
- finalOnChainState: State;
145
+ submittedTransaction: TransactionWithResultFor<TxType>;
146
+ finalOnChainState: InferOnChainDataTypeFromGatedTransaction<GatedTx>;
157
147
  };
158
148
 
159
149
  type DependencyFailedGatedTransaction = {
@@ -166,15 +156,12 @@ type DeniedGatedTransaction = {
166
156
 
167
157
  export type GatedTransactionResult<
168
158
  GatedTx extends GatedTransaction = GatedTransaction,
169
- ProcessedTxType extends Transaction = Transaction,
159
+ TxType extends Transaction = Transaction,
170
160
  > =
171
161
  | NoOpGatedTransaction
172
- | SuccessfulGatedTransaction<ProcessedTxType>
162
+ | SuccessfulGatedTransaction<TxType>
173
163
  | TxFailedGatedTransaction
174
- | CheckFailedGatedTransaction<
175
- ProcessedTxType,
176
- InferOnChainDataTypeFromGatedTransaction<GatedTx>
177
- >
164
+ | CheckFailedGatedTransaction<GatedTx, TxType>
178
165
  | DependencyFailedGatedTransaction
179
166
  | DeniedGatedTransaction;
180
167
 
@@ -207,7 +194,78 @@ export type IGatedTransactionCache = z.infer<typeof gatedTransactionCacheSchema>
207
194
  */
208
195
  export type GatedTransactionId = `${string}-${string}-${string}`;
209
196
 
197
+ export type ResolvedGatedTransaction<
198
+ GatedTx extends GatedTransaction = GatedTransaction,
199
+ TxType extends Transaction = Transaction,
200
+ > = BaseGatedTransactionFor<GatedTx> & {
201
+ result: GatedTransactionResult<GatedTx, TxType>;
202
+ };
203
+
210
204
  export type UserInteractionCallbacks = {
211
205
  confirmationCallback?: (gtx: GatedTransaction) => Promise<boolean>;
212
- onResultCallback?: (result: GatedTransaction & { result: GatedTransactionResult }) => void;
206
+ onResultCallback?: (result: ResolvedGatedTransaction) => void;
213
207
  };
208
+
209
+ export const gatedTransactionSchema = <
210
+ Name extends z.ZodString | z.ZodLiteral<string> = z.ZodString,
211
+ TransactionSchema extends typeof _transactionSchema = typeof _transactionSchema,
212
+ >(_?: {
213
+ name?: Name;
214
+ transactionSchema?: TransactionSchema;
215
+ }) => customSchema<GatedTransaction<z.infer<Name>, z.infer<TransactionSchema>>>();
216
+
217
+ export const resolvedGatedTransactionSchema = <
218
+ Name extends z.ZodString | z.ZodLiteral<string> = z.ZodString,
219
+ TransactionSchema extends typeof _transactionSchema = typeof _transactionSchema,
220
+ >(_?: {
221
+ name?: Name;
222
+ transactionSchema?: TransactionSchema;
223
+ }) =>
224
+ customSchema<
225
+ ResolvedGatedTransaction<
226
+ GatedTransaction<z.infer<Name>, z.infer<TransactionSchema>>,
227
+ z.infer<TransactionSchema>
228
+ >
229
+ >();
230
+
231
+ /**
232
+ * Builds a schema for an activity that builds a transaction based on the results of other transactions
233
+ * @param transactionSchema The schema for the transaction to be built
234
+ * @param transactionWithResultSchema The schema for the results of the transactions you're building off of
235
+ * @param txNumber The number of transactions you're building off of
236
+ * @returns A schema for the activity that builds the transaction
237
+ */
238
+ export const createTxDependentActivitySchema = <
239
+ TransactionSchema extends typeof _transactionSchema = typeof _transactionSchema,
240
+ const TxNumber extends number = 1,
241
+ >(
242
+ transactionSchema: TransactionSchema,
243
+ txNumber: TxNumber,
244
+ ) => {
245
+ const txs = Array.from({ length: txNumber }, () =>
246
+ resolvedGatedTransactionSchema({
247
+ name: z.string(),
248
+ transactionSchema: transactionSchema,
249
+ }),
250
+ );
251
+ return functionSchema({
252
+ input: z.tuple([z.tuple(txs as any)]),
253
+ output: z.promise(transactionSchema),
254
+ }) as z.ZodType<
255
+ (
256
+ txs: BuildTuple<
257
+ ResolvedGatedTransaction<
258
+ GatedTransaction<string, z.infer<TransactionSchema>, any, any, any>
259
+ >,
260
+ TxNumber
261
+ >,
262
+ ) => Promise<z.infer<TransactionSchema>>
263
+ >;
264
+ };
265
+
266
+ export type ResolvedGatedTransactionDependencies<GatedTx extends GatedTransaction> =
267
+ GatedTx extends GatedTransaction<any, any, any, any, infer _Dependencies>
268
+ ? {
269
+ [K in keyof _Dependencies]?: ResolvedGatedTransaction<_Dependencies[K]>;
270
+ }
271
+ : never;