@boostxyz/sdk 0.0.0-alpha.19 → 0.0.0-alpha.20

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.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { BOOST_REGISTRY_ADDRESS as o, BOOST_REGISTRY_ADDRESSES as a, BoostRegistry as t } from "./BoostRegistry.js";
2
- import { a as n, b as s, B as p, c as l, E as d, p as E } from "./BoostCore-kwoUw7YE.js";
2
+ import { a as n, b as p, B as s, c as l, E as d, p as E } from "./BoostCore-DVGBUr2y.js";
3
3
  import { Boost as c, prepareBoostPayload as A } from "./Boost.js";
4
4
  import { ActionByComponentInterface as f, actionFromAddress as C } from "./Actions/Action.js";
5
- import { E as I, F as b, P as v, S, i as P, p as R } from "./EventAction-D5tnm00s.js";
5
+ import { E as b, F as g, P as v, S, i as P, p as R } from "./EventAction-CIPqmAoP.js";
6
6
  import { AllowListByComponentInterface as x, OpenAllowList as D, allowListFromAddress as B } from "./AllowLists/AllowList.js";
7
- import { LIST_MANAGER_ROLE as F, SimpleAllowList as L, prepareSimpleAllowListPayload as O } from "./AllowLists/SimpleAllowList.js";
8
- import { S as w, p as M } from "./SimpleDenyList-Cn5WpNn0.js";
9
- import { BudgetByComponentInterface as h, budgetFromAddress as N } from "./Budgets/Budget.js";
7
+ import { LIST_MANAGER_ROLE as F, SimpleAllowList as O, prepareSimpleAllowListPayload as L } from "./AllowLists/SimpleAllowList.js";
8
+ import { S as w, p as _ } from "./SimpleDenyList-Cn5WpNn0.js";
9
+ import { BudgetByComponentInterface as M, budgetFromAddress as N } from "./Budgets/Budget.js";
10
10
  import { ManagedBudget as G, ManagedBudgetRoles as z, isERC1155TransferPayload as k, isFungibleTransfer as q, prepareManagedBudgetPayload as W, prepareTransfer as Y } from "./Budgets/ManagedBudget.js";
11
11
  import { Deployable as H } from "./Deployable/Deployable.js";
12
12
  import { Contract as K } from "./Deployable/Contract.js";
@@ -14,54 +14,54 @@ import { DeployableTarget as X } from "./Deployable/DeployableTarget.js";
14
14
  import { DeployableTargetWithRBAC as $, Roles as ee } from "./Deployable/DeployableTargetWithRBAC.js";
15
15
  import { AllowListIncentive as oe, prepareAllowListIncentivePayload as ae } from "./Incentives/AllowListIncentive.js";
16
16
  import { CGDAIncentive as ie, prepareCGDAIncentivePayload as ne } from "./Incentives/CGDAIncentive.js";
17
- import { ERC20Incentive as pe, prepareERC20IncentivePayload as le } from "./Incentives/ERC20Incentive.js";
17
+ import { ERC20Incentive as se, prepareERC20IncentivePayload as le } from "./Incentives/ERC20Incentive.js";
18
18
  import { E as Ee, I as me, i as ce, p as Ae } from "./Incentive-Bp8Sez7M.js";
19
19
  import { PointsIncentive as fe, preparePointsIncentivePayload as Ce } from "./Incentives/PointsIncentive.js";
20
- import { SignerValidator as Ie, prepareSignerValidatorClaimDataPayload as be, prepareSignerValidatorInputParams as ve, prepareSignerValidatorPayload as Se } from "./Validators/SignerValidator.js";
20
+ import { SignerValidator as be, prepareSignerValidatorClaimDataPayload as ge, prepareSignerValidatorInputParams as ve, prepareSignerValidatorPayload as Se } from "./Validators/SignerValidator.js";
21
21
  import { ValidatorByComponentInterface as Re, validatorFromAddress as ue } from "./Validators/Validator.js";
