@boostxyz/sdk 0.0.0-alpha.10

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 (242) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +7 -0
  3. package/dist/Actions/Action.cjs +2 -0
  4. package/dist/Actions/Action.cjs.map +1 -0
  5. package/dist/Actions/Action.d.ts +31 -0
  6. package/dist/Actions/Action.d.ts.map +1 -0
  7. package/dist/Actions/Action.js +29 -0
  8. package/dist/Actions/Action.js.map +1 -0
  9. package/dist/Actions/ContractAction.d.ts +370 -0
  10. package/dist/Actions/ContractAction.d.ts.map +1 -0
  11. package/dist/Actions/ERC721MintAction.d.ts +513 -0
  12. package/dist/Actions/ERC721MintAction.d.ts.map +1 -0
  13. package/dist/Actions/EventAction.cjs +2 -0
  14. package/dist/Actions/EventAction.cjs.map +1 -0
  15. package/dist/Actions/EventAction.d.ts +694 -0
  16. package/dist/Actions/EventAction.d.ts.map +1 -0
  17. package/dist/Actions/EventAction.js +491 -0
  18. package/dist/Actions/EventAction.js.map +1 -0
  19. package/dist/AllowLists/AllowList.cjs +2 -0
  20. package/dist/AllowLists/AllowList.cjs.map +1 -0
  21. package/dist/AllowLists/AllowList.d.ts +32 -0
  22. package/dist/AllowLists/AllowList.d.ts.map +1 -0
  23. package/dist/AllowLists/AllowList.js +30 -0
  24. package/dist/AllowLists/AllowList.js.map +1 -0
  25. package/dist/AllowLists/SimpleAllowList.cjs +2 -0
  26. package/dist/AllowLists/SimpleAllowList.cjs.map +1 -0
  27. package/dist/AllowLists/SimpleAllowList.d.ts +481 -0
  28. package/dist/AllowLists/SimpleAllowList.d.ts.map +1 -0
  29. package/dist/AllowLists/SimpleAllowList.js +154 -0
  30. package/dist/AllowLists/SimpleAllowList.js.map +1 -0
  31. package/dist/AllowLists/SimpleDenyList.cjs +2 -0
  32. package/dist/AllowLists/SimpleDenyList.cjs.map +1 -0
  33. package/dist/AllowLists/SimpleDenyList.d.ts +335 -0
  34. package/dist/AllowLists/SimpleDenyList.d.ts.map +1 -0
  35. package/dist/AllowLists/SimpleDenyList.js +115 -0
  36. package/dist/AllowLists/SimpleDenyList.js.map +1 -0
  37. package/dist/Auth/Auth.cjs +2 -0
  38. package/dist/Auth/Auth.cjs.map +1 -0
  39. package/dist/Auth/Auth.d.ts +10 -0
  40. package/dist/Auth/Auth.d.ts.map +1 -0
  41. package/dist/Auth/Auth.js +5 -0
  42. package/dist/Auth/Auth.js.map +1 -0
  43. package/dist/Auth/PassthroughAuth.cjs +2 -0
  44. package/dist/Auth/PassthroughAuth.cjs.map +1 -0
  45. package/dist/Auth/PassthroughAuth.d.ts +51 -0
  46. package/dist/Auth/PassthroughAuth.d.ts.map +1 -0
  47. package/dist/Auth/PassthroughAuth.js +39 -0
  48. package/dist/Auth/PassthroughAuth.js.map +1 -0
  49. package/dist/Boost.cjs +2 -0
  50. package/dist/Boost.cjs.map +1 -0
  51. package/dist/Boost.d.ts +234 -0
  52. package/dist/Boost.d.ts.map +1 -0
  53. package/dist/Boost.js +162 -0
  54. package/dist/Boost.js.map +1 -0
  55. package/dist/BoostCore.cjs +3 -0
  56. package/dist/BoostCore.cjs.map +1 -0
  57. package/dist/BoostCore.d.ts +498 -0
  58. package/dist/BoostCore.d.ts.map +1 -0
  59. package/dist/BoostCore.js +1153 -0
  60. package/dist/BoostCore.js.map +1 -0
  61. package/dist/BoostRegistry.cjs +2 -0
  62. package/dist/BoostRegistry.cjs.map +1 -0
  63. package/dist/BoostRegistry.d.ts +243 -0
  64. package/dist/BoostRegistry.d.ts.map +1 -0
  65. package/dist/BoostRegistry.js +262 -0
  66. package/dist/BoostRegistry.js.map +1 -0
  67. package/dist/Budgets/Budget.cjs +2 -0
  68. package/dist/Budgets/Budget.cjs.map +1 -0
  69. package/dist/Budgets/Budget.d.ts +31 -0
  70. package/dist/Budgets/Budget.d.ts.map +1 -0
  71. package/dist/Budgets/Budget.js +29 -0
  72. package/dist/Budgets/Budget.js.map +1 -0
  73. package/dist/Budgets/ManagedBudget.cjs +2 -0
  74. package/dist/Budgets/ManagedBudget.cjs.map +1 -0
  75. package/dist/Budgets/ManagedBudget.d.ts +1103 -0
  76. package/dist/Budgets/ManagedBudget.d.ts.map +1 -0
  77. package/dist/Budgets/ManagedBudget.js +516 -0
  78. package/dist/Budgets/ManagedBudget.js.map +1 -0
  79. package/dist/Budgets/SimpleBudget.d.ts +824 -0
  80. package/dist/Budgets/SimpleBudget.d.ts.map +1 -0
  81. package/dist/Budgets/VestingBudget.d.ts +778 -0
  82. package/dist/Budgets/VestingBudget.d.ts.map +1 -0
  83. package/dist/Deployable/Contract.cjs +2 -0
  84. package/dist/Deployable/Contract.cjs.map +1 -0
  85. package/dist/Deployable/Contract.d.ts +125 -0
  86. package/dist/Deployable/Contract.d.ts.map +1 -0
  87. package/dist/Deployable/Contract.js +150 -0
  88. package/dist/Deployable/Contract.js.map +1 -0
  89. package/dist/Deployable/Deployable.cjs +2 -0
  90. package/dist/Deployable/Deployable.cjs.map +1 -0
  91. package/dist/Deployable/Deployable.d.ts +161 -0
  92. package/dist/Deployable/Deployable.d.ts.map +1 -0
  93. package/dist/Deployable/Deployable.js +131 -0
  94. package/dist/Deployable/Deployable.js.map +1 -0
  95. package/dist/Deployable/DeployableTarget.cjs +2 -0
  96. package/dist/Deployable/DeployableTarget.cjs.map +1 -0
  97. package/dist/Deployable/DeployableTarget.d.ts +116 -0
  98. package/dist/Deployable/DeployableTarget.d.ts.map +1 -0
  99. package/dist/Deployable/DeployableTarget.js +132 -0
  100. package/dist/Deployable/DeployableTarget.js.map +1 -0
  101. package/dist/Incentives/AllowListIncentive.cjs +2 -0
  102. package/dist/Incentives/AllowListIncentive.cjs.map +1 -0
  103. package/dist/Incentives/AllowListIncentive.d.ts +513 -0
  104. package/dist/Incentives/AllowListIncentive.d.ts.map +1 -0
  105. package/dist/Incentives/AllowListIncentive.js +201 -0
  106. package/dist/Incentives/AllowListIncentive.js.map +1 -0
  107. package/dist/Incentives/CGDAIncentive.cjs +2 -0
  108. package/dist/Incentives/CGDAIncentive.cjs.map +1 -0
  109. package/dist/Incentives/CGDAIncentive.d.ts +644 -0
  110. package/dist/Incentives/CGDAIncentive.d.ts.map +1 -0
  111. package/dist/Incentives/CGDAIncentive.js +271 -0
  112. package/dist/Incentives/CGDAIncentive.js.map +1 -0
  113. package/dist/Incentives/ERC1155Incentive.d.ts +713 -0
  114. package/dist/Incentives/ERC1155Incentive.d.ts.map +1 -0
  115. package/dist/Incentives/ERC20Incentive.cjs +2 -0
  116. package/dist/Incentives/ERC20Incentive.cjs.map +1 -0
  117. package/dist/Incentives/ERC20Incentive.d.ts +666 -0
  118. package/dist/Incentives/ERC20Incentive.d.ts.map +1 -0
  119. package/dist/Incentives/ERC20Incentive.js +312 -0
  120. package/dist/Incentives/ERC20Incentive.js.map +1 -0
  121. package/dist/Incentives/ERC20VariableIncentive.d.ts +582 -0
  122. package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -0
  123. package/dist/Incentives/Incentive.cjs +2 -0
  124. package/dist/Incentives/Incentive.cjs.map +1 -0
  125. package/dist/Incentives/Incentive.d.ts +36 -0
  126. package/dist/Incentives/Incentive.d.ts.map +1 -0
  127. package/dist/Incentives/Incentive.js +299 -0
  128. package/dist/Incentives/Incentive.js.map +1 -0
  129. package/dist/Incentives/PointsIncentive.cjs +2 -0
  130. package/dist/Incentives/PointsIncentive.cjs.map +1 -0
  131. package/dist/Incentives/PointsIncentive.d.ts +659 -0
  132. package/dist/Incentives/PointsIncentive.d.ts.map +1 -0
  133. package/dist/Incentives/PointsIncentive.js +215 -0
  134. package/dist/Incentives/PointsIncentive.js.map +1 -0
  135. package/dist/Validators/SignerValidator.cjs +2 -0
  136. package/dist/Validators/SignerValidator.cjs.map +1 -0
  137. package/dist/Validators/SignerValidator.d.ts +745 -0
  138. package/dist/Validators/SignerValidator.d.ts.map +1 -0
  139. package/dist/Validators/SignerValidator.js +293 -0
  140. package/dist/Validators/SignerValidator.js.map +1 -0
  141. package/dist/Validators/Validator.cjs +2 -0
  142. package/dist/Validators/Validator.cjs.map +1 -0
  143. package/dist/Validators/Validator.d.ts +31 -0
  144. package/dist/Validators/Validator.d.ts.map +1 -0
  145. package/dist/Validators/Validator.js +27 -0
  146. package/dist/Validators/Validator.js.map +1 -0
  147. package/dist/claiming.cjs +2 -0
  148. package/dist/claiming.cjs.map +1 -0
  149. package/dist/claiming.d.ts +43 -0
  150. package/dist/claiming.d.ts.map +1 -0
  151. package/dist/claiming.js +17 -0
  152. package/dist/claiming.js.map +1 -0
  153. package/dist/componentInterfaces-CKCBwG16.cjs +2 -0
  154. package/dist/componentInterfaces-CKCBwG16.cjs.map +1 -0
  155. package/dist/componentInterfaces-DYkaxBda.js +13 -0
  156. package/dist/componentInterfaces-DYkaxBda.js.map +1 -0
  157. package/dist/errors.cjs +2 -0
  158. package/dist/errors.cjs.map +1 -0
  159. package/dist/errors.d.ts +441 -0
  160. package/dist/errors.d.ts.map +1 -0
  161. package/dist/errors.js +262 -0
  162. package/dist/errors.js.map +1 -0
  163. package/dist/generated-BDeDiaCK.js +4625 -0
  164. package/dist/generated-BDeDiaCK.js.map +1 -0
  165. package/dist/generated-wKBNvm48.cjs +3 -0
  166. package/dist/generated-wKBNvm48.cjs.map +1 -0
  167. package/dist/index.cjs +2 -0
  168. package/dist/index.cjs.map +1 -0
  169. package/dist/index.d.ts +25 -0
  170. package/dist/index.d.ts.map +1 -0
  171. package/dist/index.js +113 -0
  172. package/dist/index.js.map +1 -0
  173. package/dist/transfers.cjs +2 -0
  174. package/dist/transfers.cjs.map +1 -0
  175. package/dist/transfers.d.ts +198 -0
  176. package/dist/transfers.d.ts.map +1 -0
  177. package/dist/transfers.js +84 -0
  178. package/dist/transfers.js.map +1 -0
  179. package/dist/utils.cjs +2 -0
  180. package/dist/utils.cjs.map +1 -0
  181. package/dist/utils.d.ts +116 -0
  182. package/dist/utils.d.ts.map +1 -0
  183. package/dist/utils.js +30 -0
  184. package/dist/utils.js.map +1 -0
  185. package/package.json +211 -0
  186. package/src/Actions/Action.test.ts +75 -0
  187. package/src/Actions/Action.ts +61 -0
  188. package/src/Actions/ContractAction.test.ts +197 -0
  189. package/src/Actions/ContractAction.ts +301 -0
  190. package/src/Actions/ERC721MintAction.test.ts +112 -0
  191. package/src/Actions/ERC721MintAction.ts +292 -0
  192. package/src/Actions/EventAction.test.ts +205 -0
  193. package/src/Actions/EventAction.ts +811 -0
  194. package/src/AllowLists/AllowList.test.ts +64 -0
  195. package/src/AllowLists/AllowList.ts +60 -0
  196. package/src/AllowLists/SimpleAllowList.test.ts +52 -0
  197. package/src/AllowLists/SimpleAllowList.ts +284 -0
  198. package/src/AllowLists/SimpleDenyList.test.ts +52 -0
  199. package/src/AllowLists/SimpleDenyList.ts +227 -0
  200. package/src/Auth/Auth.ts +11 -0
  201. package/src/Auth/PassthroughAuth.test.ts +12 -0
  202. package/src/Auth/PassthroughAuth.ts +80 -0
  203. package/src/Boost.ts +290 -0
  204. package/src/BoostCore.test.ts +773 -0
  205. package/src/BoostCore.ts +1261 -0
  206. package/src/BoostRegistry.ts +467 -0
  207. package/src/Budgets/Budget.test.ts +27 -0
  208. package/src/Budgets/Budget.ts +61 -0
  209. package/src/Budgets/ManagedBudget.test.ts +154 -0
  210. package/src/Budgets/ManagedBudget.ts +796 -0
  211. package/src/Budgets/SimpleBudget.test.ts +152 -0
  212. package/src/Budgets/SimpleBudget.ts +564 -0
  213. package/src/Budgets/VestingBudget.test.ts +123 -0
  214. package/src/Budgets/VestingBudget.ts +602 -0
  215. package/src/Deployable/Contract.ts +229 -0
  216. package/src/Deployable/Deployable.ts +250 -0
  217. package/src/Deployable/DeployableTarget.ts +223 -0
  218. package/src/Incentives/AllowListIncentive.test.ts +143 -0
  219. package/src/Incentives/AllowListIncentive.ts +334 -0
  220. package/src/Incentives/CGDAIncentive.test.ts +132 -0
  221. package/src/Incentives/CGDAIncentive.ts +468 -0
  222. package/src/Incentives/ERC1155Incentive.test.ts +87 -0
  223. package/src/Incentives/ERC1155Incentive.ts +466 -0
  224. package/src/Incentives/ERC20Incentive.test.ts +130 -0
  225. package/src/Incentives/ERC20Incentive.ts +482 -0
  226. package/src/Incentives/ERC20VariableIncentive.test.ts +136 -0
  227. package/src/Incentives/ERC20VariableIncentive.ts +420 -0
  228. package/src/Incentives/Incentive.test.ts +92 -0
  229. package/src/Incentives/Incentive.ts +85 -0
  230. package/src/Incentives/PointsIncentive.test.ts +139 -0
  231. package/src/Incentives/PointsIncentive.ts +365 -0
  232. package/src/Validators/SignerValidator.test.ts +159 -0
  233. package/src/Validators/SignerValidator.ts +681 -0
  234. package/src/Validators/Validator.test.ts +21 -0
  235. package/src/Validators/Validator.ts +55 -0
  236. package/src/claiming.ts +56 -0
  237. package/src/errors.ts +542 -0
  238. package/src/index.test.ts +40 -0
  239. package/src/index.ts +53 -0
  240. package/src/transfers.ts +284 -0
  241. package/src/utils.test.ts +44 -0
  242. package/src/utils.ts +198 -0
