Skip to content

Commit

Permalink
chore(sdk): createBoost generator functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
sammccord committed Jun 19, 2024
1 parent abe901a commit 2784ac8
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 41 deletions.
22 changes: 10 additions & 12 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
"version": "0.0.0-alpha.0",
"private": true,
"type": "module",
"files": [
"dist"
],
"files": ["dist"],
"repository": "https://github.com/rabbitholegg/boost-protocol",
"author": "Boost Team<[email protected]>",
"exports": {
".": "./src/index.ts",
"./Deployable/Deployable": "./src/Deployable/Deployable.ts",
"./Actions/Action": "./src/AllowLists/Action.ts",
"./Actions/ContractAction": "./src/AllowLists/ContractAction.ts",
"./Actions/ERC721MintAction": "./src/AllowLists/ERC721MintAction.ts",
"./Actions/Action": "./src/Actions/Action.ts",
"./Actions/ContractAction": "./src/Actions/ContractAction.ts",
"./Actions/ERC721MintAction": "./src/Actions/ERC721MintAction.ts",
"./AllowLists/AllowList": "./src/AllowLists/AllowList.ts",
"./AllowLists/SimpleAllowList": "./src/AllowLists/SimpleAllowList.ts",
"./AllowLists/SimpleDenyList": "./src/AllowLists/SimpleDenyList.ts",
"./Budgets/Budgets": "./src/Budgets/Budgets.ts",
"./Budgets/Budget": "./src/Budgets/Budget.ts",
"./Budgets/SimpleBudget": "./src/Budgets/SimpleBudget.ts",
"./Budgets/VestingBudget": "./src/Budgets/VestingBudget.ts",
"./Incentives/AllowListIncentive": "./src/Incentives/AllowListIncentive.ts",
Expand Down Expand Up @@ -79,11 +77,11 @@
"node": "./dist/AllowLists/SimpleDenyList.js",
"types": "./dist/AllowLists/SimpleDenyList.d.ts"
},
"./Budgets/Budgets": {
"require": "./dist/Budgets/Budgets.cjs",
"import": "./dist/Budgets/Budgets.js",
"node": "./dist/Budgets/Budgets.js",
"types": "./dist/Budgets/Budgets.d.ts"
"./Budgets/Budget": {
"require": "./dist/Budgets/Budget.cjs",
"import": "./dist/Budgets/Budget.js",
"node": "./dist/Budgets/Budget.js",
"types": "./dist/Budgets/Budget.d.ts"
},
"./Budgets/SimpleBudget": {
"require": "./dist/Budgets/SimpleBudget.cjs",
Expand Down
170 changes: 143 additions & 27 deletions packages/sdk/src/BoostClient.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { boostCoreAbi, prepareBoostPayload } from '@boostxyz/evm';
import type { Config } from '@wagmi/core';
import {
type BoostPayload,
boostCoreAbi,
prepareBoostPayload,
} from '@boostxyz/evm';
import { type Config, getAccount } from '@wagmi/core';
import { createWriteContract } from '@wagmi/core/codegen';
import type { Address } from 'viem';
import { type Address, zeroAddress, zeroHash } from 'viem';
import type { Action } from './Actions/Action';
import type { AllowList } from './AllowLists/AllowList';
import type { Budget } from './Budgets/Budget';
import type { Deployable } from './Deployable/Deployable';
import type { Incentive } from './Incentives/Incentive';
import type { Validator } from './Validators/Validator';

Expand All @@ -25,7 +30,18 @@ export interface CreateBoostPayload {
protocolFee?: bigint;
referralFee?: bigint;
maxParticipants?: bigint;
owner: Address;
owner?: Address;
}

// TODO RFC?
// As dependencies are deployed, the iterator yields with the deployable and the remaining number of steps. finally, it yields with the address of
export interface CreateBoostProgress {
remaining: number;
deployed: Deployable;
}

export interface CreateBoostCompletion {
address: Address;
}

export class BoostClient {
Expand All @@ -37,8 +53,7 @@ export class BoostClient {
this.config = config;
}

// TODO don't use boost payload, instead accept nice interface with Budget, Validator instances, etc.
public async createBoost({
public async *createBoost({
budget,
action,
validator,
Expand All @@ -47,42 +62,143 @@ export class BoostClient {
protocolFee = 0n,
referralFee = 0n,
maxParticipants = 0n,
owner,
}: CreateBoostPayload) {
owner = zeroAddress,
}: CreateBoostPayload): AsyncGenerator<
CreateBoostProgress | CreateBoostCompletion,
Address
> {
const boostFactory = createWriteContract({
abi: boostCoreAbi,
functionName: 'createBoost',
address: this.address,
});

// if (!payload.budget) {
// // create simple budget
// }
if (!owner) {
owner = getAccount(this.config).address || zeroAddress;
if (owner === zeroAddress) {
// throw? TODO
console.warn('No owner supplied, falling back to zeroAddress');
}
}

// As we proceed, decrement total steps to indiciate progress to consumer
let remainingSteps = 4 + incentives.length;

let budgetPayload: Pick<BoostPayload, 'budget'> = {
budget: budget.address || zeroAddress,
};

// if (!payload.action) {
// // idk
// }
if (budget.address === zeroAddress) {
budget = await this.deploy(budget);
budgetPayload.budget = budget.address || zeroAddress;
// TODO validate and throw?
}
yield {
remaining: --remainingSteps,
deployed: budget,
};

// if (!payload.validator) {
// //
// }
let actionPayload: Pick<BoostPayload, 'action'> = {
action: {
isBase: false,
instance: action.address || zeroAddress,
parameters: action.buildParameters(this.config).args.at(0) || zeroHash,
},
};
if (actionPayload.action.instance === zeroAddress) {
action = await this.deploy(action);
actionPayload.action.instance = action.address || zeroAddress;
// TODO validate and throw?
}
yield {
remaining: --remainingSteps,
deployed: action,
};

// if (!payload.allowList) {
// }
let validatorPayload: Pick<BoostPayload, 'validator'> = {
validator: {
isBase: false,
instance: validator.address || zeroAddress,
parameters:
validator.buildParameters(this.config).args.at(0) || zeroHash,
},
};
if (validatorPayload.validator.instance === zeroAddress) {
validator = await this.deploy(validator);
validatorPayload.validator.instance = validator.address || zeroAddress;
// TODO validate and throw?
}
yield {
remaining: --remainingSteps,
deployed: validator,
};

// if (!payload.incentives) {
// }
let allowListPayload: Pick<BoostPayload, 'allowList'> = {
allowList: {
isBase: false,
instance: allowList.address || zeroAddress,
parameters:
allowList.buildParameters(this.config).args.at(0) || zeroHash,
},
};
if (allowListPayload.allowList.instance === zeroAddress) {
allowList = await this.deploy(allowList);
allowListPayload.allowList.instance = allowList.address || zeroAddress;
// TODO validate and throw?
}
yield {
remaining: --remainingSteps,
deployed: allowList,
};

// if (!payload.owner) {
// const owner = getAccount(this.config);
// payload.owner = owner.address;
// }
let incentivesPayload: Pick<BoostPayload, 'incentives'> = {
incentives: incentives.map((incentive) => ({
isBase: false,
instance: incentive.address || zeroAddress,
parameters:
incentive.buildParameters(this.config).args.at(0) || zeroHash,
})),
};
for (let i = 0; i < incentives.length; i++) {
let incentive = incentives.at(i)!;
const incentiveTarget = incentivesPayload.incentives.at(i)!;

if (incentiveTarget.instance === zeroAddress) {
incentive = await this.deploy(incentive);
incentiveTarget.instance = incentive.address || zeroAddress;
// TODO validate and throw?
}
yield {
remaining: --remainingSteps,
deployed: incentive,
};
}

const boostPayload: BoostPayload = {
...budgetPayload,
...actionPayload,
...validatorPayload,
...allowListPayload,
...incentivesPayload,
protocolFee,
referralFee,
maxParticipants,
owner,
};

const boost = await boostFactory(this.config, {
//TODO resolve this
args: [prepareBoostPayload(payload)],
args: [prepareBoostPayload(boostPayload)],
});

yield {
address: boost,
};

return boost;
}

public async deploy<T extends Deployable>(deployable: T) {
await deployable.deploy(this.config);
return deployable;
}
}
13 changes: 11 additions & 2 deletions packages/sdk/src/Deployable/Deployable.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { type Config, deployContract } from '@wagmi/core';
import type { Address } from 'viem';
import type { Address, Hex } from 'viem';
import { DeployableParametersUnspecifiedError } from '../errors';

export type GenericDeployableParams = Parameters<typeof deployContract>[1];
export type GenericDeployableParams = Omit<
Parameters<typeof deployContract>[1],
'args'
> & {
args: [Hex, ...Array<Hex>];
};

export class Deployable {
protected _address: Address | undefined;
Expand All @@ -12,6 +17,10 @@ export class Deployable {
}

public async deploy(config: Config): Promise<Address> {
if (this.address) {
// throw? TODO
console.warn(`Deployable already has address ${this.address}`);
}
return (this._address = await deployContract(
config,
this.buildParameters(config),
Expand Down

0 comments on commit 2784ac8

Please sign in to comment.