@layerzerolabs/gated-transaction 0.0.30 → 0.0.32

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