@boostxyz/sdk 0.0.0-alpha.2 → 0.0.0-alpha.21

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 (271) hide show
  1. package/dist/Actions/Action.cjs +2 -1
  2. package/dist/Actions/Action.cjs.map +1 -0
  3. package/dist/Actions/Action.d.ts +1 -1
  4. package/dist/Actions/Action.d.ts.map +1 -1
  5. package/dist/Actions/Action.js +14 -12
  6. package/dist/Actions/Action.js.map +1 -0
  7. package/dist/Actions/ContractAction.d.ts +57 -14
  8. package/dist/Actions/ContractAction.d.ts.map +1 -1
  9. package/dist/Actions/ERC721MintAction.d.ts +50 -23
  10. package/dist/Actions/ERC721MintAction.d.ts.map +1 -1
  11. package/dist/Actions/EventAction.cjs +2 -1
  12. package/dist/Actions/EventAction.cjs.map +1 -0
  13. package/dist/Actions/EventAction.d.ts +405 -36
  14. package/dist/Actions/EventAction.d.ts.map +1 -1
  15. package/dist/Actions/EventAction.js +15 -209
  16. package/dist/Actions/EventAction.js.map +1 -0
  17. package/dist/AllowLists/AllowList.cjs +2 -1
  18. package/dist/AllowLists/AllowList.cjs.map +1 -0
  19. package/dist/AllowLists/AllowList.d.ts +6 -5
  20. package/dist/AllowLists/AllowList.d.ts.map +1 -1
  21. package/dist/AllowLists/AllowList.js +46 -22
  22. package/dist/AllowLists/AllowList.js.map +1 -0
  23. package/dist/AllowLists/OpenAllowList.d.ts +423 -0
  24. package/dist/AllowLists/OpenAllowList.d.ts.map +1 -0
  25. package/dist/AllowLists/SimpleAllowList.cjs +2 -1
  26. package/dist/AllowLists/SimpleAllowList.cjs.map +1 -0
  27. package/dist/AllowLists/SimpleAllowList.d.ts +124 -40
  28. package/dist/AllowLists/SimpleAllowList.d.ts.map +1 -1
  29. package/dist/AllowLists/SimpleAllowList.js +76 -76
  30. package/dist/AllowLists/SimpleAllowList.js.map +1 -0
  31. package/dist/AllowLists/SimpleDenyList.cjs +2 -1
  32. package/dist/AllowLists/SimpleDenyList.cjs.map +1 -0
  33. package/dist/AllowLists/SimpleDenyList.d.ts +234 -13
  34. package/dist/AllowLists/SimpleDenyList.d.ts.map +1 -1
  35. package/dist/AllowLists/SimpleDenyList.js +12 -200
  36. package/dist/AllowLists/SimpleDenyList.js.map +1 -0
  37. package/dist/Auth/Auth.cjs +1 -0
  38. package/dist/Auth/Auth.cjs.map +1 -0
  39. package/dist/Auth/Auth.js +1 -0
  40. package/dist/Auth/Auth.js.map +1 -0
  41. package/dist/Auth/PassthroughAuth.cjs +2 -1
  42. package/dist/Auth/PassthroughAuth.cjs.map +1 -0
  43. package/dist/Auth/PassthroughAuth.js +5 -4
  44. package/dist/Auth/PassthroughAuth.js.map +1 -0
  45. package/dist/Boost.cjs +2 -1
  46. package/dist/Boost.cjs.map +1 -0
  47. package/dist/Boost.d.ts +105 -14
  48. package/dist/Boost.d.ts.map +1 -1
  49. package/dist/Boost.js +138 -5
  50. package/dist/Boost.js.map +1 -0
  51. package/dist/BoostCore-DolmDuXW.cjs +3 -0
  52. package/dist/BoostCore-DolmDuXW.cjs.map +1 -0
  53. package/dist/BoostCore-Z97KVu4V.js +1448 -0
  54. package/dist/BoostCore-Z97KVu4V.js.map +1 -0
  55. package/dist/BoostCore.cjs +2 -2
  56. package/dist/BoostCore.cjs.map +1 -0
  57. package/dist/BoostCore.d.ts +788 -79
  58. package/dist/BoostCore.d.ts.map +1 -1
  59. package/dist/BoostCore.js +30 -1103
  60. package/dist/BoostCore.js.map +1 -0
  61. package/dist/BoostRegistry.cjs +2 -1
  62. package/dist/BoostRegistry.cjs.map +1 -0
  63. package/dist/BoostRegistry.d.ts +95 -26
  64. package/dist/BoostRegistry.d.ts.map +1 -1
  65. package/dist/BoostRegistry.js +183 -89
  66. package/dist/BoostRegistry.js.map +1 -0
  67. package/dist/Budgets/Budget.cjs +2 -1
  68. package/dist/Budgets/Budget.cjs.map +1 -0
  69. package/dist/Budgets/Budget.d.ts +1 -1
  70. package/dist/Budgets/Budget.d.ts.map +1 -1
  71. package/dist/Budgets/Budget.js +15 -13
  72. package/dist/Budgets/Budget.js.map +1 -0
  73. package/dist/Budgets/ManagedBudget.cjs +2 -1
  74. package/dist/Budgets/ManagedBudget.cjs.map +1 -0
  75. package/dist/Budgets/ManagedBudget.d.ts +112 -192
  76. package/dist/Budgets/ManagedBudget.d.ts.map +1 -1
  77. package/dist/Budgets/ManagedBudget.js +91 -291
  78. package/dist/Budgets/ManagedBudget.js.map +1 -0
  79. package/dist/Budgets/VestingBudget.d.ts +277 -91
  80. package/dist/Budgets/VestingBudget.d.ts.map +1 -1
  81. package/dist/Deployable/Contract.cjs +2 -1
  82. package/dist/Deployable/Contract.cjs.map +1 -0
  83. package/dist/Deployable/Contract.d.ts +4 -5
  84. package/dist/Deployable/Contract.d.ts.map +1 -1
  85. package/dist/Deployable/Contract.js +7 -8
  86. package/dist/Deployable/Contract.js.map +1 -0
  87. package/dist/Deployable/Deployable.cjs +1 -0
  88. package/dist/Deployable/Deployable.cjs.map +1 -0
  89. package/dist/Deployable/Deployable.d.ts +9 -3
  90. package/dist/Deployable/Deployable.d.ts.map +1 -1
  91. package/dist/Deployable/Deployable.js +10 -5
  92. package/dist/Deployable/Deployable.js.map +1 -0
  93. package/dist/Deployable/DeployableTarget.cjs +2 -1
  94. package/dist/Deployable/DeployableTarget.cjs.map +1 -0
  95. package/dist/Deployable/DeployableTarget.d.ts +16 -15
  96. package/dist/Deployable/DeployableTarget.d.ts.map +1 -1
  97. package/dist/Deployable/DeployableTarget.js +49 -42
  98. package/dist/Deployable/DeployableTarget.js.map +1 -0
  99. package/dist/Deployable/DeployableTargetWithRBAC.cjs +2 -0
  100. package/dist/Deployable/DeployableTargetWithRBAC.cjs.map +1 -0
  101. package/dist/Deployable/DeployableTargetWithRBAC.d.ts +179 -0
  102. package/dist/Deployable/DeployableTargetWithRBAC.d.ts.map +1 -0
  103. package/dist/Deployable/DeployableTargetWithRBAC.js +222 -0
  104. package/dist/Deployable/DeployableTargetWithRBAC.js.map +1 -0
  105. package/dist/EventAction-CBKzuNoN.cjs +2 -0
  106. package/dist/EventAction-CBKzuNoN.cjs.map +1 -0
  107. package/dist/EventAction-DWuuc_Qy.js +1528 -0
  108. package/dist/EventAction-DWuuc_Qy.js.map +1 -0
  109. package/dist/Incentive-BxzEtN26.js +298 -0
  110. package/dist/Incentive-BxzEtN26.js.map +1 -0
  111. package/dist/Incentive-CrF3-ayL.cjs +2 -0
  112. package/dist/Incentive-CrF3-ayL.cjs.map +1 -0
  113. package/dist/Incentives/AllowListIncentive.cjs +2 -1
  114. package/dist/Incentives/AllowListIncentive.cjs.map +1 -0
  115. package/dist/Incentives/AllowListIncentive.d.ts +65 -21
  116. package/dist/Incentives/AllowListIncentive.d.ts.map +1 -1
  117. package/dist/Incentives/AllowListIncentive.js +52 -36
  118. package/dist/Incentives/AllowListIncentive.js.map +1 -0
  119. package/dist/Incentives/CGDAIncentive.cjs +2 -1
  120. package/dist/Incentives/CGDAIncentive.cjs.map +1 -0
  121. package/dist/Incentives/CGDAIncentive.d.ts +315 -26
  122. package/dist/Incentives/CGDAIncentive.d.ts.map +1 -1
  123. package/dist/Incentives/CGDAIncentive.js +64 -39
  124. package/dist/Incentives/CGDAIncentive.js.map +1 -0
  125. package/dist/Incentives/ERC1155Incentive.d.ts +291 -43
  126. package/dist/Incentives/ERC1155Incentive.d.ts.map +1 -1
  127. package/dist/Incentives/ERC20Incentive.cjs +2 -1
  128. package/dist/Incentives/ERC20Incentive.cjs.map +1 -0
  129. package/dist/Incentives/ERC20Incentive.d.ts +270 -33
  130. package/dist/Incentives/ERC20Incentive.d.ts.map +1 -1
  131. package/dist/Incentives/ERC20Incentive.js +69 -46
  132. package/dist/Incentives/ERC20Incentive.js.map +1 -0
  133. package/dist/{Budgets/SimpleBudget.d.ts → Incentives/ERC20VariableCriteriaIncentive.d.ts} +338 -421
  134. package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts.map +1 -0
  135. package/dist/Incentives/ERC20VariableIncentive.d.ts +262 -32
  136. package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -1
  137. package/dist/Incentives/Incentive.cjs +2 -1
  138. package/dist/Incentives/Incentive.cjs.map +1 -0
  139. package/dist/Incentives/Incentive.d.ts +5 -8
  140. package/dist/Incentives/Incentive.d.ts.map +1 -1
  141. package/dist/Incentives/Incentive.js +17 -278
  142. package/dist/Incentives/Incentive.js.map +1 -0
  143. package/dist/Incentives/PointsIncentive.cjs +2 -1
  144. package/dist/Incentives/PointsIncentive.cjs.map +1 -0
  145. package/dist/Incentives/PointsIncentive.d.ts +81 -23
  146. package/dist/Incentives/PointsIncentive.d.ts.map +1 -1
  147. package/dist/Incentives/PointsIncentive.js +57 -36
  148. package/dist/Incentives/PointsIncentive.js.map +1 -0
  149. package/dist/SimpleDenyList-BUR17Tt1.cjs +2 -0
  150. package/dist/SimpleDenyList-BUR17Tt1.cjs.map +1 -0
  151. package/dist/SimpleDenyList-CGaWjuld.js +132 -0
  152. package/dist/SimpleDenyList-CGaWjuld.js.map +1 -0
  153. package/dist/Validators/SignerValidator.cjs +2 -1
  154. package/dist/Validators/SignerValidator.cjs.map +1 -0
  155. package/dist/Validators/SignerValidator.d.ts +310 -17
  156. package/dist/Validators/SignerValidator.d.ts.map +1 -1
  157. package/dist/Validators/SignerValidator.js +165 -36
  158. package/dist/Validators/SignerValidator.js.map +1 -0
  159. package/dist/Validators/Validator.cjs +2 -1
  160. package/dist/Validators/Validator.cjs.map +1 -0
  161. package/dist/Validators/Validator.d.ts +2 -2
  162. package/dist/Validators/Validator.d.ts.map +1 -1
  163. package/dist/Validators/Validator.js +10 -8
  164. package/dist/Validators/Validator.js.map +1 -0
  165. package/dist/claiming.cjs +2 -0
  166. package/dist/claiming.cjs.map +1 -0
  167. package/dist/claiming.d.ts +43 -0
  168. package/dist/claiming.d.ts.map +1 -0
  169. package/dist/claiming.js +17 -0
  170. package/dist/claiming.js.map +1 -0
  171. package/dist/componentInterfaces-BBCFkrZv.js +14 -0
  172. package/dist/componentInterfaces-BBCFkrZv.js.map +1 -0
  173. package/dist/componentInterfaces-DRI_dQ-P.cjs +2 -0
  174. package/dist/componentInterfaces-DRI_dQ-P.cjs.map +1 -0
  175. package/dist/deployments-DVXioW2i.cjs +2 -0
  176. package/dist/deployments-DVXioW2i.cjs.map +1 -0
  177. package/dist/deployments-oykLv3_Z.js +43 -0
  178. package/dist/deployments-oykLv3_Z.js.map +1 -0
  179. package/dist/deployments.json +44 -0
  180. package/dist/errors.cjs +2 -1
  181. package/dist/errors.cjs.map +1 -0
  182. package/dist/errors.d.ts +421 -1
  183. package/dist/errors.d.ts.map +1 -1
  184. package/dist/errors.js +297 -39
  185. package/dist/errors.js.map +1 -0
  186. package/dist/{generated-x_abr3Yv.js → generated-CKt2yCQd.js} +3143 -3002
  187. package/dist/generated-CKt2yCQd.js.map +1 -0
  188. package/dist/generated-CyTNlOwM.cjs +3 -0
  189. package/dist/generated-CyTNlOwM.cjs.map +1 -0
  190. package/dist/index.cjs +2 -1
  191. package/dist/index.cjs.map +1 -0
  192. package/dist/index.d.ts +10 -9
  193. package/dist/index.d.ts.map +1 -1
  194. package/dist/index.js +144 -1353
  195. package/dist/index.js.map +1 -0
  196. package/dist/transfers.cjs +2 -0
  197. package/dist/transfers.cjs.map +1 -0
  198. package/dist/transfers.d.ts +198 -0
  199. package/dist/transfers.d.ts.map +1 -0
  200. package/dist/transfers.js +84 -0
  201. package/dist/transfers.js.map +1 -0
  202. package/dist/utils.cjs +2 -1
  203. package/dist/utils.cjs.map +1 -0
  204. package/dist/utils.d.ts +26 -1350
  205. package/dist/utils.d.ts.map +1 -1
  206. package/dist/utils.js +38 -636
  207. package/dist/utils.js.map +1 -0
  208. package/package.json +37 -11
  209. package/src/Actions/Action.test.ts +79 -0
  210. package/src/Actions/Action.ts +61 -0
  211. package/src/Actions/ContractAction.test.ts +197 -0
  212. package/src/Actions/ContractAction.ts +300 -0
  213. package/src/Actions/ERC721MintAction.test.ts +112 -0
  214. package/src/Actions/ERC721MintAction.ts +291 -0
  215. package/src/Actions/EventAction.test.ts +787 -0
  216. package/src/Actions/EventAction.ts +1218 -0
  217. package/src/AllowLists/AllowList.test.ts +64 -0
  218. package/src/AllowLists/AllowList.ts +62 -0
  219. package/src/AllowLists/OpenAllowList.test.ts +40 -0
  220. package/src/AllowLists/OpenAllowList.ts +45 -0
  221. package/src/AllowLists/SimpleAllowList.test.ts +52 -0
  222. package/src/AllowLists/SimpleAllowList.ts +262 -0
  223. package/src/AllowLists/SimpleDenyList.test.ts +52 -0
  224. package/src/AllowLists/SimpleDenyList.ts +250 -0
  225. package/src/Auth/Auth.ts +11 -0
  226. package/src/Auth/PassthroughAuth.test.ts +12 -0
  227. package/src/Auth/PassthroughAuth.ts +80 -0
  228. package/src/Boost.ts +287 -0
  229. package/src/BoostCore.test.ts +894 -0
  230. package/src/BoostCore.ts +1438 -0
  231. package/src/BoostRegistry.test.ts +53 -0
  232. package/src/BoostRegistry.ts +588 -0
  233. package/src/Budgets/Budget.test.ts +27 -0
  234. package/src/Budgets/Budget.ts +60 -0
  235. package/src/Budgets/ManagedBudget.test.ts +217 -0
  236. package/src/Budgets/ManagedBudget.ts +534 -0
  237. package/src/Budgets/VestingBudget.test.ts +123 -0
  238. package/src/Budgets/VestingBudget.ts +530 -0
  239. package/src/Deployable/Contract.ts +228 -0
  240. package/src/Deployable/Deployable.ts +250 -0
  241. package/src/Deployable/DeployableTarget.ts +234 -0
  242. package/src/Deployable/DeployableTargetWithRBAC.ts +323 -0
  243. package/src/Incentives/AllowListIncentive.test.ts +143 -0
  244. package/src/Incentives/AllowListIncentive.ts +336 -0
  245. package/src/Incentives/CGDAIncentive.test.ts +135 -0
  246. package/src/Incentives/CGDAIncentive.ts +476 -0
  247. package/src/Incentives/ERC1155Incentive.test.ts +87 -0
  248. package/src/Incentives/ERC1155Incentive.ts +465 -0
  249. package/src/Incentives/ERC20Incentive.test.ts +133 -0
  250. package/src/Incentives/ERC20Incentive.ts +490 -0
  251. package/src/Incentives/ERC20VariableCriteriaIncentive.test.ts +184 -0
  252. package/src/Incentives/ERC20VariableCriteriaIncentive.ts +309 -0
  253. package/src/Incentives/ERC20VariableIncentive.test.ts +139 -0
  254. package/src/Incentives/ERC20VariableIncentive.ts +428 -0
  255. package/src/Incentives/Incentive.test.ts +95 -0
  256. package/src/Incentives/Incentive.ts +86 -0
  257. package/src/Incentives/PointsIncentive.test.ts +138 -0
  258. package/src/Incentives/PointsIncentive.ts +367 -0
  259. package/src/Validators/SignerValidator.test.ts +159 -0
  260. package/src/Validators/SignerValidator.ts +683 -0
  261. package/src/Validators/Validator.test.ts +21 -0
  262. package/src/Validators/Validator.ts +55 -0
  263. package/src/claiming.ts +56 -0
  264. package/src/errors.ts +866 -0
  265. package/src/index.test.ts +122 -0
  266. package/src/index.ts +58 -0
  267. package/src/transfers.ts +284 -0
  268. package/src/utils.test.ts +44 -0
  269. package/src/utils.ts +247 -0
  270. package/dist/Budgets/SimpleBudget.d.ts.map +0 -1
  271. package/dist/generated-BaaleHW-.cjs +0 -2