22
- import { BoostCoreNoIdentifierEmitted as De, BudgetMustAuthorizeBoostCore as Be, ContractAddressRequiredError as Te, DecodedArgsError as Fe, DecodedArgsMalformedError as Le, DeployableAlreadyDeployedError as Oe, DeployableBuildParametersUnspecifiedError as Ve, DeployableMissingPayloadError as we, DeployableUnknownOwnerProvidedError as Me, DeployableWagmiConfigurationRequiredError as _e, FieldActionValidationError as he, FieldValueNotComparableError as Ne, FieldValueUndefinedError as Ue, FunctionDataDecodeError as Ge, IncentiveCriteriaNotFoundError as ze, IncentiveNotCloneableError as ke, InvalidComponentInterfaceError as qe, InvalidCriteriaTypeError as We, InvalidNumericalCriteriaError as Ye, InvalidProtocolChainIdError as je, MustInitializeBudgetError as He, NoConnectedChainIdError as Je, NoContractAddressUponReceiptError as Ke, NoEventActionStepsProvidedError as Qe, NoMatchingLogsError as Xe, TooManyEventActionStepsProvidedError as Ze, UnknownTransferPayloadSupplied as $e, UnparseableAbiParamError as er, UnrecognizedFilterTypeError as rr, ValidationAbiMissingError as or, ValidationLogsMissingError as ar } from "./errors.js";
23
- import { RegistryType as ir, assertValidAddressByChainId as nr, awaitResult as sr, bytes4 as pr, getDeployedContractAddress as lr } from "./utils.js";
24
- import { StrategyType as Er, prepareClaimPayload as mr } from "./claiming.js";
25
- import { AssetType as Ar, prepareERC1155Payload as yr, prepareERC1155Transfer as fr, prepareFungiblePayload as Cr, prepareFungibleTransfer as gr, prepareTransferPayload as Ir } from "./transfers.js";
26
- import { PassthroughAuth as vr } from "./Auth/PassthroughAuth.js";
27
- import { R as Pr, b as Rr, a as ur, g as xr, T as Dr, O as Br, l as Tr, d as Fr, c as Lr, z as Or, x as Vr, A as wr, I as Mr } from "./generated-B7VaSah4.js";
22
+ import { BoostCoreNoIdentifierEmitted as De, BudgetMustAuthorizeBoostCore as Be, ContractAddressRequiredError as Te, DecodedArgsError as Fe, DecodedArgsMalformedError as Oe, DeployableAlreadyDeployedError as Le, DeployableBuildParametersUnspecifiedError as Ve, DeployableMissingPayloadError as we, DeployableUnknownOwnerProvidedError as _e, DeployableWagmiConfigurationRequiredError as he, FieldActionValidationError as Me, FieldValueNotComparableError as Ne, FieldValueUndefinedError as Ue, FunctionDataDecodeError as Ge, IncentiveCriteriaNotFoundError as ze, IncentiveNotCloneableError as ke, InvalidComponentInterfaceError as qe, InvalidCriteriaTypeError as We, InvalidNumericalCriteriaError as Ye, InvalidProtocolChainIdError as je, MustInitializeBudgetError as He, NoConnectedChainIdError as Je, NoContractAddressUponReceiptError as Ke, NoEventActionStepsProvidedError as Qe, NoMatchingLogsError as Xe, TooManyEventActionStepsProvidedError as Ze, UnknownTransferPayloadSupplied as $e, UnparseableAbiParamError as er, UnrecognizedFilterTypeError as rr, ValidationAbiMissingError as or } from "./errors.js";
23
+ import { RegistryType as tr, assertValidAddressByChainId as ir, awaitResult as nr, bytes4 as pr, getDeployedContractAddress as sr } from "./utils.js";
24
+ import { StrategyType as dr, prepareClaimPayload as Er } from "./claiming.js";
25
+ import { AssetType as cr, prepareERC1155Payload as Ar, prepareERC1155Transfer as yr, prepareFungiblePayload as fr, prepareFungibleTransfer as Cr, prepareTransferPayload as Ir } from "./transfers.js";
26
+ import { PassthroughAuth as gr } from "./Auth/PassthroughAuth.js";
27
+ import { R as Sr, b as Pr, a as Rr, g as ur, T as xr, O as Dr, l as Br, d as Tr, c as Fr, z as Or, x as Lr, A as Vr, I as wr } from "./generated-B7VaSah4.js";
28
28
  export {
29
29
  f as ActionByComponentInterface,
30
30
  x as AllowListByComponentInterface,
31
31
  oe as AllowListIncentive,
32
- Ar as AssetType,
32
+ cr as AssetType,
33
33
  n as BOOST_CORE_ADDRESS,
34
- s as BOOST_CORE_ADDRESSES,
35
- p as BOOST_CORE_CLAIM_FEE,
34
+ p as BOOST_CORE_ADDRESSES,
35
+ s as BOOST_CORE_CLAIM_FEE,
36
36
  o as BOOST_REGISTRY_ADDRESS,
37
37
  a as BOOST_REGISTRY_ADDRESSES,
38
38
  c as Boost,
39
39
  l as BoostCore,
40
40
  De as BoostCoreNoIdentifierEmitted,
41
41
  t as BoostRegistry,
42
- h as BudgetByComponentInterface,
42
+ M as BudgetByComponentInterface,
43
43
  Be as BudgetMustAuthorizeBoostCore,
44
44
  ie as CGDAIncentive,
45
45
  K as Contract,
46
46
  Te as ContractAddressRequiredError,
47
47
  Fe as DecodedArgsError,
48
- Le as DecodedArgsMalformedError,
48
+ Oe as DecodedArgsMalformedError,
49
49
  H as Deployable,
50
- Oe as DeployableAlreadyDeployedError,
50
+ Le as DeployableAlreadyDeployedError,
51
51
  Ve as DeployableBuildParametersUnspecifiedError,
52
52
  we as DeployableMissingPayloadError,
53
53
  X as DeployableTarget,
54
54
  $ as DeployableTargetWithRBAC,
55
- Me as DeployableUnknownOwnerProvidedError,
56
- _e as DeployableWagmiConfigurationRequiredError,
57
- pe as ERC20Incentive,
55
+ _e as DeployableUnknownOwnerProvidedError,
56
+ he as DeployableWagmiConfigurationRequiredError,
57
+ se as ERC20Incentive,
58
58
  d as ERC20VariableCriteriaIncentive,
59
59
  Ee as ERC20VariableIncentive,
60
- I as EventAction,
61
- he as FieldActionValidationError,
60
+ b as EventAction,
61
+ Me as FieldActionValidationError,
62
62
  Ne as FieldValueNotComparableError,
63
63
  Ue as FieldValueUndefinedError,
64
- b as FilterType,
64
+ g as FilterType,
65
65
  Ge as FunctionDataDecodeError,
66
66
  me as IncentiveByComponentInterface,
67
67
  ze as IncentiveCriteriaNotFoundError,
@@ -79,68 +79,67 @@ export {
79
79
  Qe as NoEventActionStepsProvidedError,
80
80
  Xe as NoMatchingLogsError,
81
81
  D as OpenAllowList,
82
- vr as PassthroughAuth,
82
+ gr as PassthroughAuth,
83
83
  fe as PointsIncentive,
84
84
  v as PrimitiveType,
85
- ir as RegistryType,
85
+ tr as RegistryType,
86
86
  ee as Roles,
87
87
  S as SignatureType,
88
- Ie as SignerValidator,
89
- L as SimpleAllowList,
88
+ be as SignerValidator,
89
+ O as SimpleAllowList,
90
90
  w as SimpleDenyList,
91
- Er as StrategyType,
91
+ dr as StrategyType,
92
92
  Ze as TooManyEventActionStepsProvidedError,
93
93
  $e as UnknownTransferPayloadSupplied,
94
94
  er as UnparseableAbiParamError,
95
95
  rr as UnrecognizedFilterTypeError,
96
96
  or as ValidationAbiMissingError,
97
- ar as ValidationLogsMissingError,
98
97
  Re as ValidatorByComponentInterface,
99
98
  C as actionFromAddress,
100
99
  B as allowListFromAddress,
101
- Pr as allowListIncentiveAbi,
102
- nr as assertValidAddressByChainId,
103
- sr as awaitResult,
104
- Rr as boostCoreAbi,
105
- ur as boostRegistryAbi,
100
+ Sr as allowListIncentiveAbi,
101
+ ir as assertValidAddressByChainId,
102
+ nr as awaitResult,
103
+ Pr as boostCoreAbi,
104
+ Rr as boostRegistryAbi,
106
105
  N as budgetFromAddress,
107
106
  pr as bytes4,
108
- xr as cgdaIncentiveAbi,
109
- Dr as erc20IncentiveAbi,
110
- Br as erc20VariableIncentiveAbi,
111
- lr as getDeployedContractAddress,
107
+ ur as cgdaIncentiveAbi,
108
+ xr as erc20IncentiveAbi,
109
+ Dr as erc20VariableIncentiveAbi,
110
+ sr as getDeployedContractAddress,
112
111
  ce as incentiveFromAddress,
113
112
  k as isERC1155TransferPayload,
114
113
  P as isEventActionPayloadSimple,
115
114
  q as isFungibleTransfer,
116
- Tr as managedBudgetAbi,
117
- Fr as passthroughAuthAbi,
118
- Lr as pointsIncentiveAbi,
115
+ Br as managedBudgetAbi,
116
+ Tr as passthroughAuthAbi,
117
+ Fr as pointsIncentiveAbi,
119
118
  ae as prepareAllowListIncentivePayload,
120
119
  A as prepareBoostPayload,
121
120
  ne as prepareCGDAIncentivePayload,
122
- mr as prepareClaimPayload,
123
- yr as prepareERC1155Payload,
124
- fr as prepareERC1155Transfer,
121
+ Er as prepareClaimPayload,
122
+ Ar as prepareERC1155Payload,
123
+ yr as prepareERC1155Transfer,
125
124
  le as prepareERC20IncentivePayload,
126
125
  E as prepareERC20VariableCriteriaIncentivePayload,
127
126
  Ae as prepareERC20VariableIncentivePayload,
128
127
  R as prepareEventActionPayload,
129
- Cr as prepareFungiblePayload,
130
- gr as prepareFungibleTransfer,
128
+ fr as prepareFungiblePayload,
129
+ Cr as prepareFungibleTransfer,
131
130
  W as prepareManagedBudgetPayload,
132
131
  Ce as preparePointsIncentivePayload,
133
- be as prepareSignerValidatorClaimDataPayload,
132
+ ge as prepareSignerValidatorClaimDataPayload,
134
133
  ve as prepareSignerValidatorInputParams,
135
134
  Se as prepareSignerValidatorPayload,
136
- O as prepareSimpleAllowListPayload,
137
- M as prepareSimpleDenyListPayload,
135
+ L as prepareSimpleAllowListPayload,
136
+ _ as prepareSimpleDenyListPayload,
138
137
  Y as prepareTransfer,
139
138
  Ir as prepareTransferPayload,
140
139
  Or as rbacAbi,
141
- Vr as signerValidatorAbi,
142
- wr as simpleAllowListAbi,
143
- Mr as simpleDenyListAbi,
140
+ Lr as signerValidatorAbi,
141
+ Vr as simpleAllowListAbi,
142
+ wr as simpleDenyListAbi,
144
143
  ue as validatorFromAddress
145
144
  };
146
145
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boostxyz/sdk",
3
- "version": "0.0.0-alpha.19",
3
+ "version": "0.0.0-alpha.20",
4
4
  "license": "GPL-3.0-or-later",
5
5
  "type": "module",
6
6
  "files": [
@@ -482,6 +482,34 @@ describe("EventAction Event Selector", () => {
482
482
  expect(await action.validateActionSteps({ hash, chainId })).toBe(true);
483
483
  });
484
484
  });
