From 60b01e884acf2153741a6a30fd11041c328106da Mon Sep 17 00:00:00 2001 From: Georges KABBOUCHI Date: Sun, 5 Sep 2021 14:46:39 +0300 Subject: [PATCH] rename input to component in strategy --- .../context/strategy/SidebarStrategy.vue | 34 ++++---- composables/useStrategy.ts | 4 +- core/strategies/helpers/index.ts | 32 ++++---- core/strategies/helpers/strategy.ts | 78 ++++++++++--------- .../protocols/aave-v2/deposit-and-borrow.ts | 26 +++---- .../protocols/aave-v2/payback-and-withdraw.ts | 26 +++---- .../protocols/compound/deposit-and-borrow.ts | 26 +++---- .../compound/payback-and-withdraw.ts | 26 +++---- .../protocols/liquity/close-trove.ts | 38 ++++----- .../protocols/liquity/deposit-and-borrow.ts | 26 +++---- .../protocols/liquity/payback-and-withdraw.ts | 26 +++---- 11 files changed, 172 insertions(+), 170 deletions(-) diff --git a/components/sidebar/context/strategy/SidebarStrategy.vue b/components/sidebar/context/strategy/SidebarStrategy.vue index f1675c4..b34dffc 100644 --- a/components/sidebar/context/strategy/SidebarStrategy.vue +++ b/components/sidebar/context/strategy/SidebarStrategy.vue @@ -24,38 +24,38 @@
-
+
- {{ input.name }} + {{ component.name }} -
- - {{ input.value }} +
+ + {{ component.value }}
@@ -112,7 +112,7 @@ export default defineComponent({ protocolStrategies[props.protocol] || []; const { - inputs, + components, submit, error, strategy: activeStrategy, @@ -122,7 +122,7 @@ export default defineComponent({ ); return { - inputs, + components, error, submit, activeStrategy, diff --git a/composables/useStrategy.ts b/composables/useStrategy.ts index 7b0373c..a71a4b8 100644 --- a/composables/useStrategy.ts +++ b/composables/useStrategy.ts @@ -42,7 +42,7 @@ export function useStrategy(defineStrategy: DefineStrategy) { } = useNotification(); const strategy = buildStrategy(defineStrategy); - const inputs = ref(strategy.inputs); + const components = ref(strategy.components); const error = ref(""); const pending = ref(false); @@ -134,7 +134,7 @@ export function useStrategy(defineStrategy: DefineStrategy) { return { strategy, - inputs, + components, submit, error, pending diff --git a/core/strategies/helpers/index.ts b/core/strategies/helpers/index.ts index 0e6abc3..a288f48 100644 --- a/core/strategies/helpers/index.ts +++ b/core/strategies/helpers/index.ts @@ -8,7 +8,7 @@ import { useFormatting } from "~/composables/useFormatting"; export interface IStrategyContext { dsa: DSA; web3: Web3; - inputs: IStrategyInput[]; + components: IStrategyComponent[]; // TODO: add types in useStrategy.ts dsaBalances?: { [address: string]: IStrategyToken }; @@ -35,7 +35,7 @@ export interface IStrategyToken { // borrow: string; } -export enum StrategyInputType { +export enum StrategyComponentType { // INPUT = "input", INPUT_WITH_TOKEN = "input-with-token", @@ -43,38 +43,38 @@ export enum StrategyInputType { VALUE = "value" } -export type StrategyInputParameterMap = { +export type StrategyComponentParameterMap = { // [StrategyInputType.INPUT]: {}; - [StrategyInputType.INPUT_WITH_TOKEN]: { + [StrategyComponentType.INPUT_WITH_TOKEN]: { token?: IStrategyToken; }; - [StrategyInputType.HEADING]: {}; - [StrategyInputType.VALUE]: {}; + [StrategyComponentType.HEADING]: {}; + [StrategyComponentType.VALUE]: {}; }; -export interface IStrategyInput { - type: InputType; +export interface IStrategyComponent { + type: ComponentType; name: string; variables?: { [key: string]: any }; placeholder?: ( context: IStrategyContext & { - input: IStrategyInput & StrategyInputParameterMap[InputType]; + component: IStrategyComponent & StrategyComponentParameterMap[ComponentType]; } ) => string; validate?: ( context: IStrategyContext & { - input: IStrategyInput & StrategyInputParameterMap[InputType]; + component: IStrategyComponent & StrategyComponentParameterMap[ComponentType]; } ) => string | void; - defaults?: (context: Omit) => object; + defaults?: (context: Omit) => object; update?: ( context: IStrategyContext & { - input: IStrategyInput & StrategyInputParameterMap[InputType]; + component: IStrategyComponent & StrategyComponentParameterMap[ComponentType]; } ) => void; @@ -97,7 +97,7 @@ export interface IStrategy { details?: string; author?: string; - inputs: IStrategyInput[]; + components: IStrategyComponent[]; variables?: object; @@ -109,10 +109,10 @@ export interface IStrategy { submitText?: string; } -export function defineInput( - input: IStrategyInput +export function defineStrategyComponent( + component: IStrategyComponent ) { - return input as IStrategyInput; + return component as IStrategyComponent; } export function defineStrategy(strategy: IStrategy) { diff --git a/core/strategies/helpers/strategy.ts b/core/strategies/helpers/strategy.ts index 425ae7b..cc594f8 100644 --- a/core/strategies/helpers/strategy.ts +++ b/core/strategies/helpers/strategy.ts @@ -4,7 +4,7 @@ import { DefineStrategy, IStrategyContext } from "."; export class Strategy { schema: DefineStrategy; - inputs = []; + components = []; context = { web3: null as Web3, dsa: null as DSA @@ -21,10 +21,10 @@ export class Strategy { constructor(schema: DefineStrategy) { this.schema = schema; - this.inputs = this.generateInputs(this.schema.inputs); + this.components = this.generateComponents(this.schema.components); } - getBaseContext(): Omit { + getBaseContext(): Omit { return { ...this.context, ...this.props, @@ -35,65 +35,65 @@ export class Strategy { getContext(): IStrategyContext { return { ...this.getBaseContext(), - inputs: this.inputs + components: this.components }; } setProps(props: object) { Object.assign(this.props, props); - const inputs = this.inputs; + const components = this.components; - for (const input of inputs) { - if (typeof input.defaults !== "function") { + for (const component of components) { + if (typeof component.defaults !== "function") { continue; } - if (input.defaulted) { + if (component.defaulted) { continue; } - Object.assign(input, input.defaults(this.getBaseContext())); + Object.assign(component, component.defaults(this.getBaseContext())); - input.defaulted = true; + component.defaulted = true; } this.notifyListeners(); } - generateInputs(inputs) { - return inputs.map((input, idx) => { - const computedInput = { - ...input, - value: input.value || "", - error: input.error || "", + generateComponents(components) { + return components.map((component, idx) => { + const computedComponent = { + ...component, + value: component.value || "", + error: component.error || "", placeholder: () => { - return input.placeholder - ? input.placeholder({ + return component.placeholder + ? component.placeholder({ ...this.getContext(), - input: this.inputs[idx] + component: this.components[idx] }) : null; }, onInput: (val: any) => { - this.inputs[idx].error = ""; - this.inputs[idx].value = val; + this.components[idx].error = ""; + this.components[idx].value = val; if (val) { - this.inputs[idx].error = this.inputs[idx].validate({ + this.components[idx].error = this.components[idx].validate({ ...this.getContext(), - input: this.inputs[idx] + component: this.components[idx] }); } this.notifyListeners(); }, onCustomInput: (values: object) => { - this.inputs[idx] = Object.assign(this.inputs[idx], values); + this.components[idx] = Object.assign(this.components[idx], values); - this.inputs[idx].error = this.inputs[idx].validate({ + this.components[idx].error = this.components[idx].validate({ ...this.getContext(), - input: this.inputs[idx] + component: this.components[idx] }); this.notifyListeners(); } @@ -101,12 +101,12 @@ export class Strategy { let defaults = {}; - if (input.defaults) { - defaults = input.defaults(this.getBaseContext()); + if (component.defaults) { + defaults = component.defaults(this.getBaseContext()); } return { - ...computedInput, + ...computedComponent, ...defaults }; }); @@ -135,16 +135,16 @@ export class Strategy { } async validate() { - const inputs = this.inputs; + const components = this.components; - for (const input of inputs) { - if (typeof input.validate !== "function") { + for (const component of components) { + if (typeof component.validate !== "function") { continue; } - const result = await input.validate({ + const result = await component.validate({ ...this.getContext(), - input + component }); if (typeof result === "string") { @@ -178,10 +178,12 @@ export class Strategy { await listener(this); } - this.inputs.forEach(input => input.update?.({ - ...this.getContext(), - input - })); + this.components.forEach(component => + component.update?.({ + ...this.getContext(), + component + }) + ); } onUpdated(cb) { diff --git a/core/strategies/protocols/aave-v2/deposit-and-borrow.ts b/core/strategies/protocols/aave-v2/deposit-and-borrow.ts index c85daa6..7fd4034 100644 --- a/core/strategies/protocols/aave-v2/deposit-and-borrow.ts +++ b/core/strategies/protocols/aave-v2/deposit-and-borrow.ts @@ -1,8 +1,8 @@ import BigNumber from "bignumber.js"; import { defineStrategy, - defineInput, - StrategyInputType, + defineStrategyComponent, + StrategyComponentType, StrategyProtocol } from "../../helpers"; @@ -27,13 +27,13 @@ export default defineStrategy({ debtRateMode: 2 }, - inputs: [ - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Collateral", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Deposit` : "", - validate: ({ input, dsaBalances, toBN }) => { + validate: ({ component: input, dsaBalances, toBN }) => { if (!input.token) { return "Collateral token is required"; } @@ -56,12 +56,12 @@ export default defineStrategy({ }) }), - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Debt", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Borrow` : "", - validate: ({ input }) => { + validate: ({ component: input }) => { if (!input.token) { return "Debt token is required"; } @@ -76,7 +76,7 @@ export default defineStrategy({ }) ], - validate: async ({ position, inputs, toBN }) => { + validate: async ({ position, components: inputs, toBN }) => { if (toBN(inputs[0].value).isZero() && toBN(inputs[1].value).isZero()) { return; } @@ -150,7 +150,7 @@ export default defineStrategy({ } }, - spells: async ({ inputs, convertTokenAmountToWei, variables }) => { + spells: async ({ components: inputs, convertTokenAmountToWei, variables }) => { return [ { connector: "aave_v2", diff --git a/core/strategies/protocols/aave-v2/payback-and-withdraw.ts b/core/strategies/protocols/aave-v2/payback-and-withdraw.ts index 97e8542..fcb66a2 100644 --- a/core/strategies/protocols/aave-v2/payback-and-withdraw.ts +++ b/core/strategies/protocols/aave-v2/payback-and-withdraw.ts @@ -2,8 +2,8 @@ import BigNumber from "bignumber.js"; import tokens from "~/constant/tokens"; import { defineStrategy, - defineInput, - StrategyInputType, + defineStrategyComponent, + StrategyComponentType, StrategyProtocol } from "../../helpers"; @@ -21,13 +21,13 @@ export default defineStrategy({
  • Withdraw collateral
  • `, - inputs: [ - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Debt", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Payback` : "", - validate: ({ input, toBN, dsaBalances }) => { + validate: ({ component: input, toBN, dsaBalances }) => { if (!input.token) { return "Debt token is required"; } @@ -42,12 +42,12 @@ export default defineStrategy({ token: getTokenByKey?.("dai") }) }), - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Collateral", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Withdraw` : "", - validate: ({ input, position, toBN }) => { + validate: ({ component: input, position, toBN }) => { if (!input.token) { return "Collateral token is required"; } @@ -75,7 +75,7 @@ export default defineStrategy({ }) ], - validate: async ({ position, inputs, toBN }) => { + validate: async ({ position, components: inputs, toBN }) => { if (toBN(inputs[0].value).isZero() && toBN(inputs[1].value).isZero()) { return; } @@ -160,7 +160,7 @@ export default defineStrategy({ } }, - spells: async ({ inputs, convertTokenAmountToWei }) => { + spells: async ({ components: inputs, convertTokenAmountToWei }) => { return [ { connector: "aave_v2", diff --git a/core/strategies/protocols/compound/deposit-and-borrow.ts b/core/strategies/protocols/compound/deposit-and-borrow.ts index f24cbc6..4604676 100644 --- a/core/strategies/protocols/compound/deposit-and-borrow.ts +++ b/core/strategies/protocols/compound/deposit-and-borrow.ts @@ -1,8 +1,8 @@ import BigNumber from "bignumber.js"; import { defineStrategy, - defineInput, - StrategyInputType, + defineStrategyComponent, + StrategyComponentType, StrategyProtocol } from "../../helpers"; @@ -26,13 +26,13 @@ export default defineStrategy({ debtTokenKey: "dai" }, - inputs: [ - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Collateral", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Deposit` : "", - validate: ({ input, dsaBalances, toBN }) => { + validate: ({ component: input, dsaBalances, toBN }) => { if (!input.token) { return "Collateral token is required"; } @@ -55,12 +55,12 @@ export default defineStrategy({ }) }), - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Debt", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Borrow` : "", - validate: ({ input }) => { + validate: ({ component: input }) => { if (!input.token) { return "Debt token is required"; } @@ -75,7 +75,7 @@ export default defineStrategy({ }) ], - validate: async ({ position, inputs, toBN, tokenIdMapping }) => { + validate: async ({ position, components: inputs, toBN, tokenIdMapping }) => { if (toBN(inputs[0].value).isZero() && toBN(inputs[1].value).isZero()) { return; } @@ -150,7 +150,7 @@ export default defineStrategy({ } }, - spells: async ({ inputs, convertTokenAmountToWei, tokenIdMapping }) => { + spells: async ({ components: inputs, convertTokenAmountToWei, tokenIdMapping }) => { const { tokenToId } = tokenIdMapping; const collateralTokenId = tokenToId.compound[inputs[0].token.key]; diff --git a/core/strategies/protocols/compound/payback-and-withdraw.ts b/core/strategies/protocols/compound/payback-and-withdraw.ts index 8defa7f..2f390e1 100644 --- a/core/strategies/protocols/compound/payback-and-withdraw.ts +++ b/core/strategies/protocols/compound/payback-and-withdraw.ts @@ -1,8 +1,8 @@ import BigNumber from "bignumber.js"; import { defineStrategy, - defineInput, - StrategyInputType, + defineStrategyComponent, + StrategyComponentType, StrategyProtocol } from "../../helpers"; @@ -20,13 +20,13 @@ export default defineStrategy({
  • Withdraw collateral
  • `, - inputs: [ - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Debt", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Payback` : "", - validate: ({ input, toBN, dsaBalances }) => { + validate: ({ component: input, toBN, dsaBalances }) => { if (!input.token) { return "Debt token is required"; } @@ -41,12 +41,12 @@ export default defineStrategy({ token: getTokenByKey?.("dai") }) }), - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Collateral", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Withdraw` : "", - validate: ({ input, position, toBN, tokenIdMapping }) => { + validate: ({ component: input, position, toBN, tokenIdMapping }) => { if (!input.token) { return "Collateral token is required"; } @@ -79,7 +79,7 @@ export default defineStrategy({ }) ], - validate: async ({ position, inputs, toBN, tokenIdMapping }) => { + validate: async ({ position, components: inputs, toBN, tokenIdMapping }) => { if (toBN(inputs[0].value).isZero() && toBN(inputs[1].value).isZero()) { return; } @@ -154,7 +154,7 @@ export default defineStrategy({ } }, - spells: async ({ inputs, convertTokenAmountToWei, tokenIdMapping }) => { + spells: async ({ components: inputs, convertTokenAmountToWei, tokenIdMapping }) => { const { tokenToId } = tokenIdMapping; const debtTokenId = tokenToId.compound[inputs[0].token.key]; diff --git a/core/strategies/protocols/liquity/close-trove.ts b/core/strategies/protocols/liquity/close-trove.ts index a0bd742..616d15b 100644 --- a/core/strategies/protocols/liquity/close-trove.ts +++ b/core/strategies/protocols/liquity/close-trove.ts @@ -1,8 +1,8 @@ import { defineStrategy, StrategyProtocol, - StrategyInputType, - defineInput + StrategyComponentType, + defineStrategyComponent } from "../../helpers"; export default defineStrategy({ @@ -19,41 +19,41 @@ export default defineStrategy({
  • Close Trove
  • `, - inputs: [ - defineInput({ - type: StrategyInputType.HEADING, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.HEADING, name: "Payback" }), - defineInput({ - type: StrategyInputType.VALUE, + defineStrategyComponent({ + type: StrategyComponentType.VALUE, name: "Net Debt", - update: ({ position, positionExtra, input, formatting, toBN }) => { + update: ({ position, positionExtra, component, formatting, toBN }) => { const troveOverallDetails = positionExtra["troveOverallDetails"]; const netDebt = toBN(position.debt).minus( troveOverallDetails.liquidationReserve ); - input.value = `${formatting.formatDecimal(netDebt, 2)} LUSD`; + component.value = `${formatting.formatDecimal(netDebt, 2)} LUSD`; } }), - defineInput({ - type: StrategyInputType.HEADING, + defineStrategyComponent({ + type: StrategyComponentType.HEADING, name: "Withdraw" }), - defineInput({ - type: StrategyInputType.VALUE, + defineStrategyComponent({ + type: StrategyComponentType.VALUE, name: "Collateral", - update: ({ position, input, formatting }) => { - input.value = `${formatting.formatDecimal(position.collateral, 2)} ETH`; + update: ({ position, component, formatting }) => { + component.value = `${formatting.formatDecimal(position.collateral, 2)} ETH`; } }), - defineInput({ - type: StrategyInputType.VALUE, + defineStrategyComponent({ + type: StrategyComponentType.VALUE, name: "Liquidation Reserve", - update: ({ positionExtra, input, formatting }) => { + update: ({ positionExtra, component, formatting }) => { const troveOverallDetails = positionExtra["troveOverallDetails"]; - input.value = `${formatting.formatDecimal( + component.value = `${formatting.formatDecimal( troveOverallDetails.liquidationReserve, 2 )} LUSD`; diff --git a/core/strategies/protocols/liquity/deposit-and-borrow.ts b/core/strategies/protocols/liquity/deposit-and-borrow.ts index 8185297..f14e0f6 100644 --- a/core/strategies/protocols/liquity/deposit-and-borrow.ts +++ b/core/strategies/protocols/liquity/deposit-and-borrow.ts @@ -2,8 +2,8 @@ import abis from "~/constant/abis"; import addresses from "~/constant/addresses"; import { defineStrategy, - defineInput, - StrategyInputType, + defineStrategyComponent, + StrategyComponentType, StrategyProtocol } from "../../helpers"; @@ -27,13 +27,13 @@ export default defineStrategy({ debtTokenKey: "lusd" }, - inputs: [ - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Collateral", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Deposit` : "", - validate: ({ input, dsaBalances, toBN }) => { + validate: ({ component: input, dsaBalances, toBN }) => { if (!input.token) { return "Collateral token is required"; } @@ -56,12 +56,12 @@ export default defineStrategy({ }) }), - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Debt", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Borrow` : "", - validate: ({ input, toBN, position, positionExtra }) => { + validate: ({ component: input, toBN, position, positionExtra }) => { if (!input.token) { return "Debt token is required"; } @@ -99,7 +99,7 @@ export default defineStrategy({ }) ], - validate: async ({ position, positionExtra, inputs, toBN }) => { + validate: async ({ position, positionExtra, components: inputs, toBN }) => { if (toBN(inputs[0].value).isZero() && toBN(inputs[1].value).isZero()) { return; } @@ -127,7 +127,7 @@ export default defineStrategy({ }, spells: async ({ - inputs, + components: inputs, position, positionExtra, getTokenByKey, diff --git a/core/strategies/protocols/liquity/payback-and-withdraw.ts b/core/strategies/protocols/liquity/payback-and-withdraw.ts index 4cf0916..577438c 100644 --- a/core/strategies/protocols/liquity/payback-and-withdraw.ts +++ b/core/strategies/protocols/liquity/payback-and-withdraw.ts @@ -3,8 +3,8 @@ import abis from "~/constant/abis"; import addresses from "~/constant/addresses"; import { defineStrategy, - defineInput, - StrategyInputType, + defineStrategyComponent, + StrategyComponentType, StrategyProtocol } from "../../helpers"; @@ -22,13 +22,13 @@ export default defineStrategy({
  • Withdraw collateral
  • `, - inputs: [ - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + components: [ + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Debt", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Payback` : "", - validate: ({ input, toBN, position, positionExtra }) => { + validate: ({ component: input, toBN, position, positionExtra }) => { if (!input.token) { return "Debt token is required"; } @@ -64,12 +64,12 @@ export default defineStrategy({ token: getTokenByKey?.("lusd") }) }), - defineInput({ - type: StrategyInputType.INPUT_WITH_TOKEN, + defineStrategyComponent({ + type: StrategyComponentType.INPUT_WITH_TOKEN, name: "Collateral", - placeholder: ({ input }) => + placeholder: ({ component: input }) => input.token ? `${input.token.symbol} to Withdraw` : "", - validate: ({ input, dsaBalances, toBN }) => { + validate: ({ component: input, dsaBalances, toBN }) => { if (!input.token) { return "Collateral token is required"; } @@ -93,7 +93,7 @@ export default defineStrategy({ }) ], - validate: async ({ position, inputs, toBN }) => { + validate: async ({ position, components: inputs, toBN }) => { if (toBN(inputs[0].value).isZero() && toBN(inputs[1].value).isZero()) { return; } @@ -106,7 +106,7 @@ export default defineStrategy({ }, spells: async ({ - inputs, + components: inputs, position, positionExtra, getTokenByKey,