@boostxyz/sdk 0.0.0-alpha.9 → 1.1.0-alpha.23

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 (254) hide show
  1. package/dist/Actions/Action.cjs +1 -1
  2. package/dist/Actions/Action.cjs.map +1 -1
  3. package/dist/Actions/Action.js +2 -2
  4. package/dist/Actions/ContractAction.d.ts +11 -11
  5. package/dist/Actions/ContractAction.d.ts.map +1 -1
  6. package/dist/Actions/ERC721MintAction.d.ts +14 -14
  7. package/dist/Actions/ERC721MintAction.d.ts.map +1 -1
  8. package/dist/Actions/EventAction.cjs +1 -1
  9. package/dist/Actions/EventAction.cjs.map +1 -1
  10. package/dist/Actions/EventAction.d.ts +174 -41
  11. package/dist/Actions/EventAction.d.ts.map +1 -1
  12. package/dist/Actions/EventAction.js +557 -129
  13. package/dist/Actions/EventAction.js.map +1 -1
  14. package/dist/AllowLists/AllowList.cjs +1 -1
  15. package/dist/AllowLists/AllowList.cjs.map +1 -1
  16. package/dist/AllowLists/AllowList.d.ts +6 -4
  17. package/dist/AllowLists/AllowList.d.ts.map +1 -1
  18. package/dist/AllowLists/AllowList.js +45 -23
  19. package/dist/AllowLists/AllowList.js.map +1 -1
  20. package/dist/AllowLists/OpenAllowList.d.ts +423 -0
  21. package/dist/AllowLists/OpenAllowList.d.ts.map +1 -0
  22. package/dist/AllowLists/SimpleAllowList.cjs +1 -1
  23. package/dist/AllowLists/SimpleAllowList.cjs.map +1 -1
  24. package/dist/AllowLists/SimpleAllowList.d.ts +92 -37
  25. package/dist/AllowLists/SimpleAllowList.d.ts.map +1 -1
  26. package/dist/AllowLists/SimpleAllowList.js +60 -75
  27. package/dist/AllowLists/SimpleAllowList.js.map +1 -1
  28. package/dist/AllowLists/SimpleDenyList.cjs +1 -1
  29. package/dist/AllowLists/SimpleDenyList.cjs.map +1 -1
  30. package/dist/AllowLists/SimpleDenyList.d.ts +203 -11
  31. package/dist/AllowLists/SimpleDenyList.d.ts.map +1 -1
  32. package/dist/AllowLists/SimpleDenyList.js +11 -112
  33. package/dist/AllowLists/SimpleDenyList.js.map +1 -1
  34. package/dist/Auth/PassthroughAuth.cjs +1 -1
  35. package/dist/Auth/PassthroughAuth.js +1 -1
  36. package/dist/Boost.cjs +1 -1
  37. package/dist/Boost.cjs.map +1 -1
  38. package/dist/Boost.d.ts +20 -21
  39. package/dist/Boost.d.ts.map +1 -1
  40. package/dist/Boost.js +43 -57
  41. package/dist/Boost.js.map +1 -1
  42. package/dist/BoostCore-Btl5BdAs.cjs +3 -0
  43. package/dist/BoostCore-Btl5BdAs.cjs.map +1 -0
  44. package/dist/BoostCore-CD56zbYX.js +2641 -0
  45. package/dist/BoostCore-CD56zbYX.js.map +1 -0
  46. package/dist/BoostCore.cjs +1 -2
  47. package/dist/BoostCore.cjs.map +1 -1
  48. package/dist/BoostCore.d.ts +749 -78
  49. package/dist/BoostCore.d.ts.map +1 -1
  50. package/dist/BoostCore.js +29 -1150
  51. package/dist/BoostCore.js.map +1 -1
  52. package/dist/BoostRegistry.cjs +1 -1
  53. package/dist/BoostRegistry.cjs.map +1 -1
  54. package/dist/BoostRegistry.d.ts +80 -25
  55. package/dist/BoostRegistry.d.ts.map +1 -1
  56. package/dist/BoostRegistry.js +164 -82
  57. package/dist/BoostRegistry.js.map +1 -1
  58. package/dist/Budgets/Budget.cjs +1 -1
  59. package/dist/Budgets/Budget.cjs.map +1 -1
  60. package/dist/Budgets/Budget.d.ts.map +1 -1
  61. package/dist/Budgets/Budget.js +2 -2
  62. package/dist/Budgets/Budget.js.map +1 -1
  63. package/dist/Budgets/ManagedBudget.cjs +1 -1
  64. package/dist/Budgets/ManagedBudget.cjs.map +1 -1
  65. package/dist/Budgets/ManagedBudget.d.ts +103 -221
  66. package/dist/Budgets/ManagedBudget.d.ts.map +1 -1
  67. package/dist/Budgets/ManagedBudget.js +81 -298
  68. package/dist/Budgets/ManagedBudget.js.map +1 -1
  69. package/dist/Budgets/VestingBudget.d.ts +223 -89
  70. package/dist/Budgets/VestingBudget.d.ts.map +1 -1
  71. package/dist/Deployable/Contract.cjs +1 -1
  72. package/dist/Deployable/Contract.cjs.map +1 -1
  73. package/dist/Deployable/Contract.d.ts +4 -5
  74. package/dist/Deployable/Contract.d.ts.map +1 -1
  75. package/dist/Deployable/Contract.js +5 -7
  76. package/dist/Deployable/Contract.js.map +1 -1
  77. package/dist/Deployable/Deployable.cjs.map +1 -1
  78. package/dist/Deployable/Deployable.d.ts +1 -1
  79. package/dist/Deployable/Deployable.d.ts.map +1 -1
  80. package/dist/Deployable/Deployable.js +3 -5
  81. package/dist/Deployable/Deployable.js.map +1 -1
  82. package/dist/Deployable/DeployableTarget.cjs +1 -1
  83. package/dist/Deployable/DeployableTarget.cjs.map +1 -1
  84. package/dist/Deployable/DeployableTarget.d.ts +13 -13
  85. package/dist/Deployable/DeployableTarget.d.ts.map +1 -1
  86. package/dist/Deployable/DeployableTarget.js +28 -25
  87. package/dist/Deployable/DeployableTarget.js.map +1 -1
  88. package/dist/Deployable/DeployableTargetWithRBAC.cjs +2 -0
  89. package/dist/Deployable/DeployableTargetWithRBAC.cjs.map +1 -0
  90. package/dist/Deployable/DeployableTargetWithRBAC.d.ts +248 -0
  91. package/dist/Deployable/DeployableTargetWithRBAC.d.ts.map +1 -0
  92. package/dist/Deployable/DeployableTargetWithRBAC.js +320 -0
  93. package/dist/Deployable/DeployableTargetWithRBAC.js.map +1 -0
  94. package/dist/Incentive-CcnOIc8L.cjs +2 -0
  95. package/dist/Incentive-CcnOIc8L.cjs.map +1 -0
  96. package/dist/Incentive-rM5nKznp.js +313 -0
  97. package/dist/Incentive-rM5nKznp.js.map +1 -0
  98. package/dist/Incentives/AllowListIncentive.cjs +1 -1
  99. package/dist/Incentives/AllowListIncentive.cjs.map +1 -1
  100. package/dist/Incentives/AllowListIncentive.d.ts +38 -16
  101. package/dist/Incentives/AllowListIncentive.d.ts.map +1 -1
  102. package/dist/Incentives/AllowListIncentive.js +43 -29
  103. package/dist/Incentives/AllowListIncentive.js.map +1 -1
  104. package/dist/Incentives/CGDAIncentive.cjs +1 -1
  105. package/dist/Incentives/CGDAIncentive.cjs.map +1 -1
  106. package/dist/Incentives/CGDAIncentive.d.ts +234 -21
  107. package/dist/Incentives/CGDAIncentive.d.ts.map +1 -1
  108. package/dist/Incentives/CGDAIncentive.js +46 -32
  109. package/dist/Incentives/CGDAIncentive.js.map +1 -1
  110. package/dist/Incentives/ERC1155Incentive.d.ts +224 -37
  111. package/dist/Incentives/ERC1155Incentive.d.ts.map +1 -1
  112. package/dist/Incentives/ERC20Incentive.cjs +1 -1
  113. package/dist/Incentives/ERC20Incentive.cjs.map +1 -1
  114. package/dist/Incentives/ERC20Incentive.d.ts +234 -30
  115. package/dist/Incentives/ERC20Incentive.d.ts.map +1 -1
  116. package/dist/Incentives/ERC20Incentive.js +62 -46
  117. package/dist/Incentives/ERC20Incentive.js.map +1 -1
  118. package/dist/{Budgets/SimpleBudget.d.ts → Incentives/ERC20VariableCriteriaIncentive.d.ts} +333 -438
  119. package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts.map +1 -0
  120. package/dist/Incentives/ERC20VariableIncentive.d.ts +231 -29
  121. package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -1
  122. package/dist/Incentives/Incentive.cjs +1 -1
  123. package/dist/Incentives/Incentive.cjs.map +1 -1
  124. package/dist/Incentives/Incentive.d.ts +4 -4
  125. package/dist/Incentives/Incentive.d.ts.map +1 -1
  126. package/dist/Incentives/Incentive.js +16 -296
  127. package/dist/Incentives/Incentive.js.map +1 -1
  128. package/dist/Incentives/PointsIncentive.cjs +1 -1
  129. package/dist/Incentives/PointsIncentive.cjs.map +1 -1
  130. package/dist/Incentives/PointsIncentive.d.ts +40 -18
  131. package/dist/Incentives/PointsIncentive.d.ts.map +1 -1
  132. package/dist/Incentives/PointsIncentive.js +38 -24
  133. package/dist/Incentives/PointsIncentive.js.map +1 -1
  134. package/dist/SimpleDenyList-BDXpY74P.js +133 -0
  135. package/dist/SimpleDenyList-BDXpY74P.js.map +1 -0
  136. package/dist/SimpleDenyList-DNj5qDWM.cjs +2 -0
  137. package/dist/SimpleDenyList-DNj5qDWM.cjs.map +1 -0
  138. package/dist/Validators/SignerValidator.cjs +1 -1
  139. package/dist/Validators/SignerValidator.cjs.map +1 -1
  140. package/dist/Validators/SignerValidator.d.ts +16 -16
  141. package/dist/Validators/SignerValidator.d.ts.map +1 -1
  142. package/dist/Validators/SignerValidator.js +32 -28
  143. package/dist/Validators/SignerValidator.js.map +1 -1
  144. package/dist/Validators/Validator.cjs +1 -1
  145. package/dist/Validators/Validator.cjs.map +1 -1
  146. package/dist/Validators/Validator.d.ts +1 -1
  147. package/dist/Validators/Validator.js +2 -2
  148. package/dist/Validators/Validator.js.map +1 -1
  149. package/dist/claiming.cjs.map +1 -1
  150. package/dist/claiming.d.ts +1 -1
  151. package/dist/claiming.js.map +1 -1
  152. package/dist/componentInterfaces-BBCFkrZv.js +14 -0
  153. package/dist/componentInterfaces-BBCFkrZv.js.map +1 -0
  154. package/dist/componentInterfaces-DRI_dQ-P.cjs +2 -0
  155. package/dist/componentInterfaces-DRI_dQ-P.cjs.map +1 -0
  156. package/dist/deployments-DF_6-7hH.cjs +2 -0
  157. package/dist/deployments-DF_6-7hH.cjs.map +1 -0
  158. package/dist/deployments-fJsWblwS.js +56 -0
  159. package/dist/deployments-fJsWblwS.js.map +1 -0
  160. package/dist/deployments.json +58 -0
  161. package/dist/errors.cjs +1 -1
  162. package/dist/errors.cjs.map +1 -1
  163. package/dist/errors.d.ts +256 -20
  164. package/dist/errors.d.ts.map +1 -1
  165. package/dist/errors.js +183 -26
  166. package/dist/errors.js.map +1 -1
  167. package/dist/{generated-57_Kffpz.js → generated-CsNyWPKA.js} +3843 -2084
  168. package/dist/generated-CsNyWPKA.js.map +1 -0
  169. package/dist/generated-DHerxf1y.cjs +3 -0
  170. package/dist/generated-DHerxf1y.cjs.map +1 -0
  171. package/dist/index.cjs +1 -1
  172. package/dist/index.d.ts +5 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +142 -108
  175. package/dist/index.js.map +1 -1
  176. package/dist/transfers.cjs.map +1 -1
  177. package/dist/transfers.d.ts +1 -1
  178. package/dist/transfers.js.map +1 -1
  179. package/dist/utils.cjs +1 -1
  180. package/dist/utils.cjs.map +1 -1
  181. package/dist/utils.d.ts +26 -12
  182. package/dist/utils.d.ts.map +1 -1
  183. package/dist/utils.js +38 -23
  184. package/dist/utils.js.map +1 -1
  185. package/package.json +20 -10
  186. package/src/Actions/Action.test.ts +14 -13
  187. package/src/Actions/ContractAction.test.ts +10 -10
  188. package/src/Actions/ContractAction.ts +11 -12
  189. package/src/Actions/ERC721MintAction.test.ts +6 -6
  190. package/src/Actions/ERC721MintAction.ts +14 -15
  191. package/src/Actions/EventAction.test.ts +735 -109
  192. package/src/Actions/EventAction.ts +527 -88
  193. package/src/AllowLists/AllowList.test.ts +7 -7
  194. package/src/AllowLists/AllowList.ts +5 -3
  195. package/src/AllowLists/OpenAllowList.test.ts +40 -0
  196. package/src/AllowLists/OpenAllowList.ts +45 -0
  197. package/src/AllowLists/SimpleAllowList.test.ts +4 -4
  198. package/src/AllowLists/SimpleAllowList.ts +40 -61
  199. package/src/AllowLists/SimpleDenyList.test.ts +4 -4
  200. package/src/AllowLists/SimpleDenyList.ts +41 -17
  201. package/src/Auth/PassthroughAuth.test.ts +1 -1
  202. package/src/Boost.ts +21 -24
  203. package/src/BoostCore.test.ts +361 -306
  204. package/src/BoostCore.ts +403 -220
  205. package/src/BoostRegistry.test.ts +53 -0
  206. package/src/BoostRegistry.ts +161 -40
  207. package/src/Budgets/Budget.test.ts +2 -2
  208. package/src/Budgets/Budget.ts +1 -2
  209. package/src/Budgets/ManagedBudget.test.ts +106 -19
  210. package/src/Budgets/ManagedBudget.ts +49 -321
  211. package/src/Budgets/VestingBudget.test.ts +7 -7
  212. package/src/Budgets/VestingBudget.ts +36 -106
  213. package/src/Deployable/Contract.ts +4 -5
  214. package/src/Deployable/Deployable.ts +1 -1
  215. package/src/Deployable/DeployableTarget.ts +30 -19
  216. package/src/Deployable/DeployableTargetWithRBAC.test.ts +103 -0
  217. package/src/Deployable/DeployableTargetWithRBAC.ts +447 -0
  218. package/src/Incentives/AllowListIncentive.test.ts +12 -12
  219. package/src/Incentives/AllowListIncentive.ts +30 -15
  220. package/src/Incentives/CGDAIncentive.test.ts +9 -6
  221. package/src/Incentives/CGDAIncentive.ts +39 -18
  222. package/src/Incentives/ERC1155Incentive.test.ts +3 -3
  223. package/src/Incentives/ERC1155Incentive.ts +30 -29
  224. package/src/Incentives/ERC20Incentive.test.ts +9 -6
  225. package/src/Incentives/ERC20Incentive.ts +54 -27
  226. package/src/Incentives/ERC20VariableCriteriaIncentive.test.ts +184 -0
  227. package/src/Incentives/ERC20VariableCriteriaIncentive.ts +325 -0
  228. package/src/Incentives/ERC20VariableIncentive.test.ts +8 -11
  229. package/src/Incentives/ERC20VariableIncentive.ts +50 -26
  230. package/src/Incentives/Incentive.test.ts +4 -1
  231. package/src/Incentives/Incentive.ts +7 -6
  232. package/src/Incentives/PointsIncentive.test.ts +24 -25
  233. package/src/Incentives/PointsIncentive.ts +32 -17
  234. package/src/Validators/SignerValidator.test.ts +6 -6
  235. package/src/Validators/SignerValidator.ts +20 -17
  236. package/src/Validators/Validator.test.ts +2 -2
  237. package/src/Validators/Validator.ts +1 -1
  238. package/src/claiming.ts +1 -1
  239. package/src/errors.ts +345 -21
  240. package/src/index.test.ts +118 -36
  241. package/src/index.ts +5 -0
  242. package/src/transfers.ts +1 -1
  243. package/src/utils.test.ts +2 -2
  244. package/src/utils.ts +61 -12
  245. package/dist/Budgets/SimpleBudget.d.ts.map +0 -1
  246. package/dist/componentInterfaces-CKCBwG16.cjs +0 -2
  247. package/dist/componentInterfaces-CKCBwG16.cjs.map +0 -1
  248. package/dist/componentInterfaces-DYkaxBda.js +0 -13
  249. package/dist/componentInterfaces-DYkaxBda.js.map +0 -1
  250. package/dist/generated-57_Kffpz.js.map +0 -1
  251. package/dist/generated-wKBNvm48.cjs +0 -3
  252. package/dist/generated-wKBNvm48.cjs.map +0 -1
  253. package/src/Budgets/SimpleBudget.test.ts +0 -152
  254. package/src/Budgets/SimpleBudget.ts +0 -564
