This commit is contained in:
Georges KABBOUCHI 2021-08-24 02:07:53 +03:00
parent 60e1cfb5ca
commit b1b221876c
7 changed files with 146 additions and 49 deletions

View File

@ -212,6 +212,7 @@ async function getBalances(
}
const { name, symbol, decimals, type, isStableCoin, key } = tokenData;
tokensBalObj[tokenAddress] = {
address: tokenAddress,
name,
symbol,
decimals,

View File

@ -18,13 +18,13 @@ export function useStrategy(defineStrategy: DefineStrategy) {
} = useNotification();
const strategy = buildStrategy(defineStrategy);
const inputs = ref(strategy.getInputs());
const inputs = ref(strategy.inputs);
const error = ref("");
strategy.onUpdated(async () => {
await nextTick();
inputs.value = strategy.getInputs();
inputs.value = strategy.inputs;
console.log("onUpdated");
});

View File

@ -6,8 +6,8 @@ export interface IStrategyContext {
dsa: DSA;
web3: Web3;
inputs: IStrategyInput<StrategyInputType>[];
dsaTokens?: IStrategyToken,
userTokens?: IStrategyToken,
dsaTokens?: { [address: string]: IStrategyToken };
userTokens?: { [address: string]: IStrategyToken };
}
export interface IStrategyToken {
@ -46,6 +46,9 @@ export interface IStrategyInput<InputType extends StrategyInputType> {
input: IStrategyInput<InputType> & StrategyInputParameterMap[InputType];
}
) => string | void;
defaults?: (context: Omit<IStrategyContext, 'inputs'>) => object;
value?: any;
[key: string]: any;
@ -78,7 +81,7 @@ export function defineStrategy(strategy: IStrategy) {
}
export function buildStrategy(schema: DefineStrategy) {
return new Strategy(schema)
return new Strategy(schema);
}
export type DefineStrategy = ReturnType<typeof defineStrategy>;

View File

@ -21,64 +21,94 @@ export class Strategy {
constructor(schema: DefineStrategy) {
this.schema = schema;
this.inputs = this.schema.inputs;
this.inputs = this.generateInputs(this.schema.inputs);
}
getBaseContext(): Omit<IStrategyContext, "inputs"> {
return {
...this.context,
...this.props
};
}
getContext(): IStrategyContext {
return {
...this.context,
...this.props,
inputs: this.getInputs()
inputs: this.inputs
};
}
setProps(props: object) {
Object.assign(this.props, props);
this.notifyListeners()
const inputs = this.inputs;
for (const input of inputs) {
if (typeof input.defaults !== "function") {
continue;
}
Object.assign(input, input.defaults(this.getBaseContext()));
}
this.notifyListeners();
}
getInputs() {
return this.inputs.map(input => ({
...input,
value: input.value || "",
error: input.error || "",
placeholder: () =>
input.placeholder
? input.placeholder({
...this.context,
inputs: this.inputs,
input: {
token: {
// todo
},
...input
}
})
: null,
onInput: (val: any) => {
input.error = "";
input.value = val;
if (val) {
input.error = input.validate({
generateInputs(inputs) {
return inputs.map((input, idx) => {
const computedInput = {
...input,
value: input.value || "",
error: input.error || "",
placeholder: () => {
console.log({
...this.getContext(),
input
input: this.inputs[idx]
});
return input.placeholder
? input.placeholder({
...this.getContext(),
input: this.inputs[idx]
})
: null;
},
onInput: (val: any) => {
this.inputs[idx].error = "";
this.inputs[idx].value = val;
if (val) {
this.inputs[idx].error = this.inputs[idx].validate({
...this.getContext(),
input: this.inputs[idx]
});
}
this.notifyListeners();
},
onCustomInput: (values: object) => {
this.inputs[idx] = Object.assign(this.inputs[idx], values);
this.inputs[idx].error = this.inputs[idx].validate({
...this.getContext(),
input: this.inputs[idx]
});
this.notifyListeners();
}
};
this.notifyListeners();
},
onCustomInput: (values: object) => {
input = Object.assign(input, values);
let defaults = {};
input.error = input.validate({
...this.getContext(),
input
});
this.notifyListeners();
if (input.defaults) {
defaults = input.defaults(this.getBaseContext());
}
}));
return {
...computedInput,
...defaults
};
});
}
async submit(options) {
@ -100,7 +130,7 @@ export class Strategy {
}
async validate() {
const inputs = this.getInputs();
const inputs = this.inputs;
for (const input of inputs) {
if (typeof input.validate !== "function") {
@ -120,10 +150,14 @@ export class Strategy {
setWeb3(web3: Web3) {
this.context.web3 = web3;
this.notifyListeners();
}
setDSA(dsa: DSA) {
this.context.dsa = dsa;
this.notifyListeners();
}
async notifyListeners() {

View File

@ -10,7 +10,7 @@ export default defineStrategy({
defineInput({
type: StrategyInputType.INPUT_WITH_TOKEN,
name: "Debt",
placeholder: ({ input }) => `${input.token.symbol} to Payback`,
placeholder: ({ input }) => `${input.token?.symbol} to Payback`,
validate: ({ input }) => {
if (!input.token) {
return "Token is required";
@ -20,13 +20,23 @@ export default defineStrategy({
return "Your amount exceeds your maximum limit.";
}
},
token: tokens.mainnet.getTokenByKey("eth")
defaults: context => {
return {
token: context.dsaTokens
? Object.values(context.dsaTokens).find(t => t.key === "eth")
: null
};
}
}),
defineInput({
type: StrategyInputType.INPUT_WITH_TOKEN,
name: "Collateral",
placeholder: ({ input }) => `${input.token.symbol} to Withdraw`,
token: tokens.mainnet.getTokenByKey("dai")
placeholder: ({ input }) => `${input.token?.symbol} to Withdraw`,
defaults: ({ dsaTokens }) => ({
token: dsaTokens
? Object.values(dsaTokens).find(t => t.key === "dai")
: null
})
})
],

View File

@ -1,6 +1,8 @@
import depositAndBorrow from "./deposit-and-borrow"
import paybackAndWithdraw from "./payback-and-withdraw"
export default [
depositAndBorrow
depositAndBorrow,
paybackAndWithdraw,
]

View File

@ -0,0 +1,47 @@
import tokens from "~/constant/tokens";
import { defineStrategy, defineInput, StrategyInputType } from "../../helpers";
export default defineStrategy({
name: "Payback & Withdraw",
description: "Payback debt & withdraw collateral in a single txn.",
author: "Instadapp Team",
inputs: [
defineInput({
type: StrategyInputType.INPUT_WITH_TOKEN,
name: "Debt",
placeholder: ({ input }) => `${input.token.symbol} to Payback`,
validate: ({ input }) => {
if (!input.token) {
return "Token is required";
}
if (input.token.balance < input.value) {
return "Your amount exceeds your maximum limit.";
}
},
token: tokens.mainnet.getTokenByKey("eth")
}),
defineInput({
type: StrategyInputType.INPUT_WITH_TOKEN,
name: "Collateral",
placeholder: ({ input }) => `${input.token.symbol} to Withdraw`,
token: tokens.mainnet.getTokenByKey("dai")
})
],
spells: async ({ inputs }) => {
return [
{
connector: "aave_v2",
method: "payback",
args: [inputs[0].token.address, inputs[0].value, 1, 0, 0]
},
{
connector: "aave_v2",
method: "withdraw",
args: [inputs[1].token.address, inputs[1].value, 0, 0]
}
];
}
});