Skip to content

Commit

Permalink
Feat/upgrade portals to v2 (#441)
Browse files Browse the repository at this point in the history
* feat: remove support for Wido solver

* feat: upgrade portals solver to V2

---------

Co-authored-by: Majorfi <[email protected]>
  • Loading branch information
Majorfi and Majorfi authored Nov 29, 2023
1 parent d4bc7a2 commit fd3c8ec
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 86 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Release the multichain config
- Fix the zap balances fetching to use the multichain endpoint rather than the currently connected one
- Deprecate Wido due to project end-of-life
- Bump Portals solver to V2 version

# 0.1.25 (28/08/2023)

Expand Down
1 change: 1 addition & 0 deletions apps/common/schemas/yDaemonTokenListBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const SOLVER = [
'OptimismBooster',
'Cowswap',
'Portals',
'Wido',
'None'
] as const;

Expand Down
6 changes: 3 additions & 3 deletions apps/vaults-v3/components/SettingsPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,19 @@ function ZapSection({chainID}: {chainID: number}): ReactElement {
<select
id={'zapProvider'}
onChange={(e): void => set_zapProvider(e.target.value as TSolver)}
value={!isSolverDisabled(chainID)[currentZapProvider] ? currentZapProvider : Solver.enum.Portals}
value={!isSolverDisabled(currentZapProvider) ? currentZapProvider : Solver.enum.Portals}
className={
'mt-1 h-10 w-full overflow-x-scroll rounded-lg border-none bg-neutral-100 p-2 outline-none scrollbar-none'
}>
{chainID === 1 ? (
<option
disabled={isSolverDisabled(chainID)[Solver.enum.Cowswap]}
disabled={isSolverDisabled(Solver.enum.Cowswap)}
value={Solver.enum.Cowswap}>
{Solver.enum.Cowswap}
</option>
) : null}
<option
disabled={isSolverDisabled(chainID)[Solver.enum.Portals]}
disabled={isSolverDisabled(Solver.enum.Portals)}
value={Solver.enum.Portals}>
{Solver.enum.Portals}
</option>
Expand Down
6 changes: 3 additions & 3 deletions apps/vaults/components/SettingsPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function SettingsPopover({vault}: TSettingPopover): ReactElement {
id={'zapProvider'}
onChange={(e): void => set_zapProvider(e.target.value as TSolver)}
value={
!isSolverDisabled(vault.chainID)[currentZapProvider]
!isSolverDisabled(currentZapProvider)
? currentZapProvider
: Solver.enum.Portals
}
Expand All @@ -78,13 +78,13 @@ export function SettingsPopover({vault}: TSettingPopover): ReactElement {
}>
{vault.chainID === 1 ? (
<option
disabled={isSolverDisabled(vault.chainID)[Solver.enum.Cowswap]}
disabled={isSolverDisabled(Solver.enum.Cowswap)}
value={Solver.enum.Cowswap}>
{Solver.enum.Cowswap}
</option>
) : null}
<option
disabled={isSolverDisabled(vault.chainID)[Solver.enum.Portals]}
disabled={isSolverDisabled(Solver.enum.Portals)}
value={Solver.enum.Portals}>
{Solver.enum.Portals}
</option>
Expand Down
14 changes: 5 additions & 9 deletions apps/vaults/contexts/useSolver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ import {toNormalizedBN} from '@yearn-finance/web-lib/utils/format.bigNumber';
import {Solver} from '@common/schemas/yDaemonTokenListBalances';
import {hash} from '@common/utils';

import type {TDict} from '@yearn-finance/web-lib/types';
import type {TSolver} from '@common/schemas/yDaemonTokenListBalances';
import type {TNormalizedBN} from '@common/types/types';
import type {TInitSolverArgs, TSolverContext, TWithSolver} from '@vaults/types/solvers';

export const isSolverDisabled = (vaultChainID: number): TDict<boolean> => {
return {
export const isSolverDisabled = (key: TSolver): boolean => {
const solverStatus = {
[Solver.enum.Vanilla]: false,
[Solver.enum.PartnerContract]: false,
[Solver.enum.ChainCoin]: false,
[Solver.enum.InternalMigration]: false,
[Solver.enum.OptimismBooster]: false,
[Solver.enum.Cowswap]: false,
[Solver.enum.Portals]: vaultChainID === 10 || false,
[Solver.enum.Portals]: false,
[Solver.enum.None]: false
};
return solverStatus[key as typeof Solver.enum.Vanilla] || false;
};

type TUpdateSolverHandler = {
Expand Down Expand Up @@ -121,11 +121,7 @@ export function WithSolverContextApp({children}: {children: React.ReactElement})
quote: PromiseSettledResult<TNormalizedBN>;
solver: TSolver;
}): boolean => {
return (
quote.status === 'fulfilled' &&
quote?.value.raw > 0n &&
!isSolverDisabled(currentVault.chainID)[solver]
);
return quote.status === 'fulfilled' && quote?.value.raw > 0n && !isSolverDisabled(solver);
};

switch (currentSolver) {
Expand Down
64 changes: 36 additions & 28 deletions apps/vaults/hooks/usePortalsApi.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
import {z} from 'zod';
import {addressSchema} from '@yearn-finance/web-lib/utils/schemas/addressSchema';
import {fetch} from '@common/utils/fetch';

import type {TAddress} from '@yearn-finance/web-lib/types';
import type {TFetchReturn} from '@common/utils/fetch';

export const portalsEstimateResponseSchema = z.object({
buyToken: z.string(),
buyAmount: z.string(),
minBuyAmount: z.string(),
buyTokenDecimals: z.number()
outputToken: z.string(),
outputAmount: z.string(),
minOutputAmount: z.string(),
outputTokenDecimals: z.number()
});

export type TPortalsEstimate = z.infer<typeof portalsEstimateResponseSchema>;

type TGetEstimateProps = {
network: number;
params: {
sellToken: string;
sellAmount: string;
buyToken: string;
slippagePercentage: string;
inputToken: string;
inputAmount: string;
outputToken: string;
slippageTolerancePercentage: string;
};
};

type TGetTransactionProps = Omit<TGetEstimateProps, 'params'> & {
params: Required<Pick<TGetEstimateProps, 'params'>['params']> & {
takerAddress: string;
sender: TAddress;
validate?: string;
};
};
Expand Down Expand Up @@ -66,56 +67,63 @@ const portalsTransactionSchema = z.object({

export type TPortalsTransaction = z.infer<typeof portalsTransactionSchema>;

type TGetApprovalProps = Omit<TGetTransactionProps, 'params'> & {
params: Omit<TGetTransactionProps['params'], 'slippagePercentage'>;
type TGetApprovalProps = {
params: {
sender: TAddress;
inputToken: string;
inputAmount: string;
};
};

const portalsApprovalSchema = z.object({
context: z.object({
network: z.string(),
allowance: z.string(),
approvalAmount: z.string(),
canPermit: z.boolean(),
network: z.string(),
shouldApprove: z.boolean(),
spender: z.string(),
gasLimit: z.string()
}),
tx: portalsTxSchema
spender: addressSchema,
target: addressSchema
})
});

export type TPortalsApproval = z.infer<typeof portalsApprovalSchema>;

const NETWORK = new Map<number, string>([
export const PORTALS_NETWORK = new Map<number, string>([
[1, 'ethereum'],
[10, 'optimism'],
[56, 'bsc'],
[100, 'gnosis'],
[137, 'polygon'],
[250, 'fantom'],
[8453, 'base'],
[42161, 'arbitrum'],
[137, 'polygon'],
[43114, 'avalanche'],
[56, 'bsc']
[43114, 'avalanche']
]);

const BASE_URL = 'https://api.portals.fi/v1';
const BASE_URL = 'https://api.portals.fi/v2';

export async function getPortalsEstimate({network, params}: TGetEstimateProps): TFetchReturn<TPortalsEstimate> {
const url = `${BASE_URL}/portal/${NETWORK.get(network)}/estimate`;
export async function getPortalsEstimate({params}: TGetEstimateProps): TFetchReturn<TPortalsEstimate> {
const url = `${BASE_URL}/portal/estimate`;

console.warn(`${url}?${new URLSearchParams(params)}`);
return fetch<TPortalsEstimate>({
endpoint: `${url}?${new URLSearchParams(params)}`,
schema: portalsEstimateResponseSchema
});
}

export async function getPortalsTx({network, params}: TGetTransactionProps): TFetchReturn<TPortalsTransaction> {
const url = `${BASE_URL}/portal/${NETWORK.get(network)}`;
export async function getPortalsTx({params}: TGetTransactionProps): TFetchReturn<TPortalsTransaction> {
const url = `${BASE_URL}/portal`;

return fetch<TPortalsTransaction>({
endpoint: `${url}?${new URLSearchParams(params)}`,
schema: portalsTransactionSchema
});
}

export async function getPortalsApproval({network, params}: TGetApprovalProps): TFetchReturn<TPortalsApproval> {
const url = `${BASE_URL}/approval/${NETWORK.get(network)}`;
export async function getPortalsApproval({params}: TGetApprovalProps): TFetchReturn<TPortalsApproval> {
const url = `${BASE_URL}/approval`;

return fetch<TPortalsApproval>({
endpoint: `${url}?${new URLSearchParams(params)}`,
Expand Down
4 changes: 4 additions & 0 deletions apps/vaults/hooks/useSolverChainCoin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {useCallback, useMemo, useRef} from 'react';
import {isSolverDisabled} from '@vaults/contexts/useSolver';
import {getEthZapperContract, getNativeTokenWrapperContract} from '@vaults/utils';
import {getVaultEstimateOut} from '@vaults/utils/getVaultEstimateOut';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
Expand Down Expand Up @@ -27,6 +28,9 @@ export function useSolverChainCoin(): TSolverContext {
** call getQuote to get the current quote for the provided request.
**********************************************************************************************/
const init = useCallback(async (_request: TInitSolverArgs): Promise<TNormalizedBN> => {
if (isSolverDisabled(Solver.enum.ChainCoin)) {
return toNormalizedBN(0);
}
request.current = _request;
const wrapperToken = getNativeTokenWrapperContract(_request.chainID);
const estimateOut = await getVaultEstimateOut({
Expand Down
4 changes: 4 additions & 0 deletions apps/vaults/hooks/useSolverCowswap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ethers} from 'ethers';
import {BaseError} from 'viem';
import axios from 'axios';
import {OrderBookApi, OrderQuoteSide, OrderSigningUtils} from '@cowprotocol/cow-sdk';
import {isSolverDisabled} from '@vaults/contexts/useSolver';
import {toast} from '@yearn-finance/web-lib/components/yToast';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import {allowanceKey, isZeroAddress} from '@yearn-finance/web-lib/utils/address';
Expand Down Expand Up @@ -106,6 +107,9 @@ export function useSolverCowswap(): TSolverContext {
**********************************************************************************************/
const init = useCallback(
async (_request: TInitSolverArgs, shouldLogError?: boolean): Promise<TNormalizedBN> => {
if (isSolverDisabled(Solver.enum.Cowswap)) {
return toNormalizedBN(0);
}
/******************************************************************************************
** First we need to know which token we are selling to the zap. When we are depositing, we
** are selling the inputToken, when we are withdrawing, we are selling the outputToken.
Expand Down
4 changes: 4 additions & 0 deletions apps/vaults/hooks/useSolverInternalMigration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {useCallback, useMemo, useRef} from 'react';
import {isSolverDisabled} from '@vaults/contexts/useSolver';
import {getVaultEstimateOut} from '@vaults/utils/getVaultEstimateOut';
import {readContract} from '@wagmi/core';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
Expand Down Expand Up @@ -28,6 +29,9 @@ export function useSolverInternalMigration(): TSolverContext {
** call getQuote to get the current quote for the provided request.
**********************************************************************************************/
const init = useCallback(async (_request: TInitSolverArgs): Promise<TNormalizedBN> => {
if (isSolverDisabled(Solver.enum.InternalMigration)) {
return toNormalizedBN(0);
}
request.current = _request;
if (request.current.migrator === ZAP_YEARN_VE_CRV_ADDRESS) {
const estimateOut = await readContract({
Expand Down
4 changes: 4 additions & 0 deletions apps/vaults/hooks/useSolverOptimismBooster.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {useCallback, useMemo, useRef} from 'react';
import {isSolverDisabled} from '@vaults/contexts/useSolver';
import {depositAndStake} from '@vaults/utils/actions';
import {getVaultEstimateOut} from '@vaults/utils/getVaultEstimateOut';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
Expand Down Expand Up @@ -26,6 +27,9 @@ export function useSolverOptimismBooster(): TSolverContext {
** call getQuote to get the current quote for the provided request.
**********************************************************************************************/
const init = useCallback(async (_request: TInitSolverArgs): Promise<TNormalizedBN> => {
if (isSolverDisabled(Solver.enum.OptimismBooster)) {
return toNormalizedBN(0);
}
request.current = _request;
const estimateOut = await getVaultEstimateOut({
inputToken: toAddress(_request.inputToken.value),
Expand Down
4 changes: 4 additions & 0 deletions apps/vaults/hooks/useSolverPartnerContract.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {useCallback, useMemo, useRef} from 'react';
import {isSolverDisabled} from '@vaults/contexts/useSolver';
import {getVaultEstimateOut} from '@vaults/utils/getVaultEstimateOut';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import {allowanceKey, toAddress} from '@yearn-finance/web-lib/utils/address';
Expand Down Expand Up @@ -28,6 +29,9 @@ export function useSolverPartnerContract(): TSolverContext {
** call getQuote to get the current quote for the provided request.
**********************************************************************************************/
const init = useCallback(async (_request: TInitSolverArgs): Promise<TNormalizedBN> => {
if (isSolverDisabled(Solver.enum.PartnerContract)) {
return toNormalizedBN(0);
}
request.current = _request;
const estimateOut = await getVaultEstimateOut({
inputToken: toAddress(_request.inputToken.value),
Expand Down
Loading

0 comments on commit fd3c8ec

Please sign in to comment.