diff --git a/components/sidebar/context/strategy/SidebarStrategy.vue b/components/sidebar/context/strategy/SidebarStrategy.vue index f21bc7d..d8d474c 100644 --- a/components/sidebar/context/strategy/SidebarStrategy.vue +++ b/components/sidebar/context/strategy/SidebarStrategy.vue @@ -14,6 +14,7 @@ :key="index" :value="input.value" @input="$event => input.onInput($event.target.value)" + :placeholder="input.placeholder()" /> @@ -53,7 +54,7 @@ export default defineComponent({ strategies.find(strategy => strategy.id === props.strategy) ); - watch(() => { + watch([], () => { selectedStrategy.value = strategies.find( strategy => strategy.id === props.strategy ); diff --git a/core/strategies/helpers/strategy.ts b/core/strategies/helpers/strategy.ts index b9043ba..ec31728 100644 --- a/core/strategies/helpers/strategy.ts +++ b/core/strategies/helpers/strategy.ts @@ -1,10 +1,10 @@ -import DSA from "dsa-connect"; +import DSA, { Spell } from "dsa-connect"; import Web3 from "web3"; import slugify from "slugify"; export interface IStrategyContext { - dsa: typeof DSA; + dsa: DSA; web3: Web3; - inputs: IStrategyInput[]; + inputs: IStrategyInput[]; } export interface IStrategyToken { @@ -22,24 +22,27 @@ export enum StrategyInputType { INPUT_WITH_TOKEN = "input-with-token" } -// type InputTypes = { -// [StrategyInputType.INPUT] : { -// token?: IStrategyToken; -// value?: any; -// }; -// } +export type StrategyInputParameterMap = { + [StrategyInputType.INPUT]: {}; -export interface IStrategyInput { - type: StrategyInputType; + [StrategyInputType.INPUT_WITH_TOKEN]: { + token?: IStrategyToken; + }; +}; + +export interface IStrategyInput { + type: InputType; name: string; - placeholder: - | string - | ((context: IStrategyContext & { input: IStrategyInput }) => string); + placeholder: ( + context: IStrategyContext & { + input: IStrategyInput & StrategyInputParameterMap[InputType]; + } + ) => string; validate?: ( - context: IStrategyContext & { input: IStrategyInput } - ) => boolean | string; - // If type is "input-with-token", this is the token - token?: IStrategyToken; + context: IStrategyContext & { + input: IStrategyInput & StrategyInputParameterMap[InputType]; + } + ) => string | void; value?: any; [key: string]: any; @@ -51,41 +54,71 @@ export interface IStrategy { description: string; author?: string; - inputs: IStrategyInput[]; + inputs: IStrategyInput[]; - spells: (context: IStrategyContext) => any; + spells: (context: IStrategyContext) => Promise | Spell[]; submitText?: string; } +export function defineInput( + input: IStrategyInput +) { + return input as IStrategyInput; +} + export function defineStrategy(strategy: IStrategy) { + const context = { + web3: null, + dsa: null + }; + return { ...strategy, - id: strategy.id ? strategy.id : slugify(strategy.name).toLowerCase(), + id: strategy.id ? strategy.id : slugify(strategy.name).toLowerCase(), inputs: strategy.inputs.map(input => ({ ...input, value: null, + placeholder: () => + input.placeholder + ? input.placeholder({ + ...context, + inputs: strategy.inputs, + input: { + ...input, + token: { + // todo + } + } + }) + : null, onInput: (val: any) => { input.value = val; } })), - submit: async (context: Pick) => { + submit: async () => { await this.validate({ ...context, inputs: strategy.inputs }); - const spells = strategy.spells({ + const allSpells = await strategy.spells({ ...context, inputs: strategy.inputs }); + const spells = context.dsa.Spell(); + + for (const spell of allSpells) { + spells.add(spell); + } + return await context.dsa.cast({ spells, onReceipt: this.onReceipt }); }, - validate: async (context: IStrategyContext) => { + validate: async () => { for (const input of this.inputs) { const result = await input.validate({ ...context, diff --git a/core/strategies/protocols/aave-v2/deposit-and-borrow.ts b/core/strategies/protocols/aave-v2/deposit-and-borrow.ts index 919a6ef..a2c04e8 100644 --- a/core/strategies/protocols/aave-v2/deposit-and-borrow.ts +++ b/core/strategies/protocols/aave-v2/deposit-and-borrow.ts @@ -1,4 +1,8 @@ -import { defineStrategy, StrategyInputType } from "../../helpers/strategy"; +import { + defineStrategy, + defineInput, + StrategyInputType +} from "../../helpers/strategy"; export default defineStrategy({ name: "Deposit & Borrow", @@ -6,7 +10,7 @@ export default defineStrategy({ author: "Instadapp Team", inputs: [ - { + defineInput({ type: StrategyInputType.INPUT_WITH_TOKEN, name: "Debt", placeholder: ({ input }) => `${input.token.symbol} to Payback`, @@ -18,32 +22,27 @@ export default defineStrategy({ if (input.token.balance < input.value) { return "Your amount exceeds your maximum limit."; } - - return true; } - }, - { + }), + defineInput({ type: StrategyInputType.INPUT_WITH_TOKEN, name: "Collateral", placeholder: ({ input }) => `${input.token.symbol} to Withdraw` - } + }) ], - spells: async ({ dsa, inputs }) => { - const spells = dsa.Spells(); - - spells.add({ - connector: "aave_v2", - method: "deposit", - args: [inputs[0].token.address, inputs[0].value, 0, 0] - }); - - spells.add({ - connector: "aave_v2", - method: "borrow", - args: [inputs[1].token.address, inputs[1].value, 0, 0, 0] - }); - - return spells; + spells: async ({ inputs }) => { + return [ + { + connector: "aave_v2", + method: "deposit", + args: [inputs[0].token.address, inputs[0].value, 0, 0] + }, + { + connector: "aave_v2", + method: "borrow", + args: [inputs[1].token.address, inputs[1].value, 0, 0, 0] + } + ]; } });