mirror of
https://github.com/Instadapp/assembly.git
synced 2024-07-29 22:37:06 +00:00
wip
This commit is contained in:
parent
b5b7141661
commit
63dfc0c4c8
|
@ -5,17 +5,19 @@
|
|||
<div class="h-full overflow-y-scroll scrollbar-hover">
|
||||
<div class="mx-auto" style="max-width: 296px">
|
||||
<div class="py-2 sm:py-4">
|
||||
<pre>{{ $props }}</pre>
|
||||
<pre>{{ selectedStrategy }}</pre>
|
||||
<div v-for="(input, index) in inputs" :key="index">
|
||||
<input
|
||||
type="text"
|
||||
:value="input.value"
|
||||
@input="$event => input.onInput($event.target.value)"
|
||||
:placeholder="input.placeholder()"
|
||||
/>
|
||||
{{ input.error }}
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
v-for="(input, index) in selectedStrategy.inputs"
|
||||
:key="index"
|
||||
:value="input.value"
|
||||
@input="$event => input.onInput($event.target.value)"
|
||||
:placeholder="input.placeholder()"
|
||||
/>
|
||||
<button @submit="submit">Submit</button>
|
||||
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,15 +25,10 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
computed,
|
||||
defineComponent,
|
||||
watch,
|
||||
watchEffect,
|
||||
ref
|
||||
} from "@nuxtjs/composition-api";
|
||||
import { defineComponent } from "@nuxtjs/composition-api";
|
||||
import { useSidebar } from "~/composables/useSidebar";
|
||||
import { protocolStrategies, DefineStrategy } from "~/core/strategies";
|
||||
import { useStrategy } from "~/composables/useStrategy";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
|
@ -50,18 +47,14 @@ export default defineComponent({
|
|||
const strategies: DefineStrategy[] =
|
||||
protocolStrategies[props.protocol] || [];
|
||||
|
||||
const selectedStrategy = ref(
|
||||
const { inputs, submit, error } = useStrategy(
|
||||
strategies.find(strategy => strategy.id === props.strategy)
|
||||
);
|
||||
|
||||
watch([], () => {
|
||||
selectedStrategy.value = strategies.find(
|
||||
strategy => strategy.id === props.strategy
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
selectedStrategy
|
||||
inputs,
|
||||
error,
|
||||
submit
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -20,8 +20,14 @@ import { useBigNumber } from "./useBigNumber";
|
|||
import { useSorting } from "./useSorting";
|
||||
|
||||
const balances = reactive({
|
||||
user: null,
|
||||
dsa: null
|
||||
user: {
|
||||
mainnet: {},
|
||||
polygon: {}
|
||||
},
|
||||
dsa: {
|
||||
mainnet: {},
|
||||
polygon: {}
|
||||
}
|
||||
});
|
||||
|
||||
const prices = reactive({
|
||||
|
|
60
composables/useStrategy.ts
Normal file
60
composables/useStrategy.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { nextTick, onMounted, ref, watch } from "@nuxtjs/composition-api";
|
||||
import { buildStrategy, DefineStrategy, IStrategy } from "~/core/strategies";
|
||||
import { useBalances } from "./useBalances";
|
||||
import { useDSA } from "./useDSA";
|
||||
import { useWeb3 } from "./useWeb3";
|
||||
|
||||
export function useStrategy(defineStrategy: DefineStrategy) {
|
||||
const { web3, networkName } = useWeb3();
|
||||
const { dsa } = useDSA();
|
||||
const { prices, balances } = useBalances();
|
||||
|
||||
const strategy = buildStrategy(defineStrategy);
|
||||
const inputs = ref(strategy.getInputs());
|
||||
const error = ref("");
|
||||
|
||||
strategy.onUpdated(async () => {
|
||||
await nextTick();
|
||||
|
||||
inputs.value = strategy.getInputs();
|
||||
});
|
||||
|
||||
const submit = async () => {
|
||||
try {
|
||||
await strategy.submit();
|
||||
} catch (e) {
|
||||
error.value = e.message;
|
||||
}
|
||||
};
|
||||
|
||||
watch(web3, () => strategy.setWeb3(web3.value), { immediate: true });
|
||||
watch(dsa, () => strategy.setDSA(dsa.value), { immediate: true });
|
||||
watch(
|
||||
prices,
|
||||
() => strategy.setProps({ prices: prices[networkName.value] }),
|
||||
{ immediate: true }
|
||||
);
|
||||
watch(
|
||||
balances,
|
||||
() => {
|
||||
strategy.setProps({
|
||||
dsaTokens: balances.dsa[networkName.value],
|
||||
userTokens: balances.user[networkName.value]
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// testing
|
||||
onMounted(() => {
|
||||
//@ts-ignore
|
||||
window.strategy = strategy;
|
||||
});
|
||||
|
||||
return {
|
||||
strategy,
|
||||
inputs,
|
||||
submit,
|
||||
error,
|
||||
};
|
||||
}
|
84
core/strategies/helpers/index.ts
Normal file
84
core/strategies/helpers/index.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import DSA, { Spell } from "dsa-connect";
|
||||
import Web3 from "web3";
|
||||
import slugify from "slugify";
|
||||
import { Strategy } from "./strategy";
|
||||
export interface IStrategyContext {
|
||||
dsa: DSA;
|
||||
web3: Web3;
|
||||
inputs: IStrategyInput<StrategyInputType>[];
|
||||
dsaTokens?: IStrategyToken,
|
||||
userTokens?: IStrategyToken,
|
||||
}
|
||||
|
||||
export interface IStrategyToken {
|
||||
address: string;
|
||||
key: string;
|
||||
symbol: string;
|
||||
balance: string;
|
||||
|
||||
// supply: string;
|
||||
// borrow: string;
|
||||
}
|
||||
|
||||
export enum StrategyInputType {
|
||||
INPUT = "input",
|
||||
INPUT_WITH_TOKEN = "input-with-token"
|
||||
}
|
||||
|
||||
export type StrategyInputParameterMap = {
|
||||
[StrategyInputType.INPUT]: {};
|
||||
|
||||
[StrategyInputType.INPUT_WITH_TOKEN]: {
|
||||
token?: IStrategyToken;
|
||||
};
|
||||
};
|
||||
|
||||
export interface IStrategyInput<InputType extends StrategyInputType> {
|
||||
type: InputType;
|
||||
name: string;
|
||||
placeholder?: (
|
||||
context: IStrategyContext & {
|
||||
input: IStrategyInput<InputType> & StrategyInputParameterMap[InputType];
|
||||
}
|
||||
) => string;
|
||||
validate?: (
|
||||
context: IStrategyContext & {
|
||||
input: IStrategyInput<InputType> & StrategyInputParameterMap[InputType];
|
||||
}
|
||||
) => string | void;
|
||||
value?: any;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface IStrategy {
|
||||
id?: string;
|
||||
name: string;
|
||||
description: string;
|
||||
author?: string;
|
||||
|
||||
inputs: IStrategyInput<StrategyInputType>[];
|
||||
|
||||
spells: (context: IStrategyContext) => Promise<Spell[]> | Spell[];
|
||||
|
||||
submitText?: string;
|
||||
}
|
||||
|
||||
export function defineInput<InputType extends StrategyInputType>(
|
||||
input: IStrategyInput<InputType>
|
||||
) {
|
||||
return input as IStrategyInput<InputType>;
|
||||
}
|
||||
|
||||
export function defineStrategy(strategy: IStrategy) {
|
||||
return {
|
||||
...strategy,
|
||||
id: strategy.id ? strategy.id : slugify(strategy.name).toLowerCase()
|
||||
};
|
||||
}
|
||||
|
||||
export function buildStrategy(schema: DefineStrategy) {
|
||||
return new Strategy(schema)
|
||||
}
|
||||
|
||||
export type DefineStrategy = ReturnType<typeof defineStrategy>;
|
|
@ -1,140 +1,130 @@
|
|||
import DSA, { Spell } from "dsa-connect";
|
||||
import DSA from "dsa-connect";
|
||||
import Web3 from "web3";
|
||||
import slugify from "slugify";
|
||||
export interface IStrategyContext {
|
||||
dsa: DSA;
|
||||
web3: Web3;
|
||||
inputs: IStrategyInput<StrategyInputType>[];
|
||||
}
|
||||
import { DefineStrategy, IStrategyContext } from ".";
|
||||
|
||||
export interface IStrategyToken {
|
||||
address: string;
|
||||
key: string;
|
||||
symbol: string;
|
||||
balance: string;
|
||||
|
||||
supply: string;
|
||||
borrow: string;
|
||||
}
|
||||
|
||||
export enum StrategyInputType {
|
||||
INPUT = "input",
|
||||
INPUT_WITH_TOKEN = "input-with-token"
|
||||
}
|
||||
|
||||
export type StrategyInputParameterMap = {
|
||||
[StrategyInputType.INPUT]: {};
|
||||
|
||||
[StrategyInputType.INPUT_WITH_TOKEN]: {
|
||||
token?: IStrategyToken;
|
||||
};
|
||||
};
|
||||
|
||||
export interface IStrategyInput<InputType extends StrategyInputType> {
|
||||
type: InputType;
|
||||
name: string;
|
||||
placeholder: (
|
||||
context: IStrategyContext & {
|
||||
input: IStrategyInput<InputType> & StrategyInputParameterMap[InputType];
|
||||
}
|
||||
) => string;
|
||||
validate?: (
|
||||
context: IStrategyContext & {
|
||||
input: IStrategyInput<InputType> & StrategyInputParameterMap[InputType];
|
||||
}
|
||||
) => string | void;
|
||||
value?: any;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface IStrategy {
|
||||
id?: string;
|
||||
name: string;
|
||||
description: string;
|
||||
author?: string;
|
||||
|
||||
inputs: IStrategyInput<any>[];
|
||||
|
||||
spells: (context: IStrategyContext) => Promise<Spell[]> | Spell[];
|
||||
|
||||
submitText?: string;
|
||||
}
|
||||
|
||||
export function defineInput<InputType extends StrategyInputType>(
|
||||
input: IStrategyInput<InputType>
|
||||
) {
|
||||
return input as IStrategyInput<any>;
|
||||
}
|
||||
|
||||
export function defineStrategy(strategy: IStrategy) {
|
||||
const context = {
|
||||
export class Strategy {
|
||||
schema: DefineStrategy;
|
||||
inputs = [];
|
||||
context = {
|
||||
web3: null,
|
||||
dsa: null
|
||||
};
|
||||
|
||||
return {
|
||||
...strategy,
|
||||
id: strategy.id ? strategy.id : slugify(strategy.name).toLowerCase(),
|
||||
inputs: strategy.inputs.map(input => ({
|
||||
listeners = [];
|
||||
|
||||
props: object = {
|
||||
prices: {},
|
||||
dsaTokens: {},
|
||||
userTokens: {},
|
||||
};
|
||||
|
||||
constructor(schema: DefineStrategy) {
|
||||
this.schema = schema;
|
||||
|
||||
this.inputs = this.schema.inputs;
|
||||
}
|
||||
|
||||
getContext(): IStrategyContext {
|
||||
return {
|
||||
...this.context,
|
||||
...this.props,
|
||||
inputs: this.getInputs()
|
||||
};
|
||||
}
|
||||
|
||||
setProps(props: object) {
|
||||
Object.assign(this.props, props);
|
||||
}
|
||||
|
||||
getInputs() {
|
||||
return this.inputs.map(input => ({
|
||||
...input,
|
||||
value: null,
|
||||
value: input.value || "",
|
||||
error: input.error || "",
|
||||
placeholder: () =>
|
||||
input.placeholder
|
||||
? input.placeholder({
|
||||
...context,
|
||||
inputs: strategy.inputs,
|
||||
...this.context,
|
||||
inputs: this.inputs,
|
||||
input: {
|
||||
...input,
|
||||
token: {
|
||||
// todo
|
||||
// todo
|
||||
}
|
||||
}
|
||||
})
|
||||
: null,
|
||||
onInput: (val: any) => {
|
||||
input.error = "";
|
||||
input.value = val;
|
||||
}
|
||||
})),
|
||||
submit: async () => {
|
||||
await this.validate({
|
||||
...context,
|
||||
inputs: strategy.inputs
|
||||
});
|
||||
|
||||
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 () => {
|
||||
for (const input of this.inputs) {
|
||||
const result = await input.validate({
|
||||
...context,
|
||||
inputs: strategy.inputs,
|
||||
input
|
||||
});
|
||||
|
||||
if (result !== true) {
|
||||
throw new Error(result || "Error has occurred");
|
||||
if (val) {
|
||||
input.error = input.validate({
|
||||
...this.getContext(),
|
||||
input
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
onReceipt: (txHash: string, txReceipt: any) => {
|
||||
// do something
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export type DefineStrategy = ReturnType<typeof defineStrategy>;
|
||||
this.notifyListeners();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
async submit() {
|
||||
await this.validate();
|
||||
|
||||
const allSpells = await this.schema.spells(this.getContext());
|
||||
|
||||
const spells = this.context.dsa.Spell();
|
||||
|
||||
console.log(spells);
|
||||
|
||||
for (const spell of allSpells) {
|
||||
spells.add(spell);
|
||||
}
|
||||
|
||||
return await this.context.dsa.cast({
|
||||
spells,
|
||||
onReceipt: this.onReceipt
|
||||
});
|
||||
}
|
||||
|
||||
async validate() {
|
||||
const inputs = this.getInputs();
|
||||
|
||||
for (const input of inputs) {
|
||||
const result = await input.validate({
|
||||
...this.getContext(),
|
||||
input
|
||||
});
|
||||
|
||||
if (typeof result === "string") {
|
||||
throw new Error(result || "Error has occurred");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onReceipt(txHash: string, txReceipt: any) {
|
||||
// do something
|
||||
}
|
||||
|
||||
setWeb3(web3: Web3) {
|
||||
console.log(web3);
|
||||
|
||||
this.context.web3 = web3;
|
||||
}
|
||||
|
||||
setDSA(dsa: DSA) {
|
||||
this.context.dsa = dsa;
|
||||
}
|
||||
|
||||
async notifyListeners() {
|
||||
for (const listener of this.listeners) {
|
||||
await listener(this);
|
||||
}
|
||||
}
|
||||
|
||||
onUpdated(cb) {
|
||||
this.listeners.push(cb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@ export const protocolStrategies = {
|
|||
aaveV2 : AaveV2,
|
||||
}
|
||||
|
||||
export * from "./helpers/strategy"
|
||||
export * from "./helpers"
|
|
@ -2,7 +2,7 @@ import {
|
|||
defineStrategy,
|
||||
defineInput,
|
||||
StrategyInputType
|
||||
} from "../../helpers/strategy";
|
||||
} from "../../helpers";
|
||||
|
||||
export default defineStrategy({
|
||||
name: "Deposit & Borrow",
|
||||
|
|
Loading…
Reference in New Issue
Block a user