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="h-full overflow-y-scroll scrollbar-hover">
|
||||||
<div class="mx-auto" style="max-width: 296px">
|
<div class="mx-auto" style="max-width: 296px">
|
||||||
<div class="py-2 sm:py-4">
|
<div class="py-2 sm:py-4">
|
||||||
<pre>{{ $props }}</pre>
|
<div v-for="(input, index) in inputs" :key="index">
|
||||||
<pre>{{ selectedStrategy }}</pre>
|
<input
|
||||||
|
type="text"
|
||||||
|
:value="input.value"
|
||||||
|
@input="$event => input.onInput($event.target.value)"
|
||||||
|
:placeholder="input.placeholder()"
|
||||||
|
/>
|
||||||
|
{{ input.error }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<button @submit="submit">Submit</button>
|
||||||
type="text"
|
|
||||||
v-for="(input, index) in selectedStrategy.inputs"
|
{{ error }}
|
||||||
:key="index"
|
|
||||||
:value="input.value"
|
|
||||||
@input="$event => input.onInput($event.target.value)"
|
|
||||||
:placeholder="input.placeholder()"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,15 +25,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { defineComponent } from "@nuxtjs/composition-api";
|
||||||
computed,
|
|
||||||
defineComponent,
|
|
||||||
watch,
|
|
||||||
watchEffect,
|
|
||||||
ref
|
|
||||||
} from "@nuxtjs/composition-api";
|
|
||||||
import { useSidebar } from "~/composables/useSidebar";
|
import { useSidebar } from "~/composables/useSidebar";
|
||||||
import { protocolStrategies, DefineStrategy } from "~/core/strategies";
|
import { protocolStrategies, DefineStrategy } from "~/core/strategies";
|
||||||
|
import { useStrategy } from "~/composables/useStrategy";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
@ -50,18 +47,14 @@ export default defineComponent({
|
||||||
const strategies: DefineStrategy[] =
|
const strategies: DefineStrategy[] =
|
||||||
protocolStrategies[props.protocol] || [];
|
protocolStrategies[props.protocol] || [];
|
||||||
|
|
||||||
const selectedStrategy = ref(
|
const { inputs, submit, error } = useStrategy(
|
||||||
strategies.find(strategy => strategy.id === props.strategy)
|
strategies.find(strategy => strategy.id === props.strategy)
|
||||||
);
|
);
|
||||||
|
|
||||||
watch([], () => {
|
|
||||||
selectedStrategy.value = strategies.find(
|
|
||||||
strategy => strategy.id === props.strategy
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedStrategy
|
inputs,
|
||||||
|
error,
|
||||||
|
submit
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,8 +20,14 @@ import { useBigNumber } from "./useBigNumber";
|
||||||
import { useSorting } from "./useSorting";
|
import { useSorting } from "./useSorting";
|
||||||
|
|
||||||
const balances = reactive({
|
const balances = reactive({
|
||||||
user: null,
|
user: {
|
||||||
dsa: null
|
mainnet: {},
|
||||||
|
polygon: {}
|
||||||
|
},
|
||||||
|
dsa: {
|
||||||
|
mainnet: {},
|
||||||
|
polygon: {}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const prices = reactive({
|
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 Web3 from "web3";
|
||||||
import slugify from "slugify";
|
import { DefineStrategy, IStrategyContext } from ".";
|
||||||
export interface IStrategyContext {
|
|
||||||
dsa: DSA;
|
|
||||||
web3: Web3;
|
|
||||||
inputs: IStrategyInput<StrategyInputType>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStrategyToken {
|
export class Strategy {
|
||||||
address: string;
|
schema: DefineStrategy;
|
||||||
key: string;
|
inputs = [];
|
||||||
symbol: string;
|
context = {
|
||||||
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 = {
|
|
||||||
web3: null,
|
web3: null,
|
||||||
dsa: null
|
dsa: null
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
listeners = [];
|
||||||
...strategy,
|
|
||||||
id: strategy.id ? strategy.id : slugify(strategy.name).toLowerCase(),
|
props: object = {
|
||||||
inputs: strategy.inputs.map(input => ({
|
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,
|
...input,
|
||||||
value: null,
|
value: input.value || "",
|
||||||
|
error: input.error || "",
|
||||||
placeholder: () =>
|
placeholder: () =>
|
||||||
input.placeholder
|
input.placeholder
|
||||||
? input.placeholder({
|
? input.placeholder({
|
||||||
...context,
|
...this.context,
|
||||||
inputs: strategy.inputs,
|
inputs: this.inputs,
|
||||||
input: {
|
input: {
|
||||||
...input,
|
...input,
|
||||||
token: {
|
token: {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
: null,
|
: null,
|
||||||
onInput: (val: any) => {
|
onInput: (val: any) => {
|
||||||
|
input.error = "";
|
||||||
input.value = val;
|
input.value = val;
|
||||||
}
|
|
||||||
})),
|
|
||||||
submit: async () => {
|
|
||||||
await this.validate({
|
|
||||||
...context,
|
|
||||||
inputs: strategy.inputs
|
|
||||||
});
|
|
||||||
|
|
||||||
const allSpells = await strategy.spells({
|
if (val) {
|
||||||
...context,
|
input.error = input.validate({
|
||||||
inputs: strategy.inputs
|
...this.getContext(),
|
||||||
});
|
input
|
||||||
|
});
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
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,
|
aaveV2 : AaveV2,
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from "./helpers/strategy"
|
export * from "./helpers"
|
|
@ -2,7 +2,7 @@ import {
|
||||||
defineStrategy,
|
defineStrategy,
|
||||||
defineInput,
|
defineInput,
|
||||||
StrategyInputType
|
StrategyInputType
|
||||||
} from "../../helpers/strategy";
|
} from "../../helpers";
|
||||||
|
|
||||||
export default defineStrategy({
|
export default defineStrategy({
|
||||||
name: "Deposit & Borrow",
|
name: "Deposit & Borrow",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user