@@ -1,27 +1,52 @@
1
- import { selectors as eventSelectors } from '@boostxyz/signatures/events';
2
- import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
3
- import { type Hex, type Log, isAddress } from 'viem';
1
+ import { selectors as eventSelectors } from "@boostxyz/signatures/events";
2
+ import { selectors as funcSelectors } from "@boostxyz/signatures/functions";
3
+ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
4
+ import {
5
+ AbiEvent,
6
+ AbiFunction,
7
+ type Address,
8
+ type Hex,
9
+ isAddress,
10
+ parseEther,
11
+ toHex,
12
+ zeroAddress,
13
+ zeroHash,
14
+ } from 'viem';
4
15
  import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
5
- import type { MockERC721 } from '../../test/MockERC721';
6
- import { accounts } from '../../test/accounts';
16
+ import type { MockERC20 } from '@boostxyz/test/MockERC20';
17
+ import type { MockERC721 } from '@boostxyz/test/MockERC721';
18
+ import { accounts } from '@boostxyz/test/accounts';
7
19
  import {
8
20
  type Fixtures,
21
+ type StringEmitterFixtures,
9
22
  defaultOptions,
10
23
  deployFixtures,
24
+ fundErc20,
25
+ deployStringEmitterMock,
11
26
  fundErc721,
12
- } from '../../test/helpers';
27
+ } from '@boostxyz/test/helpers';
13
28
  import {
14
29
  EventAction,
30
+ type EventLogs,
15
31
  type EventActionPayloadSimple,
16
32
  FilterType,
17
33
  PrimitiveType,
18
34
  SignatureType,
19
- } from './EventAction';
35
+ Criteria,
36
+ anyActionParameter,
37
+ } from "./EventAction";
38
+ import { allKnownSignatures } from "@boostxyz/test/allKnownSignatures";
20
39
 