@@ -0,0 +1,467 @@
1
+ import {
2
+ boostRegistryAbi,
3
+ readBoostRegistryGetBaseImplementation,
4
+ readBoostRegistryGetCloneIdentifier,
5
+ readBoostRegistryGetClones,
6
+ simulateBoostRegistryDeployClone,
7
+ simulateBoostRegistryRegister,
8
+ writeBoostRegistryDeployClone,
9
+ writeBoostRegistryRegister,
10
+ } from '@boostxyz/evm';
11
+ import { bytecode } from '@boostxyz/evm/artifacts/contracts/BoostRegistry.sol/BoostRegistry.json';
12
+ import {
13
+ type Address,
14
+ type ContractEventName,
15
+ type Hex,
16
+ isAddress,
17
+ } from 'viem';
18
+ import {
19
+ Deployable,
20
+ type DeployableOptions,
21
+ type GenericDeployableParams,
22
+ } from './Deployable/Deployable';
23
+ import type { DeployableTarget } from './Deployable/DeployableTarget';
24
+ import type {
25
+ GenericLog,
26
+ HashAndSimulatedResult,
27
+ ReadParams,
28
+ RegistryType,
29
+ WriteParams,
30
+ } from './utils';
31
+
32
+ export { boostRegistryAbi };
33
+
34
+ /**
35
+ * The fixed address for the Boost Registry.
36
+ * By default, `new BoostRegistry` will use this address if not otherwise provided.
37
+ *
38
+ * @type {Address}
39
+ */
40
+ export const BOOST_REGISTRY_ADDRESS: Address = import.meta.env
41
+ .VITE_BOOST_REGISTRY_ADDRESS;
42
+
43
+ /**
44
+ * A record of `BoostRegistry` event names to `AbiEvent` objects for use with `getLogs`
45
+ *
46
+ * @export
47
+ * @typedef {BoostRegistryLog}
48
+ * @template {ContractEventName<typeof boostRegistryAbi>} [event=ContractEventName<
49
+ * typeof boostRegistryAbi
50
+ * >]
51
+ */
52
+ export type BoostRegistryLog<
53
+ event extends ContractEventName<typeof boostRegistryAbi> = ContractEventName<
54
+ typeof boostRegistryAbi
55
+ >,
56
+ > = GenericLog<typeof boostRegistryAbi, event>;
57
+
58
+ /**
59
+ * Instantiation options for a previously deployed Boost Registry
60
+ *
61
+ * @export
62
+ * @interface BoostRegistryDeployedOptions
63
+ * @typedef {BoostRegistryDeployedOptions}
64
+ * @extends {DeployableOptions}
65
+ */
66
+ export interface BoostRegistryDeployedOptions extends DeployableOptions {
67
+ /**
68
+ * The address for a Boost Registry, if different than `BOOST_REGISTRY_ADDRESS`
69
+ *
70
+ * @type {?Address}
71
+ */
72
+ address?: Address;
73
+ }
74
+
75
+ /**
76
+ * A typeguard to determine if instantiation is using a custom address.
77
+ *
78
+ * @param {*} opts
79
+ * @returns {opts is BoostRegistryDeployedOptions}
80
+ */
81
+ function isBoostRegistryDeployed(
82
+ // biome-ignore lint/suspicious/noExplicitAny: type guard
83
+ opts: any,
84
+ ): opts is BoostRegistryDeployedOptions {
85
+ return opts.address && isAddress(opts.address);
86
+ }
87
+
88
+ /**
89
+ * 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.
90
+ *
91
+ * @export
92
+ * @interface BoostRegistryOptionsWithPayload
93
+ * @typedef {BoostRegistryOptionsWithPayload}
94
+ * @extends {DeployableOptions}
95
+ */
96
+ export interface BoostRegistryOptionsWithPayload extends DeployableOptions {
97
+ /**
98
+ *
99
+ * @type {null}
100
+ */
101
+ address: null;
102
+ }
103
+
104
+ /**
105
+ * A typeguard to determine if the user is intending to deploy a new Boost Registry before usage
106
+ *
107
+ * @param {*} opts
108
+ * @returns {opts is BoostRegistryOptionsWithPayload}
109
+ */
110
+ function isBoostRegistryDeployable(
111
+ // biome-ignore lint/suspicious/noExplicitAny: type guard
112
+ opts: any,
113
+ ): opts is BoostRegistryOptionsWithPayload {
114
+ return opts.address === null;
115
+ }
116
+
117
+ /**
118
+ * Instantiation options for a Boost Registry.
119
+ *
120
+ * @example
121
+ * To target Boost's Registry, omit the address field.
122
+ * Otherwise, supply a custom address to a previously deployed custom Boost Registry.
123
+ * You can also pass `{ address: null }` if you are intending to deploy a new Boost Registry.
124
+ * ```ts
125
+ * let registry = new BoostRegistry({ config, account })
126
+ * // or
127
+ * registry = new BoostRegistry({ config, account, address: CUSTOM_ADDRESS })
128
+ * // or
129
+ * registry = new BoostRegistry({ config, account, address: null })
130
+ * await registry.deploy()
131
+ * ```
132
+ *
133
+ * @export
134
+ * @typedef {BoostRegistryConfig}
135
+ */
136
+ export type BoostRegistryConfig =
137
+ | BoostRegistryDeployedOptions
138
+ | BoostRegistryOptionsWithPayload;
139
+
140
+ /**
141
+ * Constructs a new Boost Registry. A registry for base implementations and cloned instances.
142
+ * This contract is used to register base implementations and deploy new instances of those implementations for use within the Boost protocol.
143
+ *
144
+ * @see {@link BoostRegistryConfig}
145
+ * @export
146
+ * @class BoostRegistry
147
+ * @typedef {BoostRegistry}
148
+ * @extends {Deployable<never[]>}
149
+ */
150
+ export class BoostRegistry extends Deployable<
151
+ never[],
152
+ typeof boostRegistryAbi
153
+ > {
154
+ /**
155
+ * Creates an instance of BoostRegistry.
156
+ *
157
+ * @see {@link BoostRegistryConfig}
158
+ * @constructor
159
+ * @param {BoostRegistryConfig} param0
160
+ * @param {Config} param0.config - [Wagmi Configuration](https://wagmi.sh/core/api/createConfig)
161
+ * @param {?Account} [param0.account] - [Viem Local Account](https://viem.sh/docs/accounts/local)
162
+ * @param {({ address?: Address; } | {})} param0....options
163
+ */
164
+ constructor({ config, account, ...options }: BoostRegistryConfig) {
165
+ if (isBoostRegistryDeployed(options) && options.address) {
166
+ super({ account, config }, options.address);
167
+ } else if (isBoostRegistryDeployable(options)) {
168
+ super({ account, config }, []);
169
+ } else {
170
+ super({ account, config }, BOOST_REGISTRY_ADDRESS);
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Register a new base implementation of a given type
176
+ *
177
+ * @public
178
+ * @async
179
+ * @param {RegistryType} registryType - The base type for the implementation
180
+ * @param {string} name - A name for the implementation (must be unique within the given type)
181
+ * @param {Address} implementation - The address of the implementation contract
182
+ * @param {?WriteParams<typeof boostRegistryAbi, 'register'>} [params] - Optional params to provide the underlying Viem contract call
183
+ * @returns {unknown}
184
+ * @example
185
+ * ```ts
186
+ * await registry.register(ContractAction.registryType, 'ContractAction', ContractAction.base)
187
+ * ```
188
+ */
189
+ public async register(
190
+ registryType: RegistryType,
191
+ name: string,
192
+ implementation: Address,
193
+ params?: WriteParams<typeof boostRegistryAbi, 'register'>,
194
+ ) {
195
+ return await this.awaitResult(
196
+ this.registerRaw(registryType, name, implementation, params),
197
+ );
198
+ }
199
+
200
+ /**
201
+ * @see {@link register}
202
+ * @public
203
+ * @async
204
+ * @param {RegistryType} registryType
205
+ * @param {string} name
206
+ * @param {Address} implementation
207
+ * @param {?WriteParams<typeof boostRegistryAbi, 'register'>} [params]
208
+ * @returns {unknown}
209
+ */
210
+ public async registerRaw(
211
+ registryType: RegistryType,
212
+ name: string,
213
+ implementation: Address,
214
+ params?: WriteParams<typeof boostRegistryAbi, 'register'>,
215
+ ) {
216
+ const { request, result } = await simulateBoostRegistryRegister(
217
+ this._config,
218
+ {
219
+ address: this.assertValidAddress(),
220
+ args: [registryType, name, implementation],
221
+ ...this.optionallyAttachAccount(),
222
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
223
+ ...(params as any),
224
+ },
225
+ );
226
+ const hash = await writeBoostRegistryRegister(this._config, request);
227
+ return { hash, result };
228
+ }
229
+
230
+ /**
231
+ * Initialize a new instance of a registered base implementation, returning the provided target with a new address set on it.
232
+ * This method is the same as `clone`, but serves to make its function more obvious as to why you'd need to use it.
233
+ *
234
+ * @public
235
+ * @async
236
+ * @template {DeployableTarget} Target
237
+ * @param {string} displayName - The display name for the clone
238
+ * @param {Target} target - An instance of a target contract to clone and initialize
239
+ * @param {?WriteParams<typeof boostRegistryAbi, 'deployClone'>} [params]
240
+ * @returns {Target} - The provided instance, but with a new address attached.
241
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
242
+ */
243
+ public initialize<Target extends DeployableTarget<any, any>>(
244
+ displayName: string,
245
+ target: Target,
246
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
247
+ ): Promise<Target> {
248
+ return this.clone(displayName, target, params);
249
+ }
250
+
251
+ /**
252
+ * Deploy a new instance of a registered base implementation, returning the provided target with a new address set on it.
253
+ *
254
+ * @public
255
+ * @async
256
+ * @template {DeployableTarget} Target
257
+ * @param {string} displayName - The display name for the clone
258
+ * @param {Target} target - An instance of a target contract to clone and initialize
259
+ * @param {?WriteParams<typeof boostRegistryAbi, 'deployClone'>} [params]
260
+ * @returns {Target} - The provided instance, but with a new address attached.
261
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
262
+ */
263
+ public async clone<Target extends DeployableTarget<any, any>>(
264
+ displayName: string,
265
+ target: Target,
266
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
267
+ ): Promise<Target> {
268
+ const instance = await this.deployClone(displayName, target, params);
269
+ return target.at(instance);
270
+ }
271
+
272
+ /**
273
+ *
274
+ * @see {@link clone}
275
+ * @public
276
+ * @async
277
+ * @template {DeployableTarget} Target
278
+ * @param {string} displayName
279
+ * @param {Target} target
280
+ * @param {?WriteParams<typeof boostRegistryAbi, 'deployClone'>} [params]
281
+ * @returns {Target}
282
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
283
+ */
284
+ public async deployClone<Target extends DeployableTarget<any, any>>(
285
+ displayName: string,
286
+ target: Target,
287
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
288
+ ): Promise<Address> {
289
+ return await this.awaitResult(
290
+ this.deployCloneRaw(displayName, target, params),
291
+ );
292
+ }
293
+
294
+ /**
295
+ * @see {@link clone}
296
+ * @public
297
+ * @async
298
+ * @param {string} displayName
299
+ * @param {DeployableTarget} target
300
+ * @param {?WriteParams<typeof boostRegistryAbi, 'deployClone'>} [params]
301
+ * @returns {unknown} - The transaction hash
302
+ * biome-ignore lint/suspicious/noExplicitAny: any deployable target will suffice
303
+ */
304
+ public async deployCloneRaw<Target extends DeployableTarget<any, any>>(
305
+ displayName: string,
306
+ target: Target,
307
+ params?: WriteParams<typeof boostRegistryAbi, 'deployClone'>,
308
+ ): Promise<HashAndSimulatedResult<Address>> {
309
+ const payload = target.buildParameters(undefined, {
310
+ config: this._config,
311
+ account: this._account,
312
+ });
313
+ const { request, result } = await simulateBoostRegistryDeployClone(
314
+ this._config,
315
+ {
316
+ address: this.assertValidAddress(),
317
+ args: [target.registryType, target.base, displayName, payload.args[0]],
318
+ ...this.optionallyAttachAccount(),
319
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
320
+ ...(params as any),
321
+ },
322
+ );
323
+ const hash = await writeBoostRegistryDeployClone(this._config, request);
324
+ return { hash, result };
325
+ }
326
+
327
+ /**
328
+ * Get the address of a registered base implementation.
329
+ * This function will revert if the implementation is not registered
330
+ *
331
+ * @public
332
+ * @async
333
+ * @param {Hex} identifier - The unique identifier for the implementation (see {getIdentifier})
334
+ * @param {?ReadParams<typeof boostRegistryAbi, 'getBaseImplementation'>} [params]
335
+ * @returns {unknown} - The address of the implementation
336
+ */
337
+ public async getBaseImplementation(
338
+ identifier: Hex,
339
+ params?: ReadParams<typeof boostRegistryAbi, 'getBaseImplementation'>,
340
+ ) {
341
+ return await readBoostRegistryGetBaseImplementation(this._config, {
342
+ address: this.assertValidAddress(),
343
+ args: [identifier],
344
+ ...this.optionallyAttachAccount(),
345
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
346
+ ...(params as any),
347
+ });
348
+ }
349
+
350
+ /**
351
+ * Get the address of a deployed clone by its identifier
352
+ *
353
+ * @public
354
+ * @async
355
+ * @param {Hex} identifier - The unique identifier for the deployed clone (see {getCloneIdentifier})
356
+ * @param {?ReadParams<typeof boostRegistryAbi, 'getClone'>} [params]
357
+ * @returns {Promise<Address>} - The address of the deployed clone
358
+ */
359
+ public async getClone(
360
+ identifier: Hex,
361
+ params?: ReadParams<typeof boostRegistryAbi, 'getClone'>,
362
+ ) {
363
+ return await readBoostRegistryGetBaseImplementation(this._config, {
364
+ address: this.assertValidAddress(),
365
+ args: [identifier],
366
+ ...this.optionallyAttachAccount(),
367
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
368
+ ...(params as any),
369
+ });
370
+ }
371
+
372
+ /**
373
+ * Get the list of identifiers of deployed clones for a given deployer
374
+ *
375
+ * @public
376
+ * @async
377
+ * @param {Address} deployer - The address of the deployer
378
+ * @param {?ReadParams<typeof boostRegistryAbi, 'getClones'>} [params]
379
+ * @returns {Promise<Hex[]>} - The list of deployed clones for the given deployer
380
+ */
381
+ public async getClones(
382
+ deployer: Address,
383
+ params?: ReadParams<typeof boostRegistryAbi, 'getClones'>,
384
+ ) {
385
+ return await readBoostRegistryGetClones(this._config, {
386
+ address: this.assertValidAddress(),
387
+ args: [deployer],
388
+ ...this.optionallyAttachAccount(),
389
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
390
+ ...(params as any),
391
+ });
392
+ }
393
+
394
+ /**
395
+ * Build the identifier for a clone of a base implementation
396
+ *
397
+ * @public
398
+ * @async
399
+ * @param {RegistryType} registryType - The base type for the implementation
400
+ * @param {Address} base - The address of the base implementation
401
+ * @param {Address} deployer - The address of the deployer
402
+ * @param {string} displayName - The display name of the clone
403
+ * @param {?ReadParams<typeof boostRegistryAbi, 'getCloneIdentifier'>} [params]
404
+ * @returns {Promise<Hex>} - The unique identifier for the clone
405
+ */
406
+ public async getCloneIdentifier(
407
+ registryType: RegistryType,
408
+ base: Address,
409
+ deployer: Address,
410
+ displayName: string,
411
+ params?: ReadParams<typeof boostRegistryAbi, 'getCloneIdentifier'>,
412
+ ) {
413
+ return await readBoostRegistryGetCloneIdentifier(this._config, {
414
+ address: this.assertValidAddress(),
415
+ args: [registryType, base, deployer, displayName],
416
+ ...this.optionallyAttachAccount(),
417
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
418
+ ...(params as any),
419
+ });
420
+ }
421
+
422
+ /**
423
+ * Build the identifier for a base implementation
424
+ *
425
+ * @public
426
+ * @async
427
+ * @param {RegistryType} registryType - The base type for the implementation
428
+ * @param {string} displayName - The name of the implementation
429
+ * @param {?ReadParams<typeof boostRegistryAbi, 'getIdentifier'>} [params]
430
+ * @returns {Promise<Hex>} - The unique identifier for the implementation
431
+ */
432
+ public async getIdentifier(
433
+ registryType: RegistryType,
434
+ displayName: string,
435
+ params?: ReadParams<typeof boostRegistryAbi, 'getIdentifier'>,
436
+ ) {
437
+ return await readBoostRegistryGetCloneIdentifier(this._config, {
438
+ address: this.assertValidAddress(),
439
+ args: [registryType, displayName],
440
+ ...this.optionallyAttachAccount(),
441
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
442
+ ...(params as any),
443
+ });
444
+ }
445
+
446
+ /**
447
+ * @inheritdoc
448
+ *
449
+ * @public
450
+ * @param {?never[]} [_payload]
451
+ * @param {?DeployableOptions} [_options]
452
+ * @returns {GenericDeployableParams}
453
+ */
454
+ public override buildParameters(
455
+ _payload?: never[],
456
+ _options?: DeployableOptions,
457
+ ): GenericDeployableParams {
458
+ const [, options] = this.validateDeploymentConfig([], _options);
459
+ return {
460
+ abi: boostRegistryAbi,
461
+ bytecode: bytecode as Hex,
462
+ // biome-ignore lint/suspicious/noExplicitAny: Registry doesn't construct or initialize
463
+ args: [] as any,
464
+ ...this.optionallyAttachAccount(options.account),
465
+ };
466
+ }
467
+ }
@@ -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 '../../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);
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
+ });
@@ -0,0 +1,61 @@
1
+ import { aBudgetAbi } from '@boostxyz/evm';
2
+ import { AManagedBudget } from '@boostxyz/evm/deploys/componentInterfaces.json';
3
+ import { readContract } from '@wagmi/core';
4
+ import type { Address, Hex } from 'viem';
5
+ import type { DeployableOptions } from '../Deployable/Deployable';
6
+ import { InvalidComponentInterfaceError } from '../errors';
7
+ import { ManagedBudget } from './ManagedBudget';
8
+
9
+ export {
10
+ // SimpleBudget,
11
+ // VestingBudget,
12
+ ManagedBudget,
13
+ };
14
+
15
+ /**
16
+ * A union type representing all valid protocol Budget implementations
17
+ *
18
+ * @export
19
+ * @typedef {Budget}
20
+ */
21
+ export type Budget = ManagedBudget; // | SimpleBudget | VestingBudget
22
+
23
+ /**
24
+ * A map of Budget component interfaces to their constructors.
25
+ *
26
+ * @type {{ "0xa0109882": typeof ManagedBudget; }}
27
+ */
28
+ export const BudgetByComponentInterface = {
29
+ // ['0x64683da1']: VestingBudget,
30
+ // ['0x2929d19c']: SimpleBudget,
31
+ [AManagedBudget as Hex]: ManagedBudget,
32
+ };
33
+
34
+ /**
35
+ * A function that will read a contract's component interface using `getComponentInterface` and return the correct instantiated instance.
36
+ *
37
+ * @export
38
+ * @async
39
+ * @param {DeployableOptions} options
40
+ * @param {Address} address
41
+ * @returns {Promise<ManagedBudget>}
42
+ * @throws {@link InvalidComponentInterfaceError}
43
+ */
44
+ export async function budgetFromAddress(
45
+ options: DeployableOptions,
46
+ address: Address,
47
+ ) {
48
+ const interfaceId = (await readContract(options.config, {
49
+ abi: aBudgetAbi,
50
+ functionName: 'getComponentInterface',
51
+ address,
52
+ })) as keyof typeof BudgetByComponentInterface;
53
+ const Ctor = BudgetByComponentInterface[interfaceId];
54
+ if (!Ctor) {
55
+ throw new InvalidComponentInterfaceError(
56
+ Object.keys(BudgetByComponentInterface) as Hex[],
57
+ interfaceId as Hex,
58
+ );
59
+ }
60
+ return new Ctor(options, address);
61
+ }
@@ -0,0 +1,154 @@
1
+ import { writeMockErc1155SetApprovalForAll } from '@boostxyz/evm';
2
+ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
3
+ import { isAddress, parseEther, zeroAddress } from 'viem';
4
+ import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
5
+ import type { MockERC20 } from '../../test/MockERC20';
6
+ import type { MockERC1155 } from '../../test/MockERC1155';
7
+ import {
8
+ type Fixtures,
9
+ defaultOptions,
10
+ deployFixtures,
11
+ freshBudget,
12
+ freshManagedBudget,
13
+ fundErc20,
14
+ fundErc1155,
15
+ fundManagedBudget,
16
+ } from '../../test/helpers';
17
+ import { testAccount } from '../../test/viem';
18
+ import { ManagedBudget } from './ManagedBudget';
19
+
20
+ let fixtures: Fixtures,
21
+ budget: ManagedBudget,
22
+ erc20: MockERC20,
23
+ erc1155: MockERC1155;
24
+
25
+ beforeAll(async () => {
26
+ fixtures = await loadFixture(deployFixtures);
27
+ });
28
+
29
+ describe('ManagedBudget', () => {
30
+ test('can successfully be deployed', async () => {
31
+ const action = new ManagedBudget(defaultOptions, {
32
+ owner: testAccount.address,
33
+ authorized: [],
34
+ roles: [],
35
+ });
36
+ await action.deploy();
37
+ expect(isAddress(action.assertValidAddress())).toBe(true);
38
+ });
39
+
40
+ test('can be owned', async () => {
41
+ const budget = await loadFixture(freshBudget(defaultOptions, fixtures));
42
+ expect(await budget.owner()).toBe(defaultOptions.account.address);
43
+ });
44
+
45
+ test('can have authorized users', async () => {
46
+ const budget = await loadFixture(freshBudget(defaultOptions, fixtures));
47
+ expect(await budget.isAuthorized(defaultOptions.account.address)).toBe(
48
+ true,
49
+ );
50
+ expect(await budget.isAuthorized(zeroAddress)).toBe(false);
51
+ });
52
+
53
+ test('can have no initial balance', async () => {
54
+ const budget = await loadFixture(freshBudget(defaultOptions, fixtures));
55
+ expect(await budget.available(zeroAddress)).toBe(0n);
56
+ });
57
+
58
+ describe('can allocate', () => {
59
+ beforeEach(async () => {
60
+ budget = await loadFixture(freshManagedBudget(defaultOptions, fixtures));
61
+ erc20 = await loadFixture(fundErc20(defaultOptions));
62
+ erc1155 = await loadFixture(fundErc1155(defaultOptions));
63
+ });
64
+
65
+ test('native assets', async () => {
66
+ await budget.allocate(
67
+ {
68
+ amount: parseEther('1.0'),
69
+ asset: zeroAddress,
70
+ target: defaultOptions.account.address,
71
+ },
72
+ {
73
+ value: parseEther('1.0'),
74
+ },
75
+ );
76
+ expect(await budget.available(zeroAddress)).toBe(parseEther('1.0'));
77
+ });
78
+
79
+ test('erc20', async () => {
80
+ await erc20.approve(budget.assertValidAddress(), parseEther('100'));
81
+ await budget.allocate({
82
+ amount: parseEther('100'),
83
+ asset: erc20.assertValidAddress(),
84
+ target: defaultOptions.account.address,
85
+ });
86
+ expect(await budget.available(erc20.assertValidAddress())).toBe(
87
+ parseEther('100'),
88
+ );
89
+ });
90
+
91
+ test('erc1155', async () => {
92
+ await writeMockErc1155SetApprovalForAll(defaultOptions.config, {
93
+ args: [budget.assertValidAddress(), true],
94
+ address: erc1155.assertValidAddress(),
95
+ account: defaultOptions.account,
96
+ });
97
+ await budget.allocate({
98
+ tokenId: 1n,
99
+ amount: 100n,
100
+ asset: erc1155.assertValidAddress(),
101
+ target: defaultOptions.account.address,
102
+ });
103
+ expect(await budget.available(erc1155.assertValidAddress(), 1n)).toBe(
104
+ 100n,
105
+ );
106
+ });
107
+ });
108
+
109
+ describe('can disburse', () => {
110
+ beforeEach(async () => {
111
+ const budgetFixtures = await loadFixture(
112
+ fundManagedBudget(defaultOptions, fixtures),
113
+ );
114
+ budget = budgetFixtures.budget as ManagedBudget;
115
+ erc20 = budgetFixtures.erc20;
116
+ erc1155 = budgetFixtures.erc1155;
117
+ });
118
+
119
+ test('native assets', async () => {
120
+ await budget.disburse({
121
+ amount: parseEther('1.0'),
122
+ asset: zeroAddress,
123
+ target: defaultOptions.account.address,
124
+ });
125
+
126
+ expect(await budget.available(zeroAddress)).toBe(0n);
127
+ });
128
+
129
+ test('erc20 assets', async () => {
130
+ await budget.disburse({
131
+ amount: parseEther('10'),
132
+ asset: erc20.assertValidAddress(),
133
+ target: defaultOptions.account.address,
134
+ });
135
+
136
+ expect(await budget.available(erc20.assertValidAddress())).toBe(
137
+ parseEther('90'),
138
+ );
139
+ });
140
+
141
+ test('erc1155 assets', async () => {
142
+ await budget.disburse({
143
+ tokenId: 1n,
144
+ amount: 5n,
145
+ asset: erc1155.assertValidAddress(),
146
+ target: defaultOptions.account.address,
147
+ });
148
+
149
+ expect(await budget.available(erc1155.assertValidAddress(), 1n)).to.equal(
150
+ 95n,
151
+ );
152
+ });
153
+ });
154
+ });