Skip to content

Commit 2784ac8

Browse files
committed
chore(sdk): createBoost generator functionality
1 parent abe901a commit 2784ac8

File tree

3 files changed

+164
-41
lines changed

3 files changed

+164
-41
lines changed

packages/sdk/package.json

+10-12
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,19 @@
33
"version": "0.0.0-alpha.0",
44
"private": true,
55
"type": "module",
6-
"files": [
7-
"dist"
8-
],
6+
"files": ["dist"],
97
"repository": "https://github.com/rabbitholegg/boost-protocol",
108
"author": "Boost Team<[email protected]>",
119
"exports": {
1210
".": "./src/index.ts",
1311
"./Deployable/Deployable": "./src/Deployable/Deployable.ts",
14-
"./Actions/Action": "./src/AllowLists/Action.ts",
15-
"./Actions/ContractAction": "./src/AllowLists/ContractAction.ts",
16-
"./Actions/ERC721MintAction": "./src/AllowLists/ERC721MintAction.ts",
12+
"./Actions/Action": "./src/Actions/Action.ts",
13+
"./Actions/ContractAction": "./src/Actions/ContractAction.ts",
14+
"./Actions/ERC721MintAction": "./src/Actions/ERC721MintAction.ts",
1715
"./AllowLists/AllowList": "./src/AllowLists/AllowList.ts",
1816
"./AllowLists/SimpleAllowList": "./src/AllowLists/SimpleAllowList.ts",
1917
"./AllowLists/SimpleDenyList": "./src/AllowLists/SimpleDenyList.ts",
20-
"./Budgets/Budgets": "./src/Budgets/Budgets.ts",
18+
"./Budgets/Budget": "./src/Budgets/Budget.ts",
2119
"./Budgets/SimpleBudget": "./src/Budgets/SimpleBudget.ts",
2220
"./Budgets/VestingBudget": "./src/Budgets/VestingBudget.ts",
2321
"./Incentives/AllowListIncentive": "./src/Incentives/AllowListIncentive.ts",
@@ -79,11 +77,11 @@
7977
"node": "./dist/AllowLists/SimpleDenyList.js",
8078
"types": "./dist/AllowLists/SimpleDenyList.d.ts"
8179
},
82-
"./Budgets/Budgets": {
83-
"require": "./dist/Budgets/Budgets.cjs",
84-
"import": "./dist/Budgets/Budgets.js",
85-
"node": "./dist/Budgets/Budgets.js",
86-
"types": "./dist/Budgets/Budgets.d.ts"
80+
"./Budgets/Budget": {
81+
"require": "./dist/Budgets/Budget.cjs",
82+
"import": "./dist/Budgets/Budget.js",
83+
"node": "./dist/Budgets/Budget.js",
84+
"types": "./dist/Budgets/Budget.d.ts"
8785
},
8886
"./Budgets/SimpleBudget": {
8987
"require": "./dist/Budgets/SimpleBudget.cjs",

packages/sdk/src/BoostClient.ts

+143-27
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { boostCoreAbi, prepareBoostPayload } from '@boostxyz/evm';
2-
import type { Config } from '@wagmi/core';
1+
import {
2+
type BoostPayload,
3+
boostCoreAbi,
4+
prepareBoostPayload,
5+
} from '@boostxyz/evm';
6+
import { type Config, getAccount } from '@wagmi/core';
37
import { createWriteContract } from '@wagmi/core/codegen';
4-
import type { Address } from 'viem';
8+
import { type Address, zeroAddress, zeroHash } from 'viem';
59
import type { Action } from './Actions/Action';
610
import type { AllowList } from './AllowLists/AllowList';
711
import type { Budget } from './Budgets/Budget';
12+
import type { Deployable } from './Deployable/Deployable';
813
import type { Incentive } from './Incentives/Incentive';
914
import type { Validator } from './Validators/Validator';
1015

@@ -25,7 +30,18 @@ export interface CreateBoostPayload {
2530
protocolFee?: bigint;
2631
referralFee?: bigint;
2732
maxParticipants?: bigint;
28-
owner: Address;
33+
owner?: Address;
34+
}
35+
36+
// TODO RFC?
37+
// As dependencies are deployed, the iterator yields with the deployable and the remaining number of steps. finally, it yields with the address of
38+
export interface CreateBoostProgress {
39+
remaining: number;
40+
deployed: Deployable;
41+
}
42+
43+
export interface CreateBoostCompletion {
44+
address: Address;
2945
}
3046

3147
export class BoostClient {
@@ -37,8 +53,7 @@ export class BoostClient {
3753
this.config = config;
3854
}
3955

40-
// TODO don't use boost payload, instead accept nice interface with Budget, Validator instances, etc.
41-
public async createBoost({
56+
public async *createBoost({
4257
budget,
4358
action,
4459
validator,
@@ -47,42 +62,143 @@ export class BoostClient {
4762
protocolFee = 0n,
4863
referralFee = 0n,
4964
maxParticipants = 0n,
50-
owner,
51-
}: CreateBoostPayload) {
65+
owner = zeroAddress,
66+
}: CreateBoostPayload): AsyncGenerator<
67+
CreateBoostProgress | CreateBoostCompletion,
68+
Address
69+
> {
5270
const boostFactory = createWriteContract({
5371
abi: boostCoreAbi,
5472
functionName: 'createBoost',
5573
address: this.address,
5674
});
5775

58-
// if (!payload.budget) {
59-
// // create simple budget
60-
// }
76+
if (!owner) {
77+
owner = getAccount(this.config).address || zeroAddress;
78+
if (owner === zeroAddress) {
79+
// throw? TODO
80+
console.warn('No owner supplied, falling back to zeroAddress');
81+
}
82+
}
83+
84+
// As we proceed, decrement total steps to indiciate progress to consumer
85+
let remainingSteps = 4 + incentives.length;
86+
87+
let budgetPayload: Pick<BoostPayload, 'budget'> = {
88+
budget: budget.address || zeroAddress,
89+
};
6190

62-
// if (!payload.action) {
63-
// // idk
64-
// }
91+
if (budget.address === zeroAddress) {
92+
budget = await this.deploy(budget);
93+
budgetPayload.budget = budget.address || zeroAddress;
94+
// TODO validate and throw?
95+
}
96+
yield {
97+
remaining: --remainingSteps,
98+
deployed: budget,
99+
};
65100

66-
// if (!payload.validator) {
67-
// //
68-
// }
101+
let actionPayload: Pick<BoostPayload, 'action'> = {
102+
action: {
103+
isBase: false,
104+
instance: action.address || zeroAddress,
105+
parameters: action.buildParameters(this.config).args.at(0) || zeroHash,
106+
},
107+
};
108+
if (actionPayload.action.instance === zeroAddress) {
109+
action = await this.deploy(action);
110+
actionPayload.action.instance = action.address || zeroAddress;
111+
// TODO validate and throw?
112+
}
113+
yield {
114+
remaining: --remainingSteps,
115+
deployed: action,
116+
};
69117

70-
// if (!payload.allowList) {
71-
// }
118+
let validatorPayload: Pick<BoostPayload, 'validator'> = {
119+
validator: {
120+
isBase: false,
121+
instance: validator.address || zeroAddress,
122+
parameters:
123+
validator.buildParameters(this.config).args.at(0) || zeroHash,
124+
},
125+
};
126+
if (validatorPayload.validator.instance === zeroAddress) {
127+
validator = await this.deploy(validator);
128+
validatorPayload.validator.instance = validator.address || zeroAddress;
129+
// TODO validate and throw?
130+
}
131+
yield {
132+
remaining: --remainingSteps,
133+
deployed: validator,
134+
};
72135

73-
// if (!payload.incentives) {
74-
// }
136+
let allowListPayload: Pick<BoostPayload, 'allowList'> = {
137+
allowList: {
138+
isBase: false,
139+
instance: allowList.address || zeroAddress,
140+
parameters:
141+
allowList.buildParameters(this.config).args.at(0) || zeroHash,
142+
},
143+
};
144+
if (allowListPayload.allowList.instance === zeroAddress) {
145+
allowList = await this.deploy(allowList);
146+
allowListPayload.allowList.instance = allowList.address || zeroAddress;
147+
// TODO validate and throw?
148+
}
149+
yield {
150+
remaining: --remainingSteps,
151+
deployed: allowList,
152+
};
75153

76-
// if (!payload.owner) {
77-
// const owner = getAccount(this.config);
78-
// payload.owner = owner.address;
79-
// }
154+
let incentivesPayload: Pick<BoostPayload, 'incentives'> = {
155+
incentives: incentives.map((incentive) => ({
156+
isBase: false,
157+
instance: incentive.address || zeroAddress,
158+
parameters:
159+
incentive.buildParameters(this.config).args.at(0) || zeroHash,
160+
})),
161+
};
162+
for (let i = 0; i < incentives.length; i++) {
163+
let incentive = incentives.at(i)!;
164+
const incentiveTarget = incentivesPayload.incentives.at(i)!;
165+
166+
if (incentiveTarget.instance === zeroAddress) {
167+
incentive = await this.deploy(incentive);
168+
incentiveTarget.instance = incentive.address || zeroAddress;
169+
// TODO validate and throw?
170+
}
171+
yield {
172+
remaining: --remainingSteps,
173+
deployed: incentive,
174+
};
175+
}
176+
177+
const boostPayload: BoostPayload = {
178+
...budgetPayload,
179+
...actionPayload,
180+
...validatorPayload,
181+
...allowListPayload,
182+
...incentivesPayload,
183+
protocolFee,
184+
referralFee,
185+
maxParticipants,
186+
owner,
187+
};
80188

81189
const boost = await boostFactory(this.config, {
82-
//TODO resolve this
83-
args: [prepareBoostPayload(payload)],
190+
args: [prepareBoostPayload(boostPayload)],
84191
});
85192

193+
yield {
194+
address: boost,
195+
};
196+
86197
return boost;
87198
}
199+
200+
public async deploy<T extends Deployable>(deployable: T) {
201+
await deployable.deploy(this.config);
202+
return deployable;
203+
}
88204
}

packages/sdk/src/Deployable/Deployable.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { type Config, deployContract } from '@wagmi/core';
2-
import type { Address } from 'viem';
2+
import type { Address, Hex } from 'viem';
33
import { DeployableParametersUnspecifiedError } from '../errors';
44

5-
export type GenericDeployableParams = Parameters<typeof deployContract>[1];
5+
export type GenericDeployableParams = Omit<
6+
Parameters<typeof deployContract>[1],
7+
'args'
8+
> & {
9+
args: [Hex, ...Array<Hex>];
10+
};
611

712
export class Deployable {
813
protected _address: Address | undefined;
@@ -12,6 +17,10 @@ export class Deployable {
1217
}
1318

1419
public async deploy(config: Config): Promise<Address> {
20+
if (this.address) {
21+
// throw? TODO
22+
console.warn(`Deployable already has address ${this.address}`);
23+
}
1524
return (this._address = await deployContract(
1625
config,
1726
this.buildParameters(config),

0 commit comments

Comments
 (0)