21
- let fixtures: Fixtures, erc721: MockERC721;
40
+ let fixtures: Fixtures,
41
+ erc721: MockERC721,
42
+ erc20: MockERC20,
43
+ stringEmitterFixtures: StringEmitterFixtures;
44
+ let chainId: number;
22
45
 
23
46
  beforeAll(async () => {
24
- fixtures = await loadFixture(deployFixtures);
47
+ fixtures = await loadFixture(deployFixtures(defaultOptions));
48
+ stringEmitterFixtures = await loadFixture(deployStringEmitterMock);
49
+ chainId = defaultOptions.config.chains[0].id;
25
50
  });
26
51
 
27
52
  function basicErc721TransferAction(
@@ -30,21 +55,25 @@ function basicErc721TransferAction(
30
55
  return {
31
56
  actionClaimant: {
32
57
  signatureType: SignatureType.EVENT,
33
- signature: eventSelectors['Transfer(address,address,uint256)'] as Hex,
34
- fieldIndex: 2,
58
+ signature: eventSelectors[
59
+ "Transfer(address indexed,address indexed,uint256 indexed)"
60
+ ] as Hex,
61
+ fieldIndex: 1,
35
62
  targetContract: erc721.assertValidAddress(),
36
- chainid: defaultOptions.config.chains[0].id,
63
+ chainid: chainId,
37
64
  },
38
65
  actionSteps: [
39
66
  {
40
- signature: eventSelectors['Transfer(address,address,uint256)'] as Hex,
67
+ signature: eventSelectors[
68
+ "Transfer(address indexed,address indexed,uint256 indexed)"
69
+ ] as Hex,
41
70
  signatureType: SignatureType.EVENT,
42
71
  targetContract: erc721.assertValidAddress(),
43
- chainid: defaultOptions.config.chains[0].id,
72
+ chainid: chainId,
44
73
  actionParameter: {
45
74
  filterType: FilterType.EQUAL,
46
75
  fieldType: PrimitiveType.ADDRESS,
47
- fieldIndex: 2,
76
+ fieldIndex: 1,
48
77
  filterData: accounts[1].account,
49
78
  },
50
79
  },
@@ -52,157 +81,754 @@ function basicErc721TransferAction(
52
81
  };
53
82
  }
54
83
 
55
- /*
84
+ function basicErc721TransferActionWithEmptyActionParameter(erc721: MockERC721) {
85
+ const eventActionPayload = basicErc721TransferAction(erc721)
86
+ if (eventActionPayload.actionSteps[0]?.actionParameter) {
87
+ eventActionPayload.actionSteps[0].actionParameter = anyActionParameter()
88
+ }
89
+ return eventActionPayload
90
+ }
91
+
92
+ function cloneEventAction(fixtures: Fixtures, erc721: MockERC721, eventActionPayload = basicErc721TransferAction(erc721)) {
93
+ return function cloneEventAction() {
94
+ return fixtures.registry.initialize(
95
+ crypto.randomUUID(),
96
+ fixtures.core.EventAction(eventActionPayload),
97
+ );
98
+ };
99
+ }
100
+
56
101
  function basicErc721MintFuncAction(
57
102
  erc721: MockERC721,
58
103
  ): EventActionPayloadSimple {
59
104
  return {
60
105
  actionClaimant: {
61
106
  signatureType: SignatureType.FUNC,
62
- signature: funcSelectors['mint(address)'] as Hex,
107
+ signature: funcSelectors["mint(address)"] as Hex,
63
108
  fieldIndex: 0,
64
109
  targetContract: erc721.assertValidAddress(),
110
+ chainid: chainId,
65
111
  },
66
112
  actionSteps: [
67
113
  {
68
- signature: funcSelectors['mint(address)'] as Hex,
114
+ signature: funcSelectors["mint(address)"] as Hex,
69
115
  signatureType: SignatureType.FUNC,
70
116
  actionType: 0,
71
117
  targetContract: erc721.assertValidAddress(),
118
+ chainid: chainId,
72
119
  actionParameter: {
73
120
  filterType: FilterType.EQUAL,
74
121
  fieldType: PrimitiveType.ADDRESS,
75
- fieldIndex: 2,
122
+ fieldIndex: 0,
76
123
  filterData: accounts[1].account,
77
124
  },
78
125
  },
79
126
  ],
80
127
  };
81
128
  }
82
- */
83
129
 
84
- function cloneEventAction(fixtures: Fixtures, erc721: MockERC721) {
85
- return function cloneEventAction() {
130
+ function basicErc721MintFuncActionWithEmptyActionParameter(erc721: MockERC721) {
131
+ const eventActionPayload = basicErc721MintFuncAction(erc721)
132
+ if (eventActionPayload.actionSteps[0]?.actionParameter) {
133
+ eventActionPayload.actionSteps[0].actionParameter = anyActionParameter()
134
+ }
135
+ return eventActionPayload
136
+ }
137
+
138
+ function basicErc20MintFuncAction(erc20: MockERC20): EventActionPayloadSimple {
139
+ return {
140
+ actionClaimant: {
141
+ signatureType: SignatureType.FUNC,
142
+ signature: funcSelectors["mint(address to, uint256 amount)"] as Hex,
143
+ fieldIndex: 0,
144
+ targetContract: erc20.assertValidAddress(),
145
+ chainid: chainId,
146
+ },
147
+ actionSteps: [
148
+ {
149
+ signature: funcSelectors["mint(address to, uint256 amount)"] as Hex,
150
+ signatureType: SignatureType.FUNC,
151
+ actionType: 0,
152
+ targetContract: erc20.assertValidAddress(),
153
+ chainid: chainId,
154
+ actionParameter: {
155
+ filterType: FilterType.EQUAL,
156
+ fieldType: PrimitiveType.ADDRESS,
157
+ fieldIndex: 0,
158
+ filterData: accounts[1].account,
159
+ },
160
+ },
161
+ ],
162
+ };
163
+ }
164
+
165
+ function indexedStringErc721TransferAction(
166
+ filterType: FilterType,
167
+ data: Hex,
168
+ stringEmitterAddress: Address,
169
+ erc721: MockERC721,
170
+ ): EventActionPayloadSimple {
171
+ return {
172
+ actionClaimant: {
173
+ signatureType: SignatureType.EVENT,
174
+ signature: eventSelectors[
175
+ "Transfer(address indexed,address indexed,uint256 indexed)"
176
+ ] as Hex,
177
+ fieldIndex: 1,
178
+ targetContract: erc721.assertValidAddress(),
179
+ chainid: chainId,
180
+ },
181
+ actionSteps: [
182
+ {
183
+ signature: eventSelectors[
184
+ "InfoIndexed(address indexed,string indexed)"
185
+ ] as Hex,
186
+ signatureType: SignatureType.EVENT,
187
+ actionType: 0,
188
+ targetContract: stringEmitterAddress,
189
+ chainid: chainId,
190
+ actionParameter: {
191
+ filterType,
192
+ fieldType: PrimitiveType.STRING,
193
+ fieldIndex: 1,
194
+ filterData: data,
195
+ },
196
+ },
197
+ ],
198
+ };
199
+ }
200
+
201
+ function stringErc721TransferAction(
202
+ filterType: FilterType,
203
+ data: Hex,
204
+ stringEmitterAddress: Address,
205
+ erc721: MockERC721,
206
+ ): EventActionPayloadSimple {
207
+ return {
208
+ actionClaimant: {
209
+ signatureType: SignatureType.EVENT,
210
+ signature: eventSelectors[
211
+ "Transfer(address indexed,address indexed,uint256 indexed)"
212
+ ] as Hex,
213
+ fieldIndex: 1,
214
+ targetContract: erc721.assertValidAddress(),
215
+ chainid: chainId,
216
+ },
217
+ actionSteps: [
218
+ {
219
+ signature: eventSelectors["Info(address,string)"] as Hex,
220
+ signatureType: SignatureType.EVENT,
221
+ actionType: 0,
222
+ targetContract: stringEmitterAddress,
223
+ chainid: chainId,
224
+ actionParameter: {
225
+ filterType,
226
+ fieldType: PrimitiveType.STRING,
227
+ fieldIndex: 1,
228
+ filterData: data,
229
+ },
230
+ },
231
+ ],
232
+ };
233
+ }
234
+
235
+ function cloneFunctionAction20(fixtures: Fixtures, erc20: MockERC20) {
236
+ return function cloneFunctionAction20() {
86
237
  return fixtures.registry.clone(
87
238
  crypto.randomUUID(),
88
239
  new fixtures.bases.EventAction(
89
240
  defaultOptions,
90
- basicErc721TransferAction(erc721),
241
+ basicErc20MintFuncAction(erc20),
91
242
  ),
92
243
  );
93
244
  };
94
245
  }
95
246
 
96
- describe('EventAction', () => {
247
+ function cloneFunctionAction(fixtures: Fixtures, erc721: MockERC721, eventActionPayload = basicErc721MintFuncAction(erc721)) {
248
+ return function cloneFunctionAction() {
249
+ return fixtures.registry.clone(
250
+ crypto.randomUUID(),
251
+ new fixtures.bases.EventAction(
252
+ defaultOptions,
253
+ eventActionPayload
254
+ ),
255
+ );
256
+ };
257
+ }
258
+
259
+ function cloneStringEventAction(
260
+ fixtures: Fixtures,
261
+ actionParams: EventActionPayloadSimple,
262
+ ) {
263
+ return function loadFixtureCallback() {
264
+ return fixtures.registry.clone(
265
+ crypto.randomUUID(),
266
+ new fixtures.bases.EventAction(defaultOptions, actionParams),
267
+ );
268
+ };
269
+ }
270
+
271
+ function createMockCriteria(
272
+ filterType: FilterType,
273
+ fieldType: PrimitiveType,
274
+ filterData: Hex,
275
+ fieldIndex: number = 0
276
+ ): Criteria {
277
+ return {
278
+ filterType,
279
+ fieldType,
280
+ filterData,
281
+ fieldIndex,
282
+ };
283
+ }
284
+
285
+ describe("EventAction Event Selector", () => {
97
286
  beforeEach(async () => {
98
287
  erc721 = await loadFixture(fundErc721(defaultOptions));
99
288
  });
100
289
 
101
- test('can successfully be deployed', async () => {
290
+ describe("basic transfer event", () => {
291
+ test("can successfully be deployed", async () => {
292
+ const action = new EventAction(
293
+ defaultOptions,
294
+ basicErc721TransferAction(erc721),
295
+ );
296
+ await action.deploy();
297
+ expect(isAddress(action.assertValidAddress())).toBe(true);
298
+ });
299
+
300
+ test("can get an action step", async () => {
301
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
302
+ const step = await action.getActionStep(0);
303
+ if (!step)
304
+ throw new Error("there should be an action step at this index");
305
+ step.targetContract = step.targetContract.toUpperCase() as Hex;
306
+ step.actionParameter.filterData =
307
+ step.actionParameter.filterData.toUpperCase() as Hex;
308
+ expect(step).toMatchObject({
309
+ signature: eventSelectors[
310
+ "Transfer(address indexed,address indexed,uint256 indexed)"
311
+ ] as Hex,
312
+ signatureType: SignatureType.EVENT,
313
+ actionType: 0,
314
+ targetContract: erc721.assertValidAddress().toUpperCase(),
315
+ actionParameter: {
316
+ filterType: FilterType.EQUAL,
317
+ fieldType: PrimitiveType.ADDRESS,
318
+ fieldIndex: 1,
319
+ filterData: accounts[1].account.toUpperCase(),
320
+ },
321
+ });
322
+ });
323
+
324
+ test("can get all action steps", async () => {
325
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
326
+ const steps = await action.getActionSteps();
327
+ expect(steps.length).toBe(1);
328
+ const step = steps[0]!;
329
+ step.targetContract = step.targetContract.toUpperCase() as Hex;
330
+ step.actionParameter.filterData =
331
+ step.actionParameter.filterData.toUpperCase() as Hex;
332
+ expect(step).toMatchObject({
333
+ signature: eventSelectors[
334
+ "Transfer(address indexed,address indexed,uint256 indexed)"
335
+ ] as Hex,
336
+ signatureType: SignatureType.EVENT,
337
+ actionType: 0,
338
+ targetContract: erc721.assertValidAddress().toUpperCase(),
339
+ actionParameter: {
340
+ filterType: FilterType.EQUAL,
341
+ fieldType: PrimitiveType.ADDRESS,
342
+ fieldIndex: 1,
343
+ filterData: accounts[1].account.toUpperCase(),
344
+ },
345
+ });
346
+ });
347
+
348
+ test("can get the total number of action steps", async () => {
349
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
350
+ const count = await action.getActionStepsCount();
351
+ expect(count).toBe(1);
352
+ });
353
+
354
+ test("can get the action claimant", async () => {
355
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
356
+ const claimant = await action.getActionClaimant();
357
+ claimant.targetContract = claimant.targetContract.toUpperCase() as Hex;
358
+ expect(claimant).toMatchObject({
359
+ signatureType: SignatureType.EVENT,
360
+ signature: eventSelectors[
361
+ "Transfer(address indexed,address indexed,uint256 indexed)"
362
+ ] as Hex,
363
+ fieldIndex: 1,
364
+ });
365
+ });
366
+
367
+ test("can get all action steps", async () => {
368
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
369
+ const steps = await action.getActionSteps();
370
+ expect(steps.length).toBe(1);
371
+ const step = steps[0]!;
372
+ step.targetContract = step.targetContract.toUpperCase() as Hex;
373
+ step.actionParameter.filterData =
374
+ step.actionParameter.filterData.toUpperCase() as Hex;
375
+ expect(step).toMatchObject({
376
+ signature: eventSelectors[
377
+ "Transfer(address indexed,address indexed,uint256 indexed)"
378
+ ] as Hex,
379
+ signatureType: SignatureType.EVENT,
380
+ actionType: 0,
381
+ targetContract: erc721.assertValidAddress().toUpperCase(),
382
+ actionParameter: {
383
+ filterType: FilterType.EQUAL,
384
+ fieldType: PrimitiveType.ADDRESS,
385
+ fieldIndex: 1,
386
+ filterData: accounts[1].account.toUpperCase(),
387
+ },
388
+ });
389
+ });
390
+
391
+ test("can get the total number of action steps", async () => {
392
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
393
+ const count = await action.getActionStepsCount();
394
+ expect(count).toBe(1);
395
+ });
396
+
397
+ test("can get the action claimant", async () => {
398
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
399
+ const claimant = await action.getActionClaimant();
400
+ claimant.targetContract = claimant.targetContract.toUpperCase() as Hex;
401
+ expect(claimant).toMatchObject({
402
+ signatureType: SignatureType.EVENT,
403
+ signature: eventSelectors[
404
+ "Transfer(address indexed,address indexed,uint256 indexed)"
405
+ ] as Hex,
406
+ fieldIndex: 1,
407
+ targetContract: erc721.assertValidAddress().toUpperCase(),
408
+ });
409
+ });
410
+
411
+ test("with a correct log, validates", async () => {
412
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
413
+ const recipient = accounts[1].account;
414
+ await erc721.approve(recipient, 1n);
415
+ const { hash } = await erc721.transferFromRaw(defaultOptions.account.address, recipient, 1n);
416
+ expect(await action.validateActionSteps({ hash, chainId, knownSignatures: allKnownSignatures })).toBe(true);
417
+ });
418
+
419
+ test("can supply your own logs to validate against", async () => {
420
+ const hash = "0xff0e6ab0c4961ec14b7b40afec83ed7d7a77582683512a262e641d21f82efea5"
421
+ const logs: EventLogs = [
422
+ {
423
+ eventName: "Transfer",
424
+ args: [
425
+ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
426
+ "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
427
+ 1n,
428
+ ],
429
+ address: erc721.assertValidAddress(),
430
+ blockHash:
431
+ "0xbf602f988260519805d032be46d6ff97fbefbee6924b21097074d6d0bc34eced",
432
+ blockNumber: 1203n,
433
+ data: "0x",
434
+ logIndex: 0,
435
+ removed: false,
436
+ topics: [
437
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
438
+ "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266",
439
+ "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8",
440
+ "0x0000000000000000000000000000000000000000000000000000000000000001",
441
+ ],
442
+ transactionHash:
443
+ "0xff0e6ab0c4961ec14b7b40afec83ed7d7a77582683512a262e641d21f82efea5",
444
+ transactionIndex: 0,
445
+ },
446
+ ];
447
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
448
+ expect(await action.validateActionSteps({ hash, chainId, logs, knownSignatures: allKnownSignatures })).toBe(true);
449
+ });
450
+
451
+ describe("string event actions", () => {
452
+ test("cannot parse and validate contains for an emitted string event with an indexed param", async () => {
453
+ const action = await loadFixture(
454
+ cloneStringEventAction(
455
+ fixtures,
456
+ indexedStringErc721TransferAction(
457
+ FilterType.CONTAINS,
458
+ toHex("ello"),
459
+ stringEmitterFixtures.address,
460
+ erc721,
461
+ ),
462
+ ),
463
+ );
464
+
465
+ const hash = await stringEmitterFixtures.emitIndexedString("Hello world");
466
+ await expect(() => action.validateActionSteps({ hash, chainId, knownSignatures: allKnownSignatures })).rejects.toThrowError(
467
+ /Parameter is not transparently stored onchain/,
468
+ );
469
+ });
470
+ test("can parse and validate contains for an emitted string event", async () => {
471
+ const action = await loadFixture(
472
+ cloneStringEventAction(
473
+ fixtures,
474
+ stringErc721TransferAction(
475
+ FilterType.CONTAINS,
476
+ toHex("ello"),
477
+ stringEmitterFixtures.address,
478
+ erc721,
479
+ ),
480
+ ),
481
+ );
482
+ const hash = await stringEmitterFixtures.emitString("Hello world");
483
+ expect(await action.validateActionSteps({ hash, chainId, knownSignatures: allKnownSignatures })).toBe(true);
484
+ });
485
+ test("can parse and validate regex for an emitted string event", async () => {
486
+ const action = await loadFixture(
487
+ cloneStringEventAction(
488
+ fixtures,
489
+ stringErc721TransferAction(
490
+ FilterType.REGEX,
491
+ toHex("[hH]ello"),
492
+ stringEmitterFixtures.address,
493
+ erc721,
494
+ ),
495
+ ),
496
+ );
497
+
498
+ const hash = await stringEmitterFixtures.emitString("Hello world");
499
+ expect(await action.validateActionSteps({ hash, chainId, knownSignatures: allKnownSignatures })).toBe(true);
500
+ });
501
+ });
502
+
503
+ test("can derive the claimant from an event action", async () => {
504
+ const action = await loadFixture(cloneEventAction(fixtures, erc721));
505
+ const recipient = accounts[1].account;
506
+ await erc721.approve(recipient, 1n);
507
+ const { hash } = await erc721.transferFromRaw(defaultOptions.account.address, recipient, 1n);
508
+ expect(
509
+ await action.deriveActionClaimantFromTransaction(await action.getActionClaimant(), {
510
+ hash,
511
+ chainId,
512
+ knownSignatures: allKnownSignatures
513
+ }),
514
+ ).toBe(recipient);
515
+ });
516
+
517
+ test("can derive the claimant from a function action", async () => {
518
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
519
+ const recipient = accounts[1].account;
520
+ const { hash } = await erc721.mintRaw(recipient, {
521
+ value: parseEther(".1"),
522
+ });
523
+
524
+ expect(
525
+ await action.deriveActionClaimantFromTransaction(await action.getActionClaimant(), {
526
+ hash,
527
+ chainId,
528
+ knownSignatures: allKnownSignatures
529
+ }),
530
+ ).toBe(recipient);
531
+ });
532
+
533
+ test('validates empty actionParameter', async () => {
534
+ const action = await loadFixture(cloneEventAction(fixtures, erc721, basicErc721TransferActionWithEmptyActionParameter(erc721)))
535
+ const recipient = accounts[1].account;
536
+ await erc721.approve(recipient, 1n);
537
+ const { hash } = await erc721.transferFromRaw(defaultOptions.account.address, recipient, 1n);
538
+ expect(await action.validateActionSteps({ hash, chainId, knownSignatures: allKnownSignatures })).toBe(true);
539
+ })
540
+ });
541
+ });
542
+
543
+ describe("validateFieldAgainstCriteria unit tests", () => {
544
+ let action: EventAction
545
+ beforeAll(async () => {
546
+ action = await loadFixture(cloneEventAction(fixtures, erc721));
547
+ });
548
+ const mockAddress = '0x1234567890abcdef1234567890abcdef12345678';
549
+ const mockInput = { decodedArgs: ['not used'] };
550
+
551
+ test('should return true for EQUAL filter type with ADDRESS field type', () => {
552
+ const mockCriteria = createMockCriteria(FilterType.EQUAL, PrimitiveType.ADDRESS, mockAddress);
553
+ const result = action.validateFieldAgainstCriteria(mockCriteria, mockAddress, mockInput);
554
+ expect(result).toBe(true);
555
+ });
556
+
557
+ test('should return true for EQUAL filter type with UINT field type', () => {
558
+ const mockCriteria = createMockCriteria(FilterType.EQUAL, PrimitiveType.UINT, '0xc8');
559
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 200n, mockInput);
560
+ expect(result).toBe(true);
561
+ });
562
+ test('should return true for EQUAL filter type with STRING field type when values match', () => {
563
+ // Decoded value: 'hello'
564
+ const mockCriteria = createMockCriteria(FilterType.EQUAL, PrimitiveType.STRING, '0x68656c6c6f');
565
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 'hello', mockInput);
566
+ expect(result).toBe(true);
567
+ });
568
+
569
+ test('should return false for EQUAL filter type with STRING field type when values do not match', () => {
570
+ // Decoded value: 'hello'
571
+ const mockCriteria = createMockCriteria(FilterType.EQUAL, PrimitiveType.STRING, '0x68656c6c6f');
572
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 'world', mockInput);
573
+ expect(result).toBe(false);
574
+ });
575
+
576
+ test('should return true for EQUAL filter type with BYTES field type when values match', () => {
577
+ // Decoded value: '0x68656c6c6f' (hex for 'hello')
578
+ const mockCriteria = createMockCriteria(FilterType.EQUAL, PrimitiveType.BYTES, '0x68656c6c6f');
579
+ const result = action.validateFieldAgainstCriteria(mockCriteria, '0x68656c6c6f', mockInput);
580
+ expect(result).toBe(true);
581
+ });
582
+
583
+ test('should return false for EQUAL filter type with BYTES field type when values do not match', () => {
584
+ // Decoded value: '0x68656c6c6f' (hex for 'hello')
585
+ const mockCriteria = createMockCriteria(FilterType.EQUAL, PrimitiveType.BYTES, '0x68656c6c6f');
586
+ const result = action.validateFieldAgainstCriteria(mockCriteria, '0x776f726c64', mockInput); // hex for 'world'
587
+ expect(result).toBe(false);
588
+ });
589
+
590
+ test('should return false for NOT_EQUAL filter type with ADDRESS field type', () => {
591
+ const mockCriteria = createMockCriteria(FilterType.NOT_EQUAL, PrimitiveType.ADDRESS, mockAddress);
592
+ const result = action.validateFieldAgainstCriteria(mockCriteria, zeroAddress, mockInput);
593
+ expect(result).toBe(true);
594
+ });
595
+
596
+ test('should return true for NOT_EQUAL filter type with UINT field type', () => {
597
+ const mockCriteria = createMockCriteria(FilterType.NOT_EQUAL, PrimitiveType.UINT, '0xc9');
598
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 200n, mockInput);
599
+ expect(result).toBe(true);
600
+ });
601
+
602
+ test('should throw InvalidNumericalCriteriaError for GREATER_THAN filter type with non-uint field type', () => {
603
+ const mockCriteria = createMockCriteria(FilterType.GREATER_THAN, PrimitiveType.STRING, '0x100');
604
+ expect(() => action.validateFieldAgainstCriteria(mockCriteria, '200', mockInput)).toThrow('non-numerical criteria');
605
+ });
606
+
607
+ test('should return true for GREATER_THAN filter type with UINT field type', () => {
608
+ const mockCriteria = createMockCriteria(FilterType.GREATER_THAN, PrimitiveType.UINT, '0x64');
609
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 200n, mockInput);
610
+ expect(result).toBe(true);
611
+ });
612
+
613
+ test('should return true for CONTAINS filter type with STRING field type', () => {
614
+ // Decoded value: 'hello'
615
+ const mockCriteria = createMockCriteria(FilterType.CONTAINS, PrimitiveType.STRING, '0x68656c6c6f');
616
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 'hello world', mockInput);
617
+ expect(result).toBe(true);
618
+ });
619
+
620
+ test('should return true for CONTAINS filter type with BYTES field type', () => {
621
+ const mockCriteria = createMockCriteria(FilterType.CONTAINS, PrimitiveType.BYTES, '0xbeef');
622
+ const result = action.validateFieldAgainstCriteria(mockCriteria, '0xdeadbeef', mockInput);
623
+ expect(result).toBe(true);
624
+ });
625
+
626
+ test('should throw FieldValueNotComparableError for CONTAINS filter type with non-string/bytes field type', () => {
627
+ // Decoded value: 123
628
+ const mockCriteria = createMockCriteria(FilterType.CONTAINS, PrimitiveType.UINT, '0x7b');
629
+ expect(() => action.validateFieldAgainstCriteria(mockCriteria, 123n, mockInput)).toThrow(/only .* bytes or string/);
630
+ });
631
+
632
+ test('should throw UnrecognizedFilterTypeError for unrecognized filter type', () => {
633
+ const mockCriteria = createMockCriteria(6 as FilterType, PrimitiveType.STRING, '0x74657374'); // Decoded value: 'test'
634
+ expect(() => action.validateFieldAgainstCriteria(mockCriteria, 'test', mockInput)).toThrow('Invalid FilterType');
635
+ });
636
+
637
+ test('should return true for LESS_THAN filter type with UINT field type', () => {
638
+ // Decoded value: 200
639
+ const mockCriteria = createMockCriteria(FilterType.LESS_THAN, PrimitiveType.UINT, '0xc8');
640
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 100n, mockInput);
641
+ expect(result).toBe(true);
642
+ });
643
+
644
+ test('should return false for LESS_THAN filter type with UINT field type when value is greater', () => {
645
+ // Decoded value: 100
646
+ const mockCriteria = createMockCriteria(FilterType.LESS_THAN, PrimitiveType.UINT, '0x64');
647
+ const result = action.validateFieldAgainstCriteria(mockCriteria, 200n, mockInput);
648
+ expect(result).toBe(false);
649
+ });
650
+
651
+ test('should throw InvalidNumericalCriteriaError for LESS_THAN filter type with non-uint field type', () => {
652
+ // Decoded value: 100
653
+ const mockCriteria = createMockCriteria(FilterType.LESS_THAN, PrimitiveType.STRING, '0x64');
654
+ expect(() => action.validateFieldAgainstCriteria(mockCriteria, '50', mockInput)).toThrow('non-numerical');
655
+ });
656
+
657
+ test('should throw InvalidNumericalCriteriaError for LESS_THAN filter type with ADDRESS field type', () => {
658
+ const mockCriteria = createMockCriteria(FilterType.LESS_THAN, PrimitiveType.ADDRESS, '0x1234567890abcdef1234567890abcdef12345678');
659
+ expect(() => action.validateFieldAgainstCriteria(mockCriteria, '0x1234567890abcdef1234567890abcdef12345678', mockInput)).toThrow('non-numerical');
660
+ });
661
+
662
+ test('should return true for anyActionParameter', async () => {
663
+ const mockCriteria = anyActionParameter()
664
+ const result = action.validateFieldAgainstCriteria(mockCriteria, zeroHash, mockInput)
665
+ expect(result).toBe(true)
666
+ })
667
+ })
668
+
669
+ describe("EventAction Func Selector", () => {
670
+ beforeEach(async () => {
671
+ erc721 = await loadFixture(fundErc721(defaultOptions));
672
+ erc20 = await loadFixture(fundErc20(defaultOptions));
673
+ });
674
+
675
+ test("can be deployed successfully", async () => {
102
676
  const action = new EventAction(
103
677
  defaultOptions,
104
- basicErc721TransferAction(erc721),
678
+ basicErc721MintFuncAction(erc721),
105
679
  );
106
680
  await action.deploy();
107
681
  expect(isAddress(action.assertValidAddress())).toBe(true);
108
682
  });
109
683
 
110
- test('can get an action step', async () => {
111
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
112
- const step = await action.getActionStep(0);
113
- if (!step) throw new Error('there should be an action step at this index');
114
- step.targetContract = step.targetContract.toUpperCase() as Hex;
115
- step.actionParameter.filterData =
116
- step.actionParameter.filterData.toUpperCase() as Hex;
117
- expect(step).toMatchObject({
118
- signature: eventSelectors['Transfer(address,address,uint256)'] as Hex,
119
- signatureType: SignatureType.EVENT,
120
- actionType: 0,
121
- targetContract: erc721.assertValidAddress().toUpperCase(),
122
- actionParameter: {
123
- filterType: FilterType.EQUAL,
124
- fieldType: PrimitiveType.ADDRESS,
125
- fieldIndex: 2,
126
- filterData: accounts[1].account.toUpperCase(),
127
- },
684
+ test("validates function action step with correct hash", async () => {
685
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
686
+ const actionSteps = await action.getActionSteps();
687
+ const actionStep = actionSteps[0]!
688
+ const recipient = accounts[1].account;
689
+ const { hash } = await erc721.mintRaw(recipient, {
690
+ value: parseEther(".1"),
128
691
  });
692
+
693
+ expect(
694
+ await action.isActionStepValid(actionStep, { hash, chainId, knownSignatures: allKnownSignatures })
695
+ ).toBe(true);
129
696
  });
130
697
 
131
- test('can get all action steps', async () => {
132
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
133
- const steps = await action.getActionSteps();
134
- expect(steps.length).toBe(1);
135
- const step = steps[0]!;
136
- step.targetContract = step.targetContract.toUpperCase() as Hex;
137
- step.actionParameter.filterData =
138
- step.actionParameter.filterData.toUpperCase() as Hex;
139
- expect(step).toMatchObject({
140
- signature: eventSelectors['Transfer(address,address,uint256)'] as Hex,
141
- signatureType: SignatureType.EVENT,
142
- actionType: 0,
143
- targetContract: erc721.assertValidAddress().toUpperCase(),
144
- actionParameter: {
145
- filterType: FilterType.EQUAL,
146
- fieldType: PrimitiveType.ADDRESS,
147
- fieldIndex: 2,
148
- filterData: accounts[1].account.toUpperCase(),
149
- },
698
+ test("validates function step with EQUAL filter", async () => {
699
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
700
+ const actionSteps = await action.getActionSteps();
701
+ const actionStep = actionSteps[0]!
702
+ const recipient = accounts[1].account;
703
+ const { hash } = await erc721.mintRaw(recipient, {
704
+ value: parseEther(".1"),
150
705
  });
706
+
707
+ const criteriaMatch = await action.isActionStepValid(actionStep, {
708
+ hash,
709
+ chainId,
710
+ knownSignatures: allKnownSignatures
711
+ });
712
+
713
+ expect(criteriaMatch).toBe(true);
151
714
  });
152
715
 
153
- test('can get the total number of action steps', async () => {
154
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
155
- const count = await action.getActionStepsCount();
156
- expect(count).toBe(1);
716
+ test("fails validation with incorrect function signature", async () => {
717
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
718
+ const actionSteps = await action.getActionSteps();
719
+ const actionStep = actionSteps[0]!;
720
+ const recipient = accounts[1].account;
721
+
722
+ const invalidStep = {
723
+ ...actionStep,
724
+ signature: funcSelectors["mint(address to, uint256 amount)"] as Hex, // Intentional mismatch
725
+ };
726
+
727
+ const { hash } = await erc721.mintRaw(recipient, {
728
+ value: parseEther(".1"),
729
+ });
730
+
731
+ try {
732
+ await action.isActionStepValid(invalidStep, { hash, chainId, knownSignatures: allKnownSignatures });
733
+ } catch (e) {
734
+ expect(e).toBeInstanceOf(Error);
735
+ expect((e as Error).message).toContain(
736
+ 'Failed to decode function data: Encoded function signature "0x6a627842"',
737
+ );
738
+ }
157
739
  });
158
740
 
159
- test('can get the action claimant', async () => {
160
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
161
- const claimant = await action.getActionClaimant();
162
- claimant.targetContract = claimant.targetContract.toUpperCase() as Hex;
163
- expect(claimant).toMatchObject({
164
- signatureType: SignatureType.EVENT,
165
- signature: eventSelectors['Transfer(address,address,uint256)'] as Hex,
166
- fieldIndex: 2,
167
- targetContract: erc721.assertValidAddress().toUpperCase(),
741
+ test('validates empty actionParameter', async () => {
742
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721, basicErc721MintFuncActionWithEmptyActionParameter(erc721)))
743
+ const recipient = accounts[1].account;
744
+ const { hash } = await erc721.mintRaw(recipient, {
745
+ value: parseEther(".1"),
168
746
  });
747
+
748
+ expect(await action.validateActionSteps({ hash, chainId, knownSignatures: allKnownSignatures })).toBe(true);
749
+ })
750
+
751
+ test("validates against NOT_EQUAL filter criteria", async () => {
752
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
753
+ const actionSteps = await action.getActionSteps();
754
+ const actionStep = actionSteps[0]!;
755
+ actionStep.actionParameter.filterType = FilterType.NOT_EQUAL;
756
+ const recipient = accounts[2].account;
757
+ const { hash } = await erc721.mintRaw(recipient, {
758
+ value: parseEther(".1"),
759
+ });
760
+
761
+ expect(
762
+ await action.isActionStepValid(actionStep, {
763
+ hash,
764
+ chainId,
765
+ knownSignatures: allKnownSignatures
766
+ }),
767
+ ).toBe(true);
169
768
  });
170
769
 
171
- test('with no logs, does not validate', async () => {
172
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
173
- expect(await action.validateActionSteps()).toBe(false);
770
+ test("validates GREATER_THAN criteria for numeric values", async () => {
771
+ const action = await loadFixture(cloneFunctionAction20(fixtures, erc20));
772
+ const actionSteps = await action.getActionSteps();
773
+ const actionStep = actionSteps[0]!;
774
+
775
+ actionStep.actionParameter = {
776
+ filterType: FilterType.GREATER_THAN,
777
+ fieldType: PrimitiveType.UINT,
778
+ fieldIndex: 1,
779
+ filterData: toHex("1"),
780
+ };
781
+
782
+ const address = accounts[1].account;
783
+ const value = 400n;
784
+ const { hash } = await erc20.mintRaw(address, value);
785
+
786
+ expect(
787
+ await action.isActionStepValid(actionStep, {
788
+ hash,
789
+ chainId,
790
+ knownSignatures: allKnownSignatures
791
+ }),
792
+ ).toBe(true);
174
793
  });
175
794
 
176
- test('with a correct log, validates', async () => {
177
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
795
+ test("validates LESS_THAN criteria for numeric values", async () => {
796
+ const action = await loadFixture(cloneFunctionAction20(fixtures, erc20));
797
+ const actionSteps = await action.getActionSteps();
798
+ const actionStep = actionSteps[0]!;
799
+ actionStep.actionParameter = {
800
+ filterType: FilterType.LESS_THAN,
801
+ fieldType: PrimitiveType.UINT,
802
+ fieldIndex: 1,
803
+ filterData: toHex("5"),
804
+ };
805
+
806
+ const address = accounts[1].account;
807
+ const value = 4n;
808
+ const { hash } = await erc20.mintRaw(address, value);
809
+
810
+ expect(
811
+ await action.isActionStepValid(actionStep, {
812
+ hash,
813
+ chainId,
814
+ knownSignatures: allKnownSignatures
815
+ }),
816
+ ).toBe(true);
817
+ });
818
+
819
+ test("validates entire flow of function action", async () => {
820
+ const action = await loadFixture(cloneFunctionAction(fixtures, erc721));
178
821
  const recipient = accounts[1].account;
179
- await erc721.approve(recipient, 1n);
180
- await erc721.transferFrom(defaultOptions.account.address, recipient, 1n);
181
- expect(await action.validateActionSteps()).toBe(true);
182
- });
183
-
184
- test('can supply your own logs to validate against', async () => {
185
- const log = {
186
- eventName: 'Transfer',
187
- args: undefined,
188
- address: erc721.assertValidAddress(),
189
- blockHash:
190
- '0xbf602f988260519805d032be46d6ff97fbefbee6924b21097074d6d0bc34eced',
191
- blockNumber: 1203n,
192
- data: '0x',
193
- logIndex: 0,
194
- removed: false,
195
- topics: [
196
- '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
197
- '0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
198
- '0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8',
199
- '0x0000000000000000000000000000000000000000000000000000000000000001',
200
- ],
201
- transactionHash:
202
- '0xff0e6ab0c4961ec14b7b40afec83ed7d7a77582683512a262e641d21f82efea5',
203
- transactionIndex: 0,
204
- } as Log;
205
- const action = await loadFixture(cloneEventAction(fixtures, erc721));
206
- expect(await action.validateActionSteps({ logs: [log] })).toBe(true);
822
+ const { hash } = await erc721.mintRaw(recipient, {
823
+ value: parseEther(".1"),
824
+ });
825
+
826
+ expect(
827
+ await action.validateActionSteps({
828
+ hash,
829
+ chainId,
830
+ knownSignatures: allKnownSignatures
831
+ }),
832
+ ).toBe(true);
207
833
  });
208
834
  });