diff --git a/components/Modal/Action.tsx b/components/Modal/Action.tsx index 0fbeeefd..8ef69bd4 100644 --- a/components/Modal/Action.tsx +++ b/components/Modal/Action.tsx @@ -12,7 +12,7 @@ import { supply } from "../../store/actions/supply"; import { deposit } from "../../store/actions/deposit"; import { borrow } from "../../store/actions/borrow"; import { withdraw } from "../../store/actions/withdraw"; -import { shadow_action } from "../../store/actions/shadow"; +import { shadow_action_supply } from "../../store/actions/shadow"; import { adjustCollateral } from "../../store/actions/adjustCollateral"; import { useAppSelector, useAppDispatch } from "../../redux/hooks"; import { getSelectedValues, getAssetData } from "../../redux/appSelectors"; @@ -59,7 +59,7 @@ export default function Action({ maxBorrowAmount, healthFactor, collateralType } if (tokenId === nearTokenId) { await deposit({ amount, useAsCollateral, isMax }); } else if (isLpToken) { - await shadow_action({ + await shadow_action_supply({ tokenId, decimals: +(decimals || 0) + +extraDecimals, useAsCollateral, diff --git a/store/actions/shadow.ts b/store/actions/shadow.ts index 621af67e..a3b22028 100644 --- a/store/actions/shadow.ts +++ b/store/actions/shadow.ts @@ -2,12 +2,12 @@ import Decimal from "decimal.js"; import BN from "bn.js"; import { getBurrow } from "../../utils"; import { expandTokenDecimal, expandToken } from "../helper"; -import { ChangeMethodsREFV1 } from "../../interfaces"; import { prepareAndExecuteTransactions } from "../tokens"; import { Transaction } from "../wallet"; import { NEAR_DECIMALS } from "../constants"; +import { ChangeMethodsREFV1, ChangeMethodsOracle } from "../../interfaces"; -export async function shadow_action({ +export async function shadow_action_supply({ tokenId, decimals, useAsCollateral, @@ -51,3 +51,66 @@ export async function shadow_action({ }); await prepareAndExecuteTransactions(transactions); } +export async function shadow_action_withdraw({ + tokenId, + decimals, + amount, + isMax, + decreaseCollateralAmount, +}: { + tokenId: string; + decimals: number; + amount: string; + isMax: boolean; + decreaseCollateralAmount: Decimal; +}): Promise { + const transactions: Transaction[] = []; + const { refv1Contract, logicContract, oracleContract } = await getBurrow(); + const expandAmount = expandTokenDecimal(amount, decimals).toFixed(0); + const pool_id = +tokenId.split("-")[1]; + if (decreaseCollateralAmount.gt(0)) { + // TODO 待验证 + transactions.push({ + receiverId: oracleContract.contractId, + functionCalls: [ + { + methodName: ChangeMethodsOracle[ChangeMethodsOracle.oracle_call], + gas: new BN("100000000000000"), + args: { + receiver_id: logicContract.contractId, + msg: JSON.stringify({ + Execute: { + actions: [ + { + PositionDecreaseCollateral: { + position: tokenId, + asset_amount: { + token_id: tokenId, + amount: decreaseCollateralAmount.toFixed(0), + }, + }, + }, + ], + }, + }), + }, + }, + ], + }); + } + transactions.push({ + receiverId: refv1Contract.contractId, + functionCalls: [ + { + methodName: ChangeMethodsREFV1[ChangeMethodsREFV1.shadow_action], + args: { + action: "FromBurrowland", + pool_id, + ...(isMax ? {} : { amount: expandAmount }), + msg: "", + }, + }, + ], + }); + await prepareAndExecuteTransactions(transactions); +} diff --git a/store/actions/withdraw.ts b/store/actions/withdraw.ts index 22b99e64..a35bd27f 100644 --- a/store/actions/withdraw.ts +++ b/store/actions/withdraw.ts @@ -14,6 +14,7 @@ import getAccount from "../../api/get-account"; import { transformAccount } from "../../transformers/account"; import { computeWithdrawMaxAmount } from "../../redux/selectors/getWithdrawMaxAmount"; import getConfig from "../../utils/config"; +import { shadow_action_withdraw } from "./shadow"; const { SPECIAL_REGISTRATION_TOKEN_IDS } = getConfig() as any; interface Props { @@ -31,9 +32,8 @@ export async function withdraw({ tokenId, extraDecimals, amount, isMax }: Props) const asset = assets[tokenId]; const { decimals } = asset.metadata; const { logicContract, oracleContract } = await getBurrow(); - const tokenContract = await getTokenContract(tokenId); const isNEAR = tokenId === nearTokenId; - + const { isLpToken } = asset; const suppliedBalance = new Decimal(account.portfolio?.supplied[tokenId]?.balance || 0); const maxAmount = computeWithdrawMaxAmount(tokenId, assets, account.portfolio!); @@ -42,14 +42,49 @@ export async function withdraw({ tokenId, extraDecimals, amount, isMax }: Props) : decimalMin(maxAmount, expandTokenDecimal(amount, decimals + extraDecimals)); const transactions: Transaction[] = []; - - if ( - !(await isRegistered(account.accountId, tokenContract)) && - !NO_STORAGE_DEPOSIT_CONTRACTS.includes(tokenContract.contractId) - ) { - if (SPECIAL_REGISTRATION_TOKEN_IDS.includes(tokenContract.contractId)) { - const r = await isRegisteredNew(account.accountId, tokenContract); - if (r) { + if (isLpToken) { + const decreaseCollateralAmount = decimalMax(expandedAmount.sub(suppliedBalance), 0); + shadow_action_withdraw({ + tokenId, + decimals: decimals + extraDecimals, + amount, + isMax, + decreaseCollateralAmount, + }); + } else { + const tokenContract = await getTokenContract(tokenId); + if ( + !(await isRegistered(account.accountId, tokenContract)) && + !NO_STORAGE_DEPOSIT_CONTRACTS.includes(tokenContract.contractId) + ) { + if (SPECIAL_REGISTRATION_TOKEN_IDS.includes(tokenContract.contractId)) { + const r = await isRegisteredNew(account.accountId, tokenContract); + if (r) { + transactions.push({ + receiverId: tokenContract.contractId, + functionCalls: [ + { + methodName: ChangeMethodsToken[ChangeMethodsToken.storage_deposit], + attachedDeposit: new BN(expandToken(NEAR_STORAGE_DEPOSIT, NEAR_DECIMALS)), + }, + ], + }); + } else { + transactions.push({ + receiverId: tokenContract.contractId, + functionCalls: [ + { + methodName: ChangeMethodsToken[ChangeMethodsToken.register_account], + gas: new BN("10000000000000"), + args: { + account_id: account.accountId, + }, + attachedDeposit: new BN(0), + }, + ], + }); + } + } else { transactions.push({ receiverId: tokenContract.contractId, functionCalls: [ @@ -59,97 +94,71 @@ export async function withdraw({ tokenId, extraDecimals, amount, isMax }: Props) }, ], }); - } else { - transactions.push({ - receiverId: tokenContract.contractId, - functionCalls: [ - { - methodName: ChangeMethodsToken[ChangeMethodsToken.register_account], - gas: new BN("10000000000000"), - args: { - account_id: account.accountId, - }, - attachedDeposit: new BN(0), - }, - ], - }); } + } + + const withdrawAction = { + Withdraw: { + token_id: tokenId, + max_amount: !isMax ? expandedAmount.toFixed(0) : undefined, + }, + }; + + const decreaseCollateralAmount = decimalMax(expandedAmount.sub(suppliedBalance), 0); + + if (decreaseCollateralAmount.gt(0)) { + transactions.push({ + receiverId: oracleContract.contractId, + functionCalls: [ + { + methodName: ChangeMethodsOracle[ChangeMethodsOracle.oracle_call], + gas: new BN("100000000000000"), + args: { + receiver_id: logicContract.contractId, + msg: JSON.stringify({ + Execute: { + actions: [ + { + DecreaseCollateral: { + token_id: tokenId, + amount: decreaseCollateralAmount.toFixed(0), + }, + }, + withdrawAction, + ], + }, + }), + }, + }, + ], + }); } else { transactions.push({ - receiverId: tokenContract.contractId, + receiverId: logicContract.contractId, functionCalls: [ { - methodName: ChangeMethodsToken[ChangeMethodsToken.storage_deposit], - attachedDeposit: new BN(expandToken(NEAR_STORAGE_DEPOSIT, NEAR_DECIMALS)), + methodName: ChangeMethodsLogic[ChangeMethodsLogic.execute], + args: { + actions: [withdrawAction], + }, }, ], }); } - } - - const withdrawAction = { - Withdraw: { - token_id: tokenId, - max_amount: !isMax ? expandedAmount.toFixed(0) : undefined, - }, - }; - - const decreaseCollateralAmount = decimalMax(expandedAmount.sub(suppliedBalance), 0); - - if (decreaseCollateralAmount.gt(0)) { - transactions.push({ - receiverId: oracleContract.contractId, - functionCalls: [ - { - methodName: ChangeMethodsOracle[ChangeMethodsOracle.oracle_call], - gas: new BN("100000000000000"), - args: { - receiver_id: logicContract.contractId, - msg: JSON.stringify({ - Execute: { - actions: [ - { - DecreaseCollateral: { - token_id: tokenId, - amount: decreaseCollateralAmount.toFixed(0), - }, - }, - withdrawAction, - ], - }, - }), - }, - }, - ], - }); - } else { - transactions.push({ - receiverId: logicContract.contractId, - functionCalls: [ - { - methodName: ChangeMethodsLogic[ChangeMethodsLogic.execute], - args: { - actions: [withdrawAction], - }, - }, - ], - }); - } - - // 10 yocto is for rounding errors. - if (isNEAR && expandedAmount.gt(10)) { - transactions.push({ - receiverId: tokenContract.contractId, - functionCalls: [ - { - methodName: ChangeMethodsNearToken[ChangeMethodsNearToken.near_withdraw], - args: { - amount: expandedAmount.sub(10).toFixed(0), + // 10 yocto is for rounding errors. + if (isNEAR && expandedAmount.gt(10)) { + transactions.push({ + receiverId: tokenContract.contractId, + functionCalls: [ + { + methodName: ChangeMethodsNearToken[ChangeMethodsNearToken.near_withdraw], + args: { + amount: expandedAmount.sub(10).toFixed(0), + }, }, - }, - ], - }); + ], + }); + } + await prepareAndExecuteTransactions(transactions); } - - await prepareAndExecuteTransactions(transactions); }