@@ -0,0 +1,53 @@
1
+ import { loadFixture } from '@nomicfoundation/hardhat-toolbox-viem/network-helpers';
2
+ import { pad, parseEther, zeroAddress, isAddress } from 'viem';
3
+ import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
4
+ import {
5
+ type BudgetFixtures,
6
+ type Fixtures,
7
+ defaultOptions,
8
+ deployFixtures,
9
+ freshBoost,
10
+ fundBudget,
11
+ makeMockEventActionPayload,
12
+ } from '@boostxyz/test/helpers';
13
+ import { ContractAction } from './Actions/ContractAction';
14
+ import type { ERC20Incentive } from './Incentives/ERC20Incentive';
15
+ import { StrategyType } from './claiming';
16
+ import { BoostNotFoundError, IncentiveNotCloneableError } from './errors';
17
+ import { bytes4, RegistryType } from './utils';
18
+ import { BOOST_CORE_CLAIM_FEE } from './BoostCore';
19
+ import { accounts } from '@boostxyz/test/accounts';
20
+ import { SimpleAllowList } from './AllowLists/SimpleAllowList';
21
+
22
+ let fixtures: Fixtures, budgets: BudgetFixtures;
23
+
24
+ describe('BoostRegistry', () => {
25
+ beforeAll(async () => {
26
+ fixtures = await loadFixture(deployFixtures(defaultOptions));
27
+ });
28
+
29
+ test('can initialize a new component', async () => {
30
+ const { registry, core } = fixtures;
31
+ const allowlist = await registry.initialize('NewAllowList', core.SimpleAllowList({
32
+ owner: zeroAddress,
33
+ allowed: []
34
+ }))
35
+ expect(isAddress(allowlist.assertValidAddress())).toBe(true)
36
+ });
37
+
38
+ test('can use a clones identifier to get the clone', async () => {
39
+ const { registry, bases } = fixtures;
40
+ const id = await registry.getCloneIdentifier(
41
+ RegistryType.ALLOW_LIST,
42
+ bases.SimpleAllowList.bases[31337]!,
43
+ defaultOptions.account.address,
44
+ 'NewAllowList'
45
+ )
46
+ expect(await registry.getClone(id)).toMatchObject({
47
+ baseType: RegistryType.ALLOW_LIST,
48
+ instance: expect.any(String),
49
+ deployer: defaultOptions.account.address,
50
+ name: 'NewAllowList'
51
+ })
52
+ });
53
+ });
@@ -0,0 +1,588 @@
1
+ import {
2
+ boostRegistryAbi,
3
+ readBoostRegistryGetBaseImplementation,
4
+ readBoostRegistryGetClone,
5
+ readBoostRegistryGetCloneIdentifier,
6
+ readBoostRegistryGetClones,
7
+ simulateBoostRegistryDeployClone,
8
+ simulateBoostRegistryRegister,
9
+ writeBoostRegistryDeployClone,
10
+ writeBoostRegistryRegister,
11
+ } from '@boostxyz/evm';
12
+ import { bytecode } from '@boostxyz/evm/artifacts/contracts/BoostRegistry.sol/BoostRegistry.json';
13
+ import {
14
+ type Abi,
15
+ type Address,
16
+ type ContractEventName,
17
+ type Hex,
18
+ isAddress,
19
+ zeroAddress,
20
+ } from 'viem';
21
+ import { BoostRegistry as BoostRegistryBases } from '../dist/deployments.json';
22
+ import {
23
+ Deployable,
24
+ type DeployableOptions,
25
+ type GenericDeployableParams,
26
+ } from './Deployable/Deployable';
27
+ import type { DeployableTarget } from './Deployable/DeployableTarget';
28
+ import {
29
+ type GenericLog,
30
+ type HashAndSimulatedResult,
31
+ type ReadParams,
32
+ type RegistryType,
33
+ type WriteParams,
34
+ assertValidAddressByChainId,
35
+ } from './utils';
36
+
37
+ /**
38
+ * The ABI of the BoostRegistry contract, if needed for low level operations
39
+ *
40
+ * @type {typeof boostRegistryAbi}
41
+ */
42
+ export { boostRegistryAbi };
43
+
44
+ /**
45
+ * The address of the deployed `BoostRegistry` instance. In prerelease mode, this will be its sepolia address
46
+ *
47
+ * @type {Address}
48
+ */
49
+ export const BOOST_REGISTRY_ADDRESS =
50
+ (BoostRegistryBases as Record<string, Address>)[__DEFAULT_CHAIN_ID__] ||
51
+ zeroAddress;
52
+
53
+ /**
54
+ * The fixed addresses for the deployed Boost Registry.
55
+ * By default, `new BoostRegistry` will use the address deployed to the currently connected chain, or `BOOST_REGISTRY_ADDRESS` if not provided.
56
+ *
57
+ * @type {Record<number, Address>}
58
+ */
59
+ export const BOOST_REGISTRY_ADDRESSES: Record<number, Address> = {
60
+ ...(BoostRegistryBases as Record<number, Address>),
61
+ 31337: import.meta.env.VITE_BOOST_REGISTRY_ADDRESS,
62
+ };
63
+
64
+ /**
65
+ * A record of `BoostRegistry` event names to `AbiEvent` objects for use with `getLogs`
66
+ *
67
+ * @export
68
+ * @typedef {BoostRegistryLog}
69
+ * @template {ContractEventName<typeof boostRegistryAbi>} [event=ContractEventName<
70
+ * typeof boostRegistryAbi
71
+ * >]
72
+ */
73
+ export type BoostRegistryLog<
74
+ event extends ContractEventName<typeof boostRegistryAbi> = ContractEventName<
75
+ typeof boostRegistryAbi
76
+ >,
77
+ > = GenericLog<typeof boostRegistryAbi, event>;
78
+
79
+ /**
80
+ * An interface representing an on-chain Clone
81
+ *
82
+ * @export
83
+ * @interface Clone
84
+ * @typedef {Clone}
85
+ */
86
+ export interface Clone {
87
+ // The clone's component type'
88
+ baseType: RegistryType;
89
+ // The address of the initialized clone.
90
+ instance: Address;
91
+ // The deployer of the clone.
92
+ deployer: Address;
93
+ // The display name of the clone
94
+ name: string;
95
+ }
96
+
97
+ /**
98
+ * Instantiation options for a previously deployed Boost Registry
99
+ *
100
+ * @export
101
+ * @interface BoostRegistryDeployedOptions
102
+ * @typedef {BoostRegistryDeployedOptions}
103
+ * @extends {DeployableOptions}
104
+ */
105
+ export interface BoostRegistryDeployedOptions extends DeployableOptions {
106
+ /**
107
+ * The address for a Boost Registry, if different than `BOOST_REGISTRY_ADDRESS`
108
+ *
109
+ * @type {?Address}
110
+ */
111
+ address?: Address;
112
+ }
113
+
114
+ /**
115
+ * A typeguard to determine if instantiation is using a custom address.
116
+ *
117
+ * @param {*} opts
118
+ * @returns {opts is BoostRegistryDeployedOptions}
119
+ */
120
+ function isBoostRegistryDeployed(
121
+ // biome-ignore lint/suspicious/noExplicitAny: type guard
122
+ opts: any,
123
+ ): opts is BoostRegistryDeployedOptions {
124
+ return opts.address && isAddress(opts.address);
125
+ }
126
+
127
+ /**
128
+ * The Boost Registry does not take any construction arguments, so if you'd like to deploy a new Boost Registry, pass an explicit null to the `address` field.
129
+ *
130
+ * @export
131
+ * @interface BoostRegistryOptionsWithPayload
132
+ * @typedef {BoostRegistryOptionsWithPayload}
133
+ * @extends {DeployableOptions}
134
+ */
135
+ export interface BoostRegistryOptionsWithPayload extends DeployableOptions {
136
+ /**
137
+ *
138
+ * @type {null}
139
+ */
140
+ address: null;
141
+ }
142
+
143
+ /**
144
+ * A typeguard to determine if the user is intending to deploy a new Boost Registry before usage
145
+ *
146
+ * @param {*} opts
147
+ * @returns {opts is BoostRegistryOptionsWithPayload}
148
+ */
149
+ function isBoostRegistryDeployable(
150
+ // biome-ignore lint/suspicious/noExplicitAny: type guard
151
+ opts: any,
152
+ ): opts is BoostRegistryOptionsWithPayload {
153
+ return opts.address === null;
154
+ }
155
+
156
+ /**
157
+ * Instantiation options for a Boost Registry.
158
+ *
159
+ * @example
160
+ * To target Boost's Registry, omit the address field.
161
+ * Otherwise, supply a custom address to a previously deployed custom Boost Registry.
162
+ * You can also pass `{ address: null }` if you are intending to deploy a new Boost Registry.
163
+ * ```ts
164
+ * let registry = new BoostRegistry({ config, account })
165
+ * // or
166
+ * registry = new BoostRegistry({ config, account, address: CUSTOM_ADDRESS })
167
+ * // or
168
+ * registry = new BoostRegistry({ config, account, address: null })
169
+ * await registry.deploy()
170
+ * ```
171
+ *
172
+ * @export
173
+ * @typedef {BoostRegistryConfig}
174
+ */
175
+ export type BoostRegistryConfig =
176
+ | BoostRegistryDeployedOptions
177
+ | BoostRegistryOptionsWithPayload;
178
+
179
+ /**
180
+ * Constructs a new Boost Registry. A registry for base implementations and cloned instances.
181
+ * This contract is used to register base implementations and deploy new instances of those implementations for use within the Boost protocol.
182
+ *
183
+ * @see {@link BoostRegistryConfig}
184
+ * @export
185
+ * @class BoostRegistry
186
+ * @typedef {BoostRegistry}
187
+ * @extends {Deployable<never[]>}
188
+ */
189
+ export class BoostRegistry extends Deployable<
190
+ never[],
191
+ typeof boostRegistryAbi
192
+ > {
193
+ /**
194
+ * A static property representing a map of stringified chain ID's to the address of the deployed implementation on chain
195
+ *
196
+ * @static
197
+ * @readonly
198
+ * @type {Record<string, Address>}
199
+ */
200
+ static readonly addresses: Record<number, Address> = BOOST_REGISTRY_ADDRESSES;
201
+
202
+ /**
203
+ * A getter that will return Boost registry's static addresses by numerical chain ID
204
+ *
205
+ * @public
206
+ * @readonly
207
+ * @type {Record<number, Address>}
208
+ */
209
+ public get addresses(): Record<number, Address> {
210
+ return (this.constructor as typeof BoostRegistry).addresses;
211
+ }
212
+
213
+ /**
214
+ * Creates an instance of BoostRegistry.
215
+ *
216
+ * @see {@link BoostRegistryConfig}
217
+ * @constructor
218
+ * @param {BoostRegistryConfig} param0
219
+ * @param {Config} param0.config - [Wagmi Configuration](https://wagmi.sh/core/api/createConfig)
220
+ * @param {?Account} [param0.account] - [Viem Local Account](https://viem.sh/docs/accounts/local)
221
+ * @param {({ address?: Address; } | {})} param0....options
222
+ */
223
+ constructor({ config, account, ...options }: BoostRegistryConfig) {
224
+ if (isBoostRegistryDeployed(options) && options.address) {
225
+ super({ account, config }, options.address);
226
+ } else if (isBoostRegistryDeployable(options)) {
227
+ super({ account, config }, []);
228
+ } else {
229
+ const { address } = assertValidAddressByChainId(
230
+ config,
231
+ BOOST_REGISTRY_ADDRESSES,
232
+ );
233
+ super({ account, config }, address);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Register a new base implementation of a given type
239
+ *
240
+ * @public
241
+ * @async
242
+ * @param {RegistryType} registryType - The base type for the implementation
243
+ * @param {string} name - A name for the implementation (must be unique within the given type)
244
+ * @param {Address} implementation - The address of the implementation contract
245
+ * @param {?WriteParams} [params] - Optional params to provide the underlying Viem contract call
246
+ * @returns {Promise<void>}
247
+ * @example
248
+ * ```ts
249
+ * await registry.register(ContractAction.registryType, 'ContractAction', ContractAction.base)
250
+ * ```
251
+ */
252
+ public async register(
253
+ registryType: RegistryType,
254
+ name: string,
255
+ implementation: Address,
256
+ params?: WriteParams<typeof boostRegistryAbi, 'register'>,
257
+ ) {
258
+ return await this.awaitResult(
259
+ this.registerRaw(registryType, name, implementation, params),
260
+ );
261
+ }
262
+
263
+ /**
264
+ * @see {@link register}
265
+ * @public
266
+ * @async
267
+ * @param {RegistryType} registryType
268
+ * @param {string} name
269
+ * @param {Address} implementation
270
+ * @param {?WriteParams} [params]
271
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
272
+ */
273
+ public async registerRaw(
274
+ registryType: RegistryType,
275
+ name: string,
276
+ implementation: Address,
277
+ params?: WriteParams<typeof boostRegistryAbi, 'register'>,
278
+ ) {
279
+ const { request, result } = await simulateBoostRegistryRegister(
280
+ this._config,
281
+ {
282
+ ...assertValidAddressByChainId(
283
+ this._config,
284
+ this.addresses,
285
+ params?.chain?.id || params?.chainId,
286
+ ),
287
+ args: [registryType, name, implementation],
288
+ ...this.optionallyAttachAccount(),
289
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
290
+ ...(params as any),
291
+ },
292
+ );
293
+ const hash = await writeBoostRegistryRegister(this._config, request);
294
+ return { hash, result };
295
+ }
296
+
297
+ /**
298
+ * Initialize a new instance of a registered base implementation, returning the provided target with a new address set on it.
299
+ * This method is the same as `clone`, but serves to make its function more obvious as to why you'd need to use it.
300
+ *
301
+ * @public
302
+ * @async
303
+ * @template {DeployableTarget} Target
304
+ * @param {string} displayName - The display name for the clone
305
+ * @param {Target} target - An instance of a target contract to clone and initialize
306
+ * @param {?WriteParams} [params]
307
+ * @returns {Promise<Target>} - The provided instance, but with a new address attached.
308
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
309
+ */
310
+ public initialize<Target extends DeployableTarget<any, any>>(
311
+ displayName: string,
312
+ target: Target,
313
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
314
+ ): Promise<Target> {
315
+ return this.clone(displayName, target, params);
316
+ }
317
+
318
+ /**
319
+ * Initialize a new instance of a registered base implementation, returning a transaction hash, resulting address from simulated transaction, and the given target bound to the resulting address.
320
+ * This method is the same as `deployCloneRaw`, but serves to make its function more obvious as to why you'd need to use it.
321
+ *
322
+ * @public
323
+ * @async
324
+ * @template {DeployableTarget} Target
325
+ * @param {string} displayName - The display name for the clone
326
+ * @param {Target} target - An instance of a target contract to clone and initialize
327
+ * @param {?WriteParams} [params]
328
+ * @returns {Promise<HashAndSimulatedResult<Address> & { target: Target } >} - The transaction hash, simulated return address, and given target bound to simulated return address
329
+ */
330
+ public async initializeRaw<Target extends DeployableTarget<unknown, Abi>>(
331
+ displayName: string,
332
+ target: Target,
333
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
334
+ ): Promise<HashAndSimulatedResult<Address> & { target: Target }> {
335
+ const { hash, result } = await this.deployCloneRaw(
336
+ displayName,
337
+ target,
338
+ params,
339
+ );
340
+ return { hash, result, target: target.at(result) };
341
+ }
342
+
343
+ /**
344
+ * Deploy a new instance of a registered base implementation, returning the provided target with a new address set on it.
345
+ *
346
+ * @public
347
+ * @async
348
+ * @template {DeployableTarget} Target
349
+ * @param {string} displayName - The display name for the clone
350
+ * @param {Target} target - An instance of a target contract to clone and initialize
351
+ * @param {?WriteParams} [params]
352
+ * @returns {Promise<Target>} - The provided instance, but with a new address attached.
353
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
354
+ */
355
+ public async clone<Target extends DeployableTarget<any, any>>(
356
+ displayName: string,
357
+ target: Target,
358
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
359
+ ): Promise<Target> {
360
+ const instance = await this.deployClone(displayName, target, params);
361
+ return target.at(instance);
362
+ }
363
+
364
+ /**
365
+ *
366
+ * @see {@link clone}
367
+ * @public
368
+ * @async
369
+ * @template {DeployableTarget} Target
370
+ * @param {string} displayName
371
+ * @param {Target} target
372
+ * @param {?WriteParams} [params]
373
+ * @returns {Promise<Address>}
374
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
375
+ */
376
+ public async deployClone<Target extends DeployableTarget<any, any>>(
377
+ displayName: string,
378
+ target: Target,
379
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
380
+ ): Promise<Address> {
381
+ return await this.awaitResult(
382
+ this.deployCloneRaw(displayName, target, params),
383
+ );
384
+ }
385
+
386
+ /**
387
+ * @see {@link clone}
388
+ * @public
389
+ * @async
390
+ * @param {string} displayName
391
+ * @param {DeployableTarget} target
392
+ * @param {?WriteParams} [params]
393
+ * @returns {Promise<{ hash: Hex, result: Address }>} - The transaction hash
394
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
395
+ */
396
+ public async deployCloneRaw<Target extends DeployableTarget<any, any>>(
397
+ displayName: string,
398
+ target: Target,
399
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
400
+ ): Promise<HashAndSimulatedResult<Address>> {
401
+ const payload = target.buildParameters(undefined, {
402
+ config: this._config,
403
+ account: this._account,
404
+ });
405
+ const { address: baseAddress } = assertValidAddressByChainId(
406
+ this._config,
407
+ target.bases,
408
+ params?.chain?.id || params?.chainId,
409
+ );
410
+ const { request, result } = await simulateBoostRegistryDeployClone(
411
+ this._config,
412
+ {
413
+ ...assertValidAddressByChainId(
414
+ this._config,
415
+ this.addresses,
416
+ params?.chain?.id || params?.chainId,
417
+ ),
418
+ args: [target.registryType, baseAddress, displayName, payload.args[0]],
419
+ ...this.optionallyAttachAccount(),
420
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
421
+ ...(params as any),
422
+ },
423
+ );
424
+ const hash = await writeBoostRegistryDeployClone(this._config, request);
425
+ return { hash, result };
426
+ }
427
+
428
+ /**
429
+ * Get the address of a registered base implementation.
430
+ * This function will revert if the implementation is not registered
431
+ *
432
+ * @public
433
+ * @async
434
+ * @param {Hex} identifier - The unique identifier for the implementation (see {getIdentifier})
435
+ * @param {?ReadParams} [params]
436
+ * @returns {Promise<Address>} - The address of the implementation
437
+ */
438
+ public async getBaseImplementation(
439
+ identifier: Hex,
440
+ params?: ReadParams<typeof boostRegistryAbi, 'getBaseImplementation'>,
441
+ ) {
442
+ return await readBoostRegistryGetBaseImplementation(this._config, {
443
+ ...assertValidAddressByChainId(
444
+ this._config,
445
+ this.addresses,
446
+ params?.chainId,
447
+ ),
448
+ args: [identifier],
449
+ ...this.optionallyAttachAccount(),
450
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
451
+ ...(params as any),
452
+ });
453
+ }
454
+
455
+ /**
456
+ * Get the address of a deployed clone by its identifier
457
+ *
458
+ * @public
459
+ * @async
460
+ * @param {Hex} identifier - The unique identifier for the deployed clone (see {getCloneIdentifier})
461
+ * @param {?ReadParams} [params]
462
+ * @returns {Promise<Clone>} - The on-chain representation of the clone
463
+ */
464
+ public async getClone(
465
+ identifier: Hex,
466
+ params?: ReadParams<typeof boostRegistryAbi, 'getClone'>,
467
+ ): Promise<Clone> {
468
+ return await readBoostRegistryGetClone(this._config, {
469
+ ...assertValidAddressByChainId(
470
+ this._config,
471
+ this.addresses,
472
+ params?.chainId,
473
+ ),
474
+ args: [identifier],
475
+ ...this.optionallyAttachAccount(),
476
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
477
+ ...(params as any),
478
+ });
479
+ }
480
+
481
+ /**
482
+ * Get the list of identifiers of deployed clones for a given deployer
483
+ *
484
+ * @public
485
+ * @async
486
+ * @param {Address} deployer - The address of the deployer
487
+ * @param {?ReadParams} [params]
488
+ * @returns {Promise<Hex[]>} - The list of deployed clones for the given deployer
489
+ */
490
+ public async getClones(
491
+ deployer: Address,
492
+ params?: ReadParams<typeof boostRegistryAbi, 'getClones'>,
493
+ ) {
494
+ return await readBoostRegistryGetClones(this._config, {
495
+ ...assertValidAddressByChainId(
496
+ this._config,
497
+ this.addresses,
498
+ params?.chainId,
499
+ ),
500
+ args: [deployer],
501
+ ...this.optionallyAttachAccount(),
502
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
503
+ ...(params as any),
504
+ });
505
+ }
506
+
507
+ /**
508
+ * Build the identifier for a clone of a base implementation
509
+ *
510
+ * @public
511
+ * @async
512
+ * @param {RegistryType} registryType - The base type for the implementation
513
+ * @param {Address} base - The address of the base implementation
514
+ * @param {Address} deployer - The address of the deployer
515
+ * @param {string} displayName - The display name of the clone
516
+ * @param {?ReadParams} [params]
517
+ * @returns {Promise<Hex>} - The unique identifier for the clone
518
+ */
519
+ public async getCloneIdentifier(
520
+ registryType: RegistryType,
521
+ base: Address,
522
+ deployer: Address,
523
+ displayName: string,
524
+ params?: ReadParams<typeof boostRegistryAbi, 'getCloneIdentifier'>,
525
+ ) {
526
+ return await readBoostRegistryGetCloneIdentifier(this._config, {
527
+ ...assertValidAddressByChainId(
528
+ this._config,
529
+ this.addresses,
530
+ params?.chainId,
531
+ ),
532
+ args: [registryType, base, deployer, displayName],
533
+ ...this.optionallyAttachAccount(),
534
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
535
+ ...(params as any),
536
+ });
537
+ }
538
+
539
+ /**
540
+ * Build the identifier for a base implementation
541
+ *
542
+ * @public
543
+ * @async
544
+ * @param {RegistryType} registryType - The base type for the implementation
545
+ * @param {string} displayName - The name of the implementation
546
+ * @param {?ReadParams} [params]
547
+ * @returns {Promise<Hex>} - The unique identifier for the implementation
548
+ */
549
+ public async getIdentifier(
550
+ registryType: RegistryType,
551
+ displayName: string,
552
+ params?: ReadParams<typeof boostRegistryAbi, 'getIdentifier'>,
553
+ ) {
554
+ return await readBoostRegistryGetCloneIdentifier(this._config, {
555
+ ...assertValidAddressByChainId(
556
+ this._config,
557
+ this.addresses,
558
+ params?.chainId,
559
+ ),
560
+ args: [registryType, displayName],
561
+ ...this.optionallyAttachAccount(),
562
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
563
+ ...(params as any),
564
+ });
565
+ }
566
+
567
+ /**
568
+ * @inheritdoc
569
+ *
570
+ * @public
571
+ * @param {?never[]} [_payload]
572
+ * @param {?DeployableOptions} [_options]
573
+ * @returns {GenericDeployableParams}
574
+ */
575
+ public override buildParameters(
576
+ _payload?: never[],
577
+ _options?: DeployableOptions,
578
+ ): GenericDeployableParams {
579
+ const [, options] = this.validateDeploymentConfig([], _options);
580
+ return {
581
+ abi: boostRegistryAbi,
582
+ bytecode: bytecode as Hex,
583
+ // biome-ignore lint/suspicious/noExplicitAny: Registry doesn't construct or initialize
584
+ args: [] as any,
585
+ ...this.optionallyAttachAccount(options.account),
586
+ };
587
+ }
588
+ }
@@ -0,0 +1,27 @@
1
+ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
2
+ import { beforeAll, describe, expect, test } from 'vitest';
3
+ import {
4
+ type Fixtures,
5
+ defaultOptions,
6
+ deployFixtures,
7
+ freshManagedBudget,
8
+ } from '@boostxyz/test/helpers';
9
+ import { budgetFromAddress } from './Budget';
10
+ import { ManagedBudget } from './ManagedBudget';
11
+
12
+ let fixtures: Fixtures;
13
+
14
+ beforeAll(async () => {
15
+ fixtures = await loadFixture(deployFixtures(defaultOptions));
16
+ });
17
+
18
+ describe('Budget', () => {
19
+ test('can automatically instantiate ManagedBudget given an address', async () => {
20
+ const budget = await loadFixture(
21
+ freshManagedBudget(defaultOptions, fixtures),
22
+ );
23
+ expect(
24
+ await budgetFromAddress(defaultOptions, budget.assertValidAddress()),
25
+ ).toBeInstanceOf(ManagedBudget);
26
+ });
27
+ });