485
+
486
+ test("can derive the claimant from an event action", async () => {
487
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
488
+ const recipient = accounts[1].account;
489
+ await erc721.approve(recipient, 1n);
490
+ const { hash } = await erc721.transferFromRaw(defaultOptions.account.address, recipient, 1n);
491
+ expect(
492
+ await action.deriveActionClaimantFromTransaction(await action.getActionClaimant(), {
493
+ hash,
494
+ chainId,
495
+ }),
496
+ ).toBe(recipient);
497
+ });
498
+
499
+ test("can derive the claimant from a function action", async () => {
500
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
501
+ const recipient = accounts[1].account;
502
+ const { hash } = await erc721.mintRaw(recipient, {
503
+ value: parseEther(".1"),
504
+ });
505
+
506
+ expect(
507
+ await action.deriveActionClaimantFromTransaction(await action.getActionClaimant(), {
508
+ hash,
509
+ chainId,
510
+ }),
511
+ ).toBe(recipient);
512
+ });
485
513
  });
486
514
  });
487
515
 
@@ -8,11 +8,17 @@ import {
8
8
  import { bytecode } from '@boostxyz/evm/artifacts/contracts/actions/EventAction.sol/EventAction.json';
9
9
  import events from '@boostxyz/signatures/events';
10
10
  import functions from '@boostxyz/signatures/functions';
11
+ import {
12
+ GetTransactionReceiptParameters,
13
+ getTransaction,
14
+ getTransactionReceipt,
15
+ } from '@wagmi/core';
11
16
  import { match } from 'ts-pattern';
12
17
  import {
13
18
  type Abi,
14
19
  type AbiEvent,
15
20
  type AbiFunction,
21
+ AbiItem,
16
22
  type Address,
17
23
  type ContractEventName,
18
24
  type ContractFunctionName,
@@ -26,6 +32,7 @@ import {
26
32
  decodeFunctionData,
27
33
  encodeAbiParameters,
28
34
  fromHex,
35
+ isAddress,
29
36
  isAddressEqual,
30
37
  } from 'viem';
31
38
  import { EventAction as EventActionBases } from '../../dist/deployments.json';
@@ -45,7 +52,6 @@ import {
45
52
  UnparseableAbiParamError,
46
53
  UnrecognizedFilterTypeError,
47
54
  ValidationAbiMissingError,
48
- ValidationLogsMissingError,
49
55
  } from '../errors';
50
56
  import {
51
57
  type GetLogsParams,
@@ -220,15 +226,15 @@ export interface ActionStep {
220
226
  * Parameters for validating an action step.
221
227
  *
222
228
  * @typedef {Object} ValidateActionStepParams
223
- * @property {Record<Hex, AbiEvent>} [knownEvents] - Optional record of known events, keyed by their hex signature.
224
- * @property {AbiEvent} [event] - Optional ABI event definition.
229
+ * @property {Record<Hex, AbiEvent | AbiFunction>} [knownSignatures] - Optional record of known events, keyed by 32 byte selectors.
230
+ * @property {AbiEvent | AbiFunction} [abiItem] - Optional ABI item definition.
225
231
  * @property {EventLogs} [logs] - Event logs to validate against. Required if 'hash' is not provided.
226
232
  * @property {Hex} [hash] - Transaction hash to validate against. Required if 'logs' is not provided.
227
233
  * @property {number} [chainId] - Chain ID for the transaction. Required if 'hash' is provided.
228
234
  */
229
235
  export type ValidateActionStepParams = {
230
- knownEvents?: Record<Hex, AbiEvent>;
231
- event?: AbiEvent;
236
+ knownSignatures?: Record<Hex, AbiEvent | AbiFunction>;
237
+ abiItem?: AbiEvent | AbiFunction;
232
238
  } & ({ logs: EventLogs } | { hash: Hex; chainId: number });
233
239
 
234
240
  /**
@@ -432,7 +438,7 @@ export class EventAction extends DeployableTarget<
432
438
  */
433
439
  public async getActionClaimant(
434
440
  params?: ReadEventActionParams<'getActionClaimant'>,
435
- ) {
441
+ ): Promise<ActionClaimant> {
436
442
  const result = (await readEventActionGetActionClaimant(this._config, {
437
443
  address: this.assertValidAddress(),
438
444
  ...this.optionallyAttachAccount(),
@@ -481,6 +487,141 @@ export class EventAction extends DeployableTarget<
481
487
  return { hash, result };
482
488
  }
483
489
 
490
+ /**
491
+ * Derives the action claimant address from a transaction based on the provided ActionClaimant configuration.
492
+ * This method supports both event-based and function-based claimant derivation.
493
+ *
494
+ ** @example
495
+ * // Example usage
496
+ * const eventAction = boost.action as EventAction
497
+ * const claimant = await eventAction.getActionClaimant() // {
498
+ * signatureType: SignatureType.EVENT,
499
+ * signature: '0x1234...',
500
+ * fieldIndex: 2,
501
+ * targetContract: '0xabcd...',
502
+ * chainid: 1
503
+ * };
504
+ * const params: ValidateActionStepParams = {
505
+ * hash: '0x5678...',
506
+ * chainId: 1,
507
+ * knownSignatures?: {
508
+ * '0x1234...': {}
509
+ * }
510
+ * };
511
+ * const claimantAddress = await eventAction.deriveActionClaimantFromTransaction(claimant, params);
512
+ *
513
+ * @param {ActionClaimant} claimant - The configuration specifying how to derive the claimant.
514
+ * @param {ValidateActionStepParams} params - Parameters for validation, including transaction hash, known signatures, logs, and chain ID.
515
+ * @returns {Promise<Address | undefined>} The derived claimant address if found, undefined otherwise.
516
+ * @throws {ValidationAbiMissingError} If the ABI for the specified signature is not found.
517
+ * @throws {FunctionDataDecodeError} If there's an error decoding function data (for function-based derivation).
518
+ */
519
+ public async deriveActionClaimantFromTransaction(
520
+ claimant: ActionClaimant,
521
+ params: ValidateActionStepParams,
522
+ ): Promise<Address | undefined> {
523
+ const signature = claimant.signature;
524
+ if (claimant.signatureType === SignatureType.EVENT) {
525
+ let event: AbiEvent;
526
+ if (params.abiItem) event = params.abiItem as AbiEvent;
527
+ if (params.knownSignatures) {
528
+ event = params.knownSignatures?.[signature] as AbiEvent;
529
+ } else {
530
+ event = (events.abi as Record<Hex, AbiEvent>)[signature] as AbiEvent;
531
+ }
532
+
533
+ if (!event) {
534
+ throw new ValidationAbiMissingError(signature);
535
+ }
536
+
537
+ let address: Address | undefined;
538
+ if ('logs' in params) {
539
+ for (let log of params.logs) {
540
+ if (!isAddressEqual(log.address, claimant.targetContract)) continue;
541
+ let addressCandidate = this.validateClaimantAgainstArgs(
542
+ claimant,
543
+ log,
544
+ );
545
+ if (addressCandidate) address = addressCandidate;
546
+ }
547
+ return address;
548
+ }
549
+ const receipt = await getTransactionReceipt(this._config, params);
550
+ const decodedLogs = receipt.logs.map((log) => {
551
+ const { eventName, args } = decodeEventLog({
552
+ abi: [event],
553
+ data: log.data,
554
+ topics: log.topics,
555
+ });
556
+ return { ...log, eventName, args };
557
+ });
558
+
559
+ for (let log of decodedLogs) {
560
+ if (!isAddressEqual(log.address, claimant.targetContract)) continue;
561
+ let addressCandidate = this.validateClaimantAgainstArgs(claimant, log);
562
+ if (addressCandidate) address = addressCandidate;
563
+ }
564
+ return address;
565
+ }
566
+ if (
567
+ claimant.signatureType === SignatureType.FUNC &&
568
+ 'hash' in params &&
569
+ 'chainId' in params
570
+ ) {
571
+ const transaction = await getTransaction(this._config, {
572
+ hash: params.hash,
573
+ });
574
+ if (!isAddressEqual(transaction.to!, claimant.targetContract)) return;
575
+ let func: AbiFunction;
576
+ if (params.abiItem) func = params.abiItem as AbiFunction;
577
+ if (params.knownSignatures) {
578
+ func = params.knownSignatures?.[signature] as AbiFunction;
579
+ } else {
580
+ func = (functions.abi as Record<Hex, AbiFunction>)[
581
+ signature
582
+ ] as AbiFunction;
583
+ }
584
+ if (!func) {
585
+ throw new ValidationAbiMissingError(claimant.signature);
586
+ }
587
+ let decodedData;
588
+ try {
589
+ decodedData = decodeFunctionData({
590
+ abi: [func],
591
+ data: transaction.input,
592
+ });
593
+ } catch (e) {
594
+ throw new FunctionDataDecodeError([func], e as Error);
595
+ }
596
+ return this.validateClaimantAgainstArgs(claimant, decodedData);
597
+ }
598
+ }
599
+
600
+ /**
601
+ * Validates the action claimant against the arguments of a log or function data.
602
+ *
603
+ * @param {ActionClaimant} claimant - The action claimant to validate.
604
+ * @param {Object} [logOrFnData] - Optional object containing the arguments to validate against.
605
+ * @param {Array<any> | readonly unknown[] | Record<string, unknown>} [logOrFnData.args] - The arguments from the log or function data.
606
+ * @returns {Address | undefined} The validated address if found and valid, otherwise undefined.
607
+ */
608
+ public validateClaimantAgainstArgs(
609
+ claimant: ActionClaimant,
610
+ logOrFnData?: {
611
+ args: Array<unknown> | readonly unknown[] | Record<string, unknown>;
612
+ },
613
+ ): Address | undefined {
614
+ if (
615
+ !logOrFnData ||
616
+ !Array.isArray(logOrFnData?.args) ||
617
+ logOrFnData?.args.length <= claimant.fieldIndex
618
+ ) {
619
+ return;
620
+ }
621
+ const maybeAddress = logOrFnData.args.at(claimant.fieldIndex);
622
+ if (isAddress(maybeAddress)) return maybeAddress;
623
+ }
624
+
484
625
  /**
485
626
  * Retrieves action steps, and uses them to validate against, and optionally fetch logs that match the step's signature.
486
627
  * If logs are provided in the optional `params` argument, then those logs will be used instead of fetched with the configured client.
@@ -518,9 +659,9 @@ export class EventAction extends DeployableTarget<
518
659
  if (actionStep.signatureType === SignatureType.EVENT) {
519
660
  const signature = actionStep.signature;
520
661
  let event: AbiEvent;
521
- // Lookup ABI based on event signature
522
- if (params.knownEvents) {
523
- event = params.knownEvents?.[signature] as AbiEvent;
662
+ if (params.abiItem) event = params.abiItem as AbiEvent;
663
+ if (params.knownSignatures) {
664
+ event = params.knownSignatures?.[signature] as AbiEvent;
524
665
  } else {
525
666
  event = (events.abi as Record<Hex, AbiEvent>)[signature] as AbiEvent;
526
667
  }
@@ -537,13 +678,9 @@ export class EventAction extends DeployableTarget<
537
678
  );
538
679
  }
539
680
 
540
- params.event = event;
541
-
542
681
  // Use the provided logs, no need to fetch receipt
543
682
  if ('logs' in params) {
544
- return this.isActionEventValid(actionStep, {
545
- ...params,
546
- });
683
+ return this.isActionEventValid(actionStep, params.logs);
547
684
  }
548
685
 
549
686
  const client = this._config.getClient({
@@ -562,10 +699,7 @@ export class EventAction extends DeployableTarget<
562
699
  return { ...log, eventName, args };
563
700
  });
564
701
 
565
- return this.isActionEventValid(actionStep, {
566
- logs: decodedLogs,
567
- ...params,
568
- });
702
+ return this.isActionEventValid(actionStep, decodedLogs);
569
703
  }
570
704
  if (actionStep.signatureType === SignatureType.FUNC) {
571
705
  if ('hash' in params && 'chainId' in params) {
@@ -575,7 +709,7 @@ export class EventAction extends DeployableTarget<
575
709
  const transaction = await client.getTransaction({
576
710
  hash: params.hash,
577
711
  });
578
- return this.isActionFunctionValid(actionStep, transaction);
712
+ return this.isActionFunctionValid(actionStep, transaction, params);
579
713
  }
580
714
  }
581
715
  return false;
@@ -588,18 +722,11 @@ export class EventAction extends DeployableTarget<
588
722
  * @public
589
723
  * @async
590
724
  * @param {ActionStep} actionStep - The action step containing the event to validate.
591
- * @param {ValidateActionStepParams} params - Additional parameters for validation, including known events and logs
725
+ * @param {EventLogs} logs - Event logs to validate the given step against
592
726
  * @returns {Promise<boolean>} Resolves to true if the action event is valid, throws if input is invalid, otherwise false.
593
727
  */
594
- public isActionEventValid(
595
- actionStep: ActionStep,
596
- params: ValidateActionStepParams,
597
- ) {
598
- if (!('logs' in params)) {
599
- throw new ValidationLogsMissingError();
600
- }
728
+ public isActionEventValid(actionStep: ActionStep, logs: EventLogs) {
601
729
  const criteria = actionStep.actionParameter;
602
- const logs = params.logs;
603
730
  if (!logs.length) return false;
604
731
  for (let log of logs) {
605
732
  if (this.validateLogAgainstCriteria(criteria, log)) {
@@ -608,25 +735,37 @@ export class EventAction extends DeployableTarget<
608
735
  }
609
736
  return false;
610
737
  }
738
+
611
739
  /**
612
740
  * Validates a single action function with a given criteria against the transaction input.
613
741
  *
614
742
  * @public
615
- * @async
616
743
  * @param {ActionStep} actionStep - The action step containing the function to validate.
617
744
  * @param {Transaction} transaction - The transaction that will be validated against.
618
- * @returns {Promise<boolean>} Resolves to true if the action function is valid, throws if the inputs are invalid, otherwise false.
745
+ * @param {Object} [params] - Optional parameters for validation.
746
+ * @param {AbiItem} [params.abiItem] - The ABI item for the function, if known.
747
+ * @param {Record<Hex, AbiEvent | AbiFunction>} [params.knownSignatures] - A record of known signatures.
748
+ * @returns {boolean} Returns true if the action function is valid, false otherwise.
749
+ * @throws {ValidationAbiMissingError} Throws if the ABI for the function signature is not found.
750
+ * @throws {FunctionDataDecodeError} Throws if there's an error decoding the function data.
619
751
  */
620
752
  public isActionFunctionValid(
621
753
  actionStep: ActionStep,
622
754
  transaction: Transaction,
755
+ params?: Pick<ValidateActionStepParams, 'abiItem' | 'knownSignatures'>,
623
756
  ) {
624
757
  const criteria = actionStep.actionParameter;
625
758
  let signature = actionStep.signature;
626
759
 
627
- const func = (functions.abi as Record<Hex, AbiFunction>)[
628
- signature
629
- ] as AbiFunction;
760
+ let func: AbiFunction;
761
+ if (params?.abiItem) func = params?.abiItem as AbiFunction;
762
+ if (params?.knownSignatures) {
763
+ func = params?.knownSignatures?.[signature] as AbiFunction;
764
+ } else {
765
+ func = (functions.abi as Record<Hex, AbiFunction>)[
766
+ signature
767
+ ] as AbiFunction;
768
+ }
630
769
  if (!func) {
631
770
  throw new ValidationAbiMissingError(signature);
632
771
  }
@@ -776,7 +915,7 @@ export class EventAction extends DeployableTarget<
776
915
  *
777
916
  * @param {Criteria} criteria - The criteria to validate against.
778
917
  * @param {Log} log - The Viem event log.
779
- * @returns {Promise<boolean>} - Returns true if the log passes the criteria, false otherwise.
918
+ * @returns {boolean} - Returns true if the log passes the criteria, false otherwise.
780
919
  */
781
920
  public validateLogAgainstCriteria(
782
921
  criteria: Criteria,
package/src/errors.ts CHANGED
@@ -441,25 +441,6 @@ export class ValidationAbiMissingError extends Error {
441
441
  }
442
442
  }
443
443
 
444
- /**
445
- * Thrown when missing logs for validating action steps.
446
- *
447
- * @export
448
- * @class ValidationLogsMissingError
449
- * @typedef {ValidationLogsMissingError}
450
- * @extends {Error}
451
- */
452
- export class ValidationLogsMissingError extends Error {
453
- /**
454
- * Creates an instance of ValidationLogsMissingError.
455
- *
456
- * @constructor
457
- */
458
- constructor() {
459
- super('Logs are required for validation');
460
- }
461
- }
462
-
463
444
  /**
464
445
  * Function action validation context to help debug other validation errors
465
446
  *
package/src/index.test.ts CHANGED
@@ -40,7 +40,6 @@ const allExports = [
40
40
  "NoEventActionStepsProvidedError",
41
41
  "TooManyEventActionStepsProvidedError",
42
42
  "ValidationAbiMissingError",
43
- "ValidationLogsMissingError",
44
43
  "FieldActionValidationError",
45
44
  "DecodedArgsMalformedError",
46
45
  "FieldValueUndefinedError",