@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,773 @@
1
+ import { loadFixture } from '@nomicfoundation/hardhat-toolbox-viem/network-helpers';
2
+ import { parseEther, zeroAddress } 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
+ fundBudget,
10
+ makeMockEventActionPayload,
11
+ } from '../test/helpers';
12
+ import { ContractAction } from './Actions/ContractAction';
13
+ import { BoostCore } from './BoostCore';
14
+ import type { ERC20Incentive } from './Incentives/ERC20Incentive';
15
+ import { ERC1155StrategyType } from './Incentives/ERC1155Incentive';
16
+ import { StrategyType } from './claiming';
17
+ import { IncentiveNotCloneableError } from './errors';
18
+ import { bytes4 } from './utils';
19
+
20
+ let fixtures: Fixtures, budgets: BudgetFixtures;
21
+
22
+ describe('BoostCore', () => {
23
+ beforeAll(async () => {
24
+ fixtures = await loadFixture(deployFixtures);
25
+ });
26
+ beforeEach(async () => {
27
+ budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
28
+ });
29
+
30
+ test('can get the total number of boosts', async () => {
31
+ const { core } = fixtures;
32
+ const client = new BoostCore({
33
+ ...defaultOptions,
34
+ address: core.assertValidAddress(),
35
+ });
36
+
37
+ const { budget, erc20 } = budgets;
38
+ await client.createBoost({
39
+ protocolFee: 1n,
40
+ referralFee: 2n,
41
+ maxParticipants: 100n,
42
+ budget: budget,
43
+ action: core.EventAction(
44
+ makeMockEventActionPayload(
45
+ core.assertValidAddress(),
46
+ erc20.assertValidAddress(),
47
+ ),
48
+ ),
49
+ validator: core.SignerValidator({
50
+ signers: [defaultOptions.account.address],
51
+ validatorCaller: defaultOptions.account.address,
52
+ }),
53
+ allowList: core.SimpleAllowList({
54
+ owner: defaultOptions.account.address,
55
+ allowed: [defaultOptions.account.address],
56
+ }),
57
+ incentives: [
58
+ core.ERC20Incentive({
59
+ asset: erc20.assertValidAddress(),
60
+ reward: parseEther('1'),
61
+ limit: 100n,
62
+ strategy: StrategyType.POOL,
63
+ }),
64
+ ],
65
+ });
66
+ expect(await client.getBoostCount()).toBe(1n);
67
+ });
68
+
69
+ test('can successfully create a boost using all base contract implementations', async () => {
70
+ const { core } = fixtures;
71
+ const client = new BoostCore({
72
+ ...defaultOptions,
73
+ address: core.assertValidAddress(),
74
+ });
75
+ const { budget, erc20 } = budgets;
76
+ const boost = await client.createBoost({
77
+ protocolFee: 1n,
78
+ referralFee: 2n,
79
+ maxParticipants: 100n,
80
+ budget: budget,
81
+ action: core.EventAction(
82
+ makeMockEventActionPayload(
83
+ core.assertValidAddress(),
84
+ erc20.assertValidAddress(),
85
+ ),
86
+ ),
87
+ validator: core.SignerValidator({
88
+ signers: [defaultOptions.account.address],
89
+ validatorCaller: defaultOptions.account.address,
90
+ }),
91
+ allowList: core.SimpleAllowList({
92
+ owner: defaultOptions.account.address,
93
+ allowed: [defaultOptions.account.address],
94
+ }),
95
+ incentives: [
96
+ core.ERC20Incentive({
97
+ asset: erc20.assertValidAddress(),
98
+ reward: parseEther('1'),
99
+ limit: 100n,
100
+ strategy: StrategyType.POOL,
101
+ }),
102
+ ],
103
+ });
104
+ const onChainBoost = await client.readBoost(boost.id);
105
+
106
+ expect(boost.owner).toBe(onChainBoost.owner);
107
+ expect(boost.protocolFee).toBe(onChainBoost.protocolFee);
108
+ expect(boost.referralFee).toBe(onChainBoost.referralFee);
109
+ expect(boost.maxParticipants).toBe(onChainBoost.maxParticipants);
110
+
111
+ expect(boost.action.address).toBe(onChainBoost.action);
112
+ // just get some type safety here
113
+ if (boost.action instanceof ContractAction === false) return;
114
+ expect(await boost.action.chainId()).toBe(BigInt(31_337));
115
+ expect((await boost.action.target()).toLowerCase()).toBe(
116
+ core.assertValidAddress().toLowerCase(),
117
+ );
118
+ expect(await boost.action.selector()).toBe('0xdeadbeef');
119
+ expect(await boost.action.value()).toBe(0n);
120
+
121
+ expect(boost.validator.address?.toLowerCase()).toBe(
122
+ onChainBoost.validator.toLowerCase(),
123
+ );
124
+ expect(await boost.validator.signers(defaultOptions.account.address)).toBe(
125
+ true,
126
+ );
127
+
128
+ expect(boost.allowList.address?.toLowerCase()).toBe(
129
+ onChainBoost.allowList.toLowerCase(),
130
+ );
131
+ expect(
132
+ await boost.allowList.isAllowed(defaultOptions.account.address),
133
+ ).toBe(true);
134
+ expect(await boost.allowList.isAllowed(zeroAddress)).toBe(false);
135
+
136
+ expect(boost.budget.address?.toLowerCase()).toBe(
137
+ onChainBoost.budget.toLowerCase(),
138
+ );
139
+ expect(
140
+ await boost.budget.isAuthorized(defaultOptions.account.address),
141
+ ).toBe(true);
142
+
143
+ expect(boost.incentives.length).toBe(onChainBoost.incentives.length);
144
+ const incentive = boost.incentives.at(0) as ERC20Incentive;
145
+ expect(incentive.address?.toLowerCase()).toBe(
146
+ onChainBoost.incentives.at(0)?.toLowerCase(),
147
+ );
148
+ expect((await incentive.asset()).toLowerCase()).toBe(
149
+ erc20.address?.toLowerCase(),
150
+ );
151
+ expect(await incentive.currentReward()).toBe(parseEther('1'));
152
+ expect(await incentive.limit()).toBe(100n);
153
+ expect(await incentive.claims()).toBe(0n);
154
+ });
155
+
156
+ test('can read the raw on chain representation of a boost', async () => {
157
+ const { core } = fixtures;
158
+ const client = new BoostCore({
159
+ ...defaultOptions,
160
+ address: core.assertValidAddress(),
161
+ });
162
+ const { budget, erc20 } = budgets;
163
+ const _boost = await client.createBoost({
164
+ protocolFee: 1n,
165
+ referralFee: 2n,
166
+ maxParticipants: 100n,
167
+ budget: budget,
168
+ action: core.EventAction(
169
+ makeMockEventActionPayload(
170
+ core.assertValidAddress(),
171
+ erc20.assertValidAddress(),
172
+ ),
173
+ ),
174
+ validator: core.SignerValidator({
175
+ signers: [defaultOptions.account.address],
176
+ validatorCaller: defaultOptions.account.address,
177
+ }),
178
+ allowList: core.SimpleAllowList({
179
+ owner: defaultOptions.account.address,
180
+ allowed: [defaultOptions.account.address],
181
+ }),
182
+ incentives: [
183
+ core.ERC20Incentive({
184
+ asset: erc20.assertValidAddress(),
185
+ reward: parseEther('1'),
186
+ limit: 100n,
187
+ strategy: StrategyType.POOL,
188
+ }),
189
+ ],
190
+ });
191
+ const boost = await client.readBoost(_boost.id);
192
+ expect(boost.protocolFee).toBe(1001n);
193
+ expect(boost.referralFee).toBe(1002n);
194
+ expect(boost.maxParticipants).toBe(100n);
195
+ expect(boost.budget).toBe(_boost.budget.assertValidAddress());
196
+ expect(boost.action).toBe(_boost.action.assertValidAddress());
197
+ expect(boost.validator).toBe(_boost.validator.assertValidAddress());
198
+ expect(boost.allowList).toBe(_boost.allowList.assertValidAddress());
199
+ expect(boost.incentives.at(0)).toBe(
200
+ _boost.incentives.at(0)?.assertValidAddress(),
201
+ );
202
+ });
203
+
204
+ test('can reuse an existing action', async () => {
205
+ const { core } = fixtures;
206
+ const client = new BoostCore({
207
+ ...defaultOptions,
208
+ address: core.assertValidAddress(),
209
+ });
210
+ const { budget, erc20 } = budgets;
211
+
212
+ // allocate more funds to the budget
213
+ await erc20.mint(defaultOptions.account.address, parseEther('100'));
214
+ await erc20.approve(budget.assertValidAddress(), parseEther('100'));
215
+ await budget.allocate({
216
+ amount: parseEther('100'),
217
+ asset: erc20.assertValidAddress(),
218
+ target: defaultOptions.account.address,
219
+ });
220
+
221
+ const _boost = await client.createBoost({
222
+ budget: budget,
223
+ action: core.EventAction(
224
+ makeMockEventActionPayload(
225
+ core.assertValidAddress(),
226
+ erc20.assertValidAddress(),
227
+ ),
228
+ ),
229
+ validator: core.SignerValidator({
230
+ signers: [defaultOptions.account.address],
231
+ validatorCaller: defaultOptions.account.address,
232
+ }),
233
+ allowList: core.SimpleAllowList({
234
+ owner: defaultOptions.account.address,
235
+ allowed: [defaultOptions.account.address],
236
+ }),
237
+ incentives: [
238
+ core.ERC20Incentive({
239
+ asset: erc20.assertValidAddress(),
240
+ reward: parseEther('1'),
241
+ limit: 100n,
242
+ strategy: StrategyType.POOL,
243
+ }),
244
+ ],
245
+ });
246
+ const boost = await client.createBoost({
247
+ budget: budget,
248
+ action: core.EventAction(_boost.action.assertValidAddress(), false),
249
+ validator: core.SignerValidator({
250
+ signers: [defaultOptions.account.address],
251
+ validatorCaller: defaultOptions.account.address,
252
+ }),
253
+ allowList: core.SimpleAllowList({
254
+ owner: defaultOptions.account.address,
255
+ allowed: [defaultOptions.account.address],
256
+ }),
257
+ incentives: [
258
+ core.ERC20Incentive({
259
+ asset: erc20.assertValidAddress(),
260
+ reward: parseEther('1'),
261
+ limit: 100n,
262
+ strategy: StrategyType.POOL,
263
+ }),
264
+ ],
265
+ });
266
+ const onChainBoost = await client.readBoost(boost.id);
267
+ expect(onChainBoost.action).toBe(_boost.action.assertValidAddress());
268
+ });
269
+
270
+ test('can reuse an existing validator', async () => {
271
+ const { core } = fixtures;
272
+ const client = new BoostCore({
273
+ ...defaultOptions,
274
+ address: core.assertValidAddress(),
275
+ });
276
+ const { budget, erc20 } = budgets;
277
+
278
+ // allocate more erc20 funds to the budget from the owning accound
279
+ await erc20.mint(defaultOptions.account.address, parseEther('100'));
280
+ await erc20.approve(budget.assertValidAddress(), parseEther('100'));
281
+ await budget.allocate({
282
+ amount: parseEther('100'),
283
+ asset: erc20.assertValidAddress(),
284
+ target: defaultOptions.account.address,
285
+ });
286
+
287
+ const _boost = await client.createBoost({
288
+ budget: budget,
289
+ action: core.EventAction(
290
+ makeMockEventActionPayload(
291
+ core.assertValidAddress(),
292
+ erc20.assertValidAddress(),
293
+ ),
294
+ ),
295
+ validator: core.SignerValidator({
296
+ signers: [defaultOptions.account.address],
297
+ validatorCaller: defaultOptions.account.address,
298
+ }),
299
+ allowList: core.SimpleAllowList({
300
+ owner: defaultOptions.account.address,
301
+ allowed: [defaultOptions.account.address],
302
+ }),
303
+ incentives: [
304
+ core.ERC20Incentive({
305
+ asset: erc20.assertValidAddress(),
306
+ reward: parseEther('1'),
307
+ limit: 100n,
308
+ strategy: StrategyType.POOL,
309
+ }),
310
+ ],
311
+ });
312
+ const boost = await client.createBoost({
313
+ budget: budget,
314
+ action: core.EventAction(
315
+ makeMockEventActionPayload(
316
+ core.assertValidAddress(),
317
+ erc20.assertValidAddress(),
318
+ ),
319
+ ),
320
+ validator: core.SignerValidator(
321
+ _boost.validator.assertValidAddress(),
322
+ false,
323
+ ),
324
+ allowList: core.SimpleAllowList({
325
+ owner: defaultOptions.account.address,
326
+ allowed: [defaultOptions.account.address],
327
+ }),
328
+ incentives: [
329
+ core.ERC20Incentive({
330
+ asset: erc20.assertValidAddress(),
331
+ reward: parseEther('1'),
332
+ limit: 100n,
333
+ strategy: StrategyType.POOL,
334
+ }),
335
+ ],
336
+ });
337
+ const onChainBoost = await client.readBoost(boost.id);
338
+ expect(onChainBoost.validator).toBe(_boost.validator.assertValidAddress());
339
+ });
340
+
341
+ test('can reuse an existing allowlist', async () => {
342
+ const { core } = fixtures;
343
+ const client = new BoostCore({
344
+ ...defaultOptions,
345
+ address: core.assertValidAddress(),
346
+ });
347
+ const { budget, erc20 } = budgets;
348
+
349
+ // allocate more erc20 funds to the budget from the owning accound
350
+ await erc20.mint(defaultOptions.account.address, parseEther('100'));
351
+ await erc20.approve(budget.assertValidAddress(), parseEther('100'));
352
+ await budget.allocate({
353
+ amount: parseEther('100'),
354
+ asset: erc20.assertValidAddress(),
355
+ target: defaultOptions.account.address,
356
+ });
357
+
358
+ const _boost = await client.createBoost({
359
+ budget: budget,
360
+ action: core.EventAction(
361
+ makeMockEventActionPayload(
362
+ core.assertValidAddress(),
363
+ erc20.assertValidAddress(),
364
+ ),
365
+ ),
366
+ validator: core.SignerValidator({
367
+ signers: [defaultOptions.account.address],
368
+ validatorCaller: defaultOptions.account.address,
369
+ }),
370
+ allowList: core.SimpleAllowList({
371
+ owner: defaultOptions.account.address,
372
+ allowed: [defaultOptions.account.address],
373
+ }),
374
+ incentives: [
375
+ core.ERC20Incentive({
376
+ asset: erc20.assertValidAddress(),
377
+ reward: parseEther('1'),
378
+ limit: 100n,
379
+ strategy: StrategyType.POOL,
380
+ }),
381
+ ],
382
+ });
383
+ const boost = await client.createBoost({
384
+ budget: budget,
385
+ action: core.EventAction(
386
+ makeMockEventActionPayload(
387
+ core.assertValidAddress(),
388
+ erc20.assertValidAddress(),
389
+ ),
390
+ ),
391
+ validator: core.SignerValidator({
392
+ signers: [defaultOptions.account.address],
393
+ validatorCaller: defaultOptions.account.address,
394
+ }),
395
+ allowList: core.SimpleAllowList(
396
+ _boost.allowList.assertValidAddress(),
397
+ false,
398
+ ),
399
+ incentives: [
400
+ core.ERC20Incentive({
401
+ asset: erc20.assertValidAddress(),
402
+ reward: parseEther('1'),
403
+ limit: 100n,
404
+ strategy: StrategyType.POOL,
405
+ }),
406
+ ],
407
+ });
408
+ const onChainBoost = await client.readBoost(boost.id);
409
+ expect(onChainBoost.allowList).toBe(_boost.allowList.assertValidAddress());
410
+ });
411
+
412
+ test('cannot reuse an existing incentive', async () => {
413
+ const { core } = fixtures;
414
+ const client = new BoostCore({
415
+ ...defaultOptions,
416
+ address: core.assertValidAddress(),
417
+ });
418
+ const { budget, erc20 } = budgets;
419
+
420
+ // allocate more erc20 funds to the budget from the owning accound
421
+ await erc20.mint(defaultOptions.account.address, parseEther('100'));
422
+ await erc20.approve(budget.assertValidAddress(), parseEther('100'));
423
+ await budget.allocate({
424
+ amount: parseEther('100'),
425
+ asset: erc20.assertValidAddress(),
426
+ target: defaultOptions.account.address,
427
+ });
428
+
429
+ const incentive = core.ERC20Incentive({
430
+ asset: erc20.assertValidAddress(),
431
+ reward: parseEther('1'),
432
+ limit: 100n,
433
+ strategy: StrategyType.POOL,
434
+ });
435
+ const _boost = await client.createBoost({
436
+ budget: budget,
437
+ action: core.EventAction(
438
+ makeMockEventActionPayload(
439
+ core.assertValidAddress(),
440
+ erc20.assertValidAddress(),
441
+ ),
442
+ ),
443
+ validator: core.SignerValidator({
444
+ signers: [defaultOptions.account.address],
445
+ validatorCaller: defaultOptions.account.address,
446
+ }),
447
+ allowList: core.SimpleAllowList({
448
+ owner: defaultOptions.account.address,
449
+ allowed: [defaultOptions.account.address],
450
+ }),
451
+ incentives: [incentive],
452
+ });
453
+ try {
454
+ await client.createBoost({
455
+ budget: budget,
456
+ action: core.EventAction(
457
+ makeMockEventActionPayload(
458
+ core.assertValidAddress(),
459
+ erc20.assertValidAddress(),
460
+ ),
461
+ ),
462
+ validator: core.SignerValidator({
463
+ signers: [defaultOptions.account.address],
464
+ validatorCaller: defaultOptions.account.address,
465
+ }),
466
+ allowList: core.SimpleAllowList({
467
+ owner: defaultOptions.account.address,
468
+ allowed: [defaultOptions.account.address],
469
+ }),
470
+ incentives: [incentive],
471
+ });
472
+ } catch (e) {
473
+ expect(e).toBeInstanceOf(IncentiveNotCloneableError);
474
+ }
475
+ });
476
+
477
+ test('can offer multiple incentives', async () => {
478
+ const { registry, core } = fixtures;
479
+ const client = new BoostCore({
480
+ ...defaultOptions,
481
+ address: core.assertValidAddress(),
482
+ });
483
+ const { budget, erc20, points, erc1155 } = budgets;
484
+ const allowList = await registry.initialize(
485
+ 'SharedAllowList',
486
+ core.SimpleAllowList({
487
+ owner: defaultOptions.account.address,
488
+ allowed: [defaultOptions.account.address],
489
+ }),
490
+ );
491
+
492
+ const erc20Incentive = core.ERC20Incentive({
493
+ asset: erc20.assertValidAddress(),
494
+ reward: 1n,
495
+ limit: 10n,
496
+ strategy: StrategyType.POOL,
497
+ });
498
+ const erc1155Incentive = core.ERC1155Incentive({
499
+ asset: erc1155.assertValidAddress(),
500
+ strategy: ERC1155StrategyType.POOL,
501
+ limit: 1n,
502
+ tokenId: 1n,
503
+ extraData: '0x',
504
+ });
505
+ const cgdaIncentive = core.CGDAIncentive({
506
+ asset: erc20.assertValidAddress(),
507
+ initialReward: 1n,
508
+ totalBudget: 10n,
509
+ rewardBoost: 1n,
510
+ rewardDecay: 1n,
511
+ });
512
+ const allowListIncentive = core.AllowListIncentive({
513
+ allowList: allowList.assertValidAddress(),
514
+ limit: 5n,
515
+ });
516
+ const pointsIncentive = core.PointsIncentive({
517
+ venue: points.assertValidAddress(),
518
+ selector: bytes4('issue(address,uint256)'),
519
+ reward: 1n,
520
+ limit: 10n,
521
+ });
522
+
523
+ await client.createBoost({
524
+ protocolFee: 1n,
525
+ referralFee: 2n,
526
+ maxParticipants: 100n,
527
+ budget: budget,
528
+ action: core.EventAction(
529
+ makeMockEventActionPayload(
530
+ core.assertValidAddress(),
531
+ erc20.assertValidAddress(),
532
+ ),
533
+ ),
534
+ validator: core.SignerValidator({
535
+ signers: [defaultOptions.account.address],
536
+ validatorCaller: defaultOptions.account.address,
537
+ }),
538
+ allowList: core.SimpleAllowList(allowList.assertValidAddress()),
539
+ incentives: [
540
+ erc1155Incentive,
541
+ erc20Incentive,
542
+ cgdaIncentive,
543
+ allowListIncentive,
544
+ pointsIncentive,
545
+ ],
546
+ });
547
+ expect(await erc20Incentive.reward()).toEqual(1n);
548
+ expect(await erc20Incentive.limit()).toEqual(10n);
549
+ expect((await cgdaIncentive.asset()).toLowerCase()).toEqual(
550
+ erc20.address?.toLowerCase(),
551
+ );
552
+ expect(await cgdaIncentive.currentReward()).toEqual(1n);
553
+ expect(
554
+ await (await allowListIncentive.allowList()).isAllowed(
555
+ defaultOptions.account.address,
556
+ ),
557
+ ).toEqual(true);
558
+ expect(await pointsIncentive.reward()).toEqual(1n);
559
+ expect(await pointsIncentive.currentReward()).toEqual(1n);
560
+ expect(await pointsIncentive.limit()).toEqual(10n);
561
+ });
562
+
563
+ test('can get the protocol fee', async () => {
564
+ const { core } = fixtures;
565
+ const client = new BoostCore({
566
+ ...defaultOptions,
567
+ address: core.assertValidAddress(),
568
+ });
569
+
570
+ expect(await client.protocolFee()).toBe(1000n);
571
+ });
572
+
573
+ test('can get the protocol fee receiver', async () => {
574
+ const { core } = fixtures;
575
+ const client = new BoostCore({
576
+ ...defaultOptions,
577
+ address: core.assertValidAddress(),
578
+ });
579
+
580
+ expect(await client.protocolFeeReceiver()).toBe(
581
+ defaultOptions.account.address,
582
+ );
583
+ });
584
+
585
+ test('can set the protocol fee receiver', async () => {
586
+ const { core } = fixtures;
587
+ const client = new BoostCore({
588
+ ...defaultOptions,
589
+ address: core.assertValidAddress(),
590
+ });
591
+
592
+ await client.setProcolFeeReceiver(zeroAddress);
593
+
594
+ expect(await client.protocolFeeReceiver()).toBe(zeroAddress);
595
+ });
596
+
597
+ test('can get the claim fee', async () => {
598
+ const { core } = fixtures;
599
+ const client = new BoostCore({
600
+ ...defaultOptions,
601
+ address: core.assertValidAddress(),
602
+ });
603
+
604
+ expect(await client.claimFee()).toBe(75000000000000n);
605
+ });
606
+
607
+ test('can set the claim fee', async () => {
608
+ const { core } = fixtures;
609
+ const client = new BoostCore({
610
+ ...defaultOptions,
611
+ address: core.assertValidAddress(),
612
+ });
613
+
614
+ await client.setClaimFee(100n);
615
+
616
+ expect(await client.claimFee()).toBe(100n);
617
+ });
618
+
619
+ test('binds all actions, budgets, allowlists, incentives, and validators to reuse core options and account', () => {
620
+ const { core } = fixtures;
621
+
622
+ // const contractAction = core.ContractAction(zeroAddress);
623
+ // expect(contractAction._config).toEqual(defaultOptions.config);
624
+ // expect(contractAction._account).toEqual(defaultOptions.account);
625
+
626
+ // const erc721MintAction = core.ERC721MintAction(zeroAddress);
627
+ // expect(erc721MintAction._config).toEqual(defaultOptions.config);
628
+ // expect(erc721MintAction._account).toEqual(defaultOptions.account);
629
+
630
+ const eventAction = core.EventAction(zeroAddress);
631
+ expect(eventAction._config).toEqual(defaultOptions.config);
632
+ expect(eventAction._account).toEqual(defaultOptions.account);
633
+
634
+ const allowList = core.SimpleAllowList(zeroAddress);
635
+ expect(allowList._config).toEqual(defaultOptions.config);
636
+ expect(allowList._account).toEqual(defaultOptions.account);
637
+
638
+ const denyList = core.SimpleDenyList(zeroAddress);
639
+ expect(denyList._config).toEqual(defaultOptions.config);
640
+ expect(denyList._account).toEqual(defaultOptions.account);
641
+
642
+ const managedBudget = core.ManagedBudget(zeroAddress);
643
+ expect(managedBudget._config).toEqual(defaultOptions.config);
644
+ expect(managedBudget._account).toEqual(defaultOptions.account);
645
+
646
+ // const simpleBudget = core.SimpleBudget(zeroAddress);
647
+ // expect(simpleBudget._config).toEqual(defaultOptions.config);
648
+ // expect(simpleBudget._account).toEqual(defaultOptions.account);
649
+
650
+ // const vestingBudget = core.VestingBudget(zeroAddress);
651
+ // expect(vestingBudget._config).toEqual(defaultOptions.config);
652
+ // expect(vestingBudget._account).toEqual(defaultOptions.account);
653
+
654
+ const allowListIncentive = core.AllowListIncentive({
655
+ allowList: zeroAddress,
656
+ limit: 0n,
657
+ });
658
+ expect(allowListIncentive._config).toEqual(defaultOptions.config);
659
+ expect(allowListIncentive._account).toEqual(defaultOptions.account);
660
+
661
+ const cgdaIncentive = core.CGDAIncentive({
662
+ asset: zeroAddress,
663
+ initialReward: 0n,
664
+ rewardDecay: 0n,
665
+ rewardBoost: 0n,
666
+ totalBudget: 0n,
667
+ });
668
+ expect(cgdaIncentive._config).toEqual(defaultOptions.config);
669
+ expect(cgdaIncentive._account).toEqual(defaultOptions.account);
670
+
671
+ const erc20Incentive = core.ERC20Incentive({
672
+ asset: zeroAddress,
673
+ strategy: 0,
674
+ reward: 0n,
675
+ limit: 0n,
676
+ });
677
+ expect(erc20Incentive._config).toEqual(defaultOptions.config);
678
+ expect(erc20Incentive._account).toEqual(defaultOptions.account);
679
+
680
+ const erc20VariableIncentive = core.ERC20VariableIncentive({
681
+ asset: zeroAddress,
682
+ reward: 0n,
683
+ limit: 0n,
684
+ });
685
+ expect(erc20VariableIncentive._config).toEqual(defaultOptions.config);
686
+ expect(erc20VariableIncentive._account).toEqual(defaultOptions.account);
687
+
688
+ // const erc1155Incentive = core.ERC1155Incentive({
689
+ // asset: zeroAddress,
690
+ // strategy: 0,
691
+ // tokenId: 1n,
692
+ // limit: 0n,
693
+ // extraData: '0x',
694
+ // });
695
+ // expect(erc1155Incentive._config).toEqual(defaultOptions.config);
696
+ // expect(erc1155Incentive._account).toEqual(defaultOptions.account);
697
+
698
+ const pointsIncentive = core.PointsIncentive({
699
+ venue: zeroAddress,
700
+ selector: '0x',
701
+ reward: 0n,
702
+ limit: 0n,
703
+ });
704
+ expect(pointsIncentive._config).toEqual(defaultOptions.config);
705
+ expect(pointsIncentive._account).toEqual(defaultOptions.account);
706
+
707
+ const signerValidator = core.SignerValidator(zeroAddress);
708
+ expect(signerValidator._config).toEqual(defaultOptions.config);
709
+ expect(signerValidator._account).toEqual(defaultOptions.account);
710
+ });
711
+
712
+ test('can subscribe to contract events', async () => {
713
+ const subscription = vi.fn();
714
+
715
+ const { core } = fixtures;
716
+ const client = new BoostCore({
717
+ ...defaultOptions,
718
+ address: core.assertValidAddress(),
719
+ });
720
+ client.subscribe(subscription, { pollingInterval: 100 });
721
+ const { budget, erc20 } = budgets;
722
+ await client.createBoost({
723
+ protocolFee: 1n,
724
+ referralFee: 2n,
725
+ maxParticipants: 100n,
726
+ budget: budget,
727
+ action: core.EventAction(
728
+ makeMockEventActionPayload(
729
+ core.assertValidAddress(),
730
+ erc20.assertValidAddress(),
731
+ ),
732
+ ),
733
+ validator: core.SignerValidator({
734
+ signers: [defaultOptions.account.address],
735
+ validatorCaller: defaultOptions.account.address,
736
+ }),
737
+ allowList: core.SimpleAllowList({
738
+ owner: defaultOptions.account.address,
739
+ allowed: [defaultOptions.account.address],
740
+ }),
741
+ incentives: [
742
+ core.ERC20Incentive({
743
+ asset: erc20.assertValidAddress(),
744
+ reward: parseEther('1'),
745
+ limit: 100n,
746
+ strategy: StrategyType.POOL,
747
+ }),
748
+ ],
749
+ });
750
+
751
+ await new Promise((resolve) => {
752
+ setTimeout(resolve, 500);
753
+ });
754
+
755
+ expect(subscription).toHaveBeenCalledTimes(1);
756
+ });
757
+
758
+ test('can set a passthrough auth scheme', async () => {
759
+ const { core } = fixtures;
760
+ const client = new BoostCore({
761
+ ...defaultOptions,
762
+ address: core.assertValidAddress(),
763
+ });
764
+
765
+ const auth = client.PassthroughAuth();
766
+ await auth.deploy();
767
+ await client.setCreateBoostAuth(auth);
768
+ expect((await client.createBoostAuth()).toLowerCase()).toBe(
769
+ auth.assertValidAddress(),
770
+ );
771
+ expect(await client.isAuthorized(zeroAddress)).toBe(true);
772
+ });
773
+ });