Skip to content

Commit

Permalink
use services
Browse files Browse the repository at this point in the history
  • Loading branch information
dohaki committed Jan 15, 2025
1 parent eedbc90 commit b33f45b
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 242 deletions.
4 changes: 2 additions & 2 deletions api/swap/approval/_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const quoteFetchStrategies: QuoteFetchStrategies = {
};

export async function handleApprovalSwap(
query: TypedVercelRequest<BaseSwapQueryParams>["query"]
request: TypedVercelRequest<BaseSwapQueryParams>
) {
const {
integratorId,
Expand All @@ -37,7 +37,7 @@ export async function handleApprovalSwap(
depositor,
slippageTolerance,
refundToken,
} = await handleBaseSwapQueryParams(query);
} = await handleBaseSwapQueryParams(request.query);

const crossSwapQuotes = await getCrossSwapQuotes(
{
Expand Down
2 changes: 1 addition & 1 deletion api/swap/approval/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const handler = async (
});
const mark = profiler.start("e2e endpoint runtime");

const responseJson = await handleApprovalSwap(request.query);
const responseJson = await handleApprovalSwap(request);

mark.stop();
logger.debug({
Expand Down
122 changes: 122 additions & 0 deletions api/swap/auth/_service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { assert, Infer, optional, type } from "superstruct";
import { BigNumber } from "ethers";
import * as sdk from "@across-protocol/sdk";

import { TypedVercelRequest } from "../../_types";
import { positiveIntStr } from "../../_utils";
import { getCrossSwapQuotes } from "../../_dexes/cross-swap-service";
import {
handleBaseSwapQueryParams,
BaseSwapQueryParams,
buildBaseSwapResponseJson,
} from "../_utils";
import { getSwapRouter02Strategy } from "../../_dexes/uniswap/swap-router-02";
import { InvalidParamError } from "../../_errors";
import { QuoteFetchStrategies } from "../../_dexes/utils";
import { buildAuthTxPayload } from "./_utils";
import { GAS_SPONSOR_ADDRESS } from "../../relay/_utils";
import { getBalance } from "../../_erc20";

export const AuthSwapQueryParamsSchema = type({
authDeadline: optional(positiveIntStr()),
});

export type AuthSwapQueryParams = Infer<typeof AuthSwapQueryParamsSchema>;

const DEFAULT_AUTH_DEADLINE = sdk.utils.getCurrentTime() + 60 * 60 * 24 * 365; // 1 year

// For auth-based flows, we have to use the `SpokePoolPeriphery` as an entry point
const quoteFetchStrategies: QuoteFetchStrategies = {
default: getSwapRouter02Strategy("SpokePoolPeriphery"),
};

export async function handleAuthSwap(
request: TypedVercelRequest<BaseSwapQueryParams & AuthSwapQueryParams>
) {
const {
authDeadline: _authDeadline,
authStart: _authStart,
...restQuery
} = request.query;
assert(
{
authDeadline: _authDeadline,
},
AuthSwapQueryParamsSchema
);
const authDeadline = Number(_authDeadline ?? DEFAULT_AUTH_DEADLINE);
const authStart = Number(_authStart ?? sdk.utils.getCurrentTime());

if (authDeadline < Math.floor(Date.now() / 1000)) {
throw new InvalidParamError({
message: "auth deadline must be a UNIX timestamp (seconds) in the future",
param: "authDeadline",
});
}

// `/swap` specific params validation + quote generation
const {
isInputNative,
isOutputNative,
inputToken,
outputToken,
amount,
amountType,
refundOnOrigin,
refundAddress,
recipient,
depositor,
slippageTolerance,
refundToken,
} = await handleBaseSwapQueryParams(restQuery);

const crossSwapQuotes = await getCrossSwapQuotes(
{
amount,
inputToken,
outputToken,
depositor,
recipient: recipient || depositor,
slippageTolerance: Number(slippageTolerance),
type: amountType,
refundOnOrigin,
refundAddress,
isInputNative,
isOutputNative,
},
quoteFetchStrategies
);
// Build tx for auth
const crossSwapTxForAuth = await buildAuthTxPayload({
crossSwapQuotes,
authDeadline,
authStart,
// FIXME: Calculate proper fees
submissionFees: {
amount: "0",
recipient: GAS_SPONSOR_ADDRESS,
},
});

const balance = await getBalance({
chainId: inputToken.chainId,
tokenAddress: inputToken.address,
owner: crossSwapQuotes.crossSwap.depositor,
});

const responseJson = buildBaseSwapResponseJson({
inputTokenAddress: inputToken.address,
originChainId: inputToken.chainId,
permitSwapTx: crossSwapTxForAuth,
inputAmount: amount,
bridgeQuote: crossSwapQuotes.bridgeQuote,
originSwapQuote: crossSwapQuotes.originSwapQuote,
destinationSwapQuote: crossSwapQuotes.destinationSwapQuote,
refundToken,
balance,
// Allowance does not matter for auth-based flows
allowance: BigNumber.from(0),
});

return responseJson;
}
120 changes: 5 additions & 115 deletions api/swap/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
import { VercelResponse } from "@vercel/node";
import { assert, Infer, optional, type } from "superstruct";
import { BigNumber } from "ethers";

import { TypedVercelRequest } from "../../_types";
import { getLogger, handleErrorCondition, positiveIntStr } from "../../_utils";
import { getCrossSwapQuotes } from "../../_dexes/cross-swap-service";
import {
handleBaseSwapQueryParams,
BaseSwapQueryParams,
buildBaseSwapResponseJson,
} from "../_utils";
import { getSwapRouter02Strategy } from "../../_dexes/uniswap/swap-router-02";
import { InvalidParamError } from "../../_errors";
import { QuoteFetchStrategies } from "../../_dexes/utils";
import { buildAuthTxPayload } from "./_utils";
import { GAS_SPONSOR_ADDRESS } from "../../relay/_utils";
import * as sdk from "@across-protocol/sdk";
import { getBalance } from "../../_erc20";
import { getLogger, handleErrorCondition } from "../../_utils";
import { BaseSwapQueryParams } from "../_utils";

export const authSwapQueryParamsSchema = type({
authDeadline: optional(positiveIntStr()),
});

export type authSwapQueryParams = Infer<typeof authSwapQueryParamsSchema>;

const DEFAULT_AUTH_DEADLINE = sdk.utils.getCurrentTime() + 60 * 60 * 24 * 365; // 1 year

// For auth-based flows, we have to use the `SpokePoolPeriphery` as an entry point
const quoteFetchStrategies: QuoteFetchStrategies = {
default: getSwapRouter02Strategy("SpokePoolPeriphery"),
};
import { handleAuthSwap, AuthSwapQueryParams } from "./_service";

const handler = async (
request: TypedVercelRequest<BaseSwapQueryParams & authSwapQueryParams>,
request: TypedVercelRequest<BaseSwapQueryParams & AuthSwapQueryParams>,
response: VercelResponse
) => {
const logger = getLogger();
Expand All @@ -42,92 +17,7 @@ const handler = async (
query: request.query,
});
try {
// `/swap/auth` specific params validation
const {
authDeadline: _authDeadline,
authStart: _authStart,
...restQuery
} = request.query;
assert(
{
authDeadline: _authDeadline,
},
authSwapQueryParamsSchema
);
const authDeadline = Number(_authDeadline ?? DEFAULT_AUTH_DEADLINE);
const authStart = Number(_authStart ?? sdk.utils.getCurrentTime());

if (authDeadline < Math.floor(Date.now() / 1000)) {
throw new InvalidParamError({
message:
"auth deadline must be a UNIX timestamp (seconds) in the future",
param: "authDeadline",
});
}

// `/swap` specific params validation + quote generation
const {
isInputNative,
isOutputNative,
inputToken,
outputToken,
amount,
amountType,
refundOnOrigin,
refundAddress,
recipient,
depositor,
slippageTolerance,
refundToken,
} = await handleBaseSwapQueryParams(restQuery);

const crossSwapQuotes = await getCrossSwapQuotes(
{
amount,
inputToken,
outputToken,
depositor,
recipient: recipient || depositor,
slippageTolerance: Number(slippageTolerance),
type: amountType,
refundOnOrigin,
refundAddress,
isInputNative,
isOutputNative,
},
quoteFetchStrategies
);
// Build tx for auth
const crossSwapTxForAuth = await buildAuthTxPayload({
crossSwapQuotes,
authDeadline,
authStart,
// FIXME: Calculate proper fees
submissionFees: {
amount: "0",
recipient: GAS_SPONSOR_ADDRESS,
},
});

const balance = await getBalance({
chainId: inputToken.chainId,
tokenAddress: inputToken.address,
owner: crossSwapQuotes.crossSwap.depositor,
});

const responseJson = buildBaseSwapResponseJson({
inputTokenAddress: inputToken.address,
originChainId: inputToken.chainId,
permitSwapTx: crossSwapTxForAuth,
inputAmount: amount,
bridgeQuote: crossSwapQuotes.bridgeQuote,
originSwapQuote: crossSwapQuotes.originSwapQuote,
destinationSwapQuote: crossSwapQuotes.destinationSwapQuote,
refundToken,
balance,
// Allowance does not matter for auth-based flows
allowance: BigNumber.from(0),
});
const responseJson = await handleAuthSwap(request);

logger.debug({
at: "Swap/auth",
Expand Down
36 changes: 14 additions & 22 deletions api/swap/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
import { VercelResponse } from "@vercel/node";
import axios from "axios";

import { TypedVercelRequest } from "../_types";
import {
getLogger,
handleErrorCondition,
resolveVercelEndpoint,
} from "../_utils";
import { getLogger, handleErrorCondition } from "../_utils";
import { handleBaseSwapQueryParams, BaseSwapQueryParams } from "./_utils";
import { getPermitArgsFromContract } from "../_permit";
import { getReceiveWithAuthArgsFromContract } from "../_transfer-with-auth";
import { handleApprovalSwap } from "./approval/_service";
import { handlePermitSwap } from "./permit/_service";
import { handleAuthSwap } from "./auth/_service";

type SwapFlowType = "permit" | "transfer-with-auth" | "approval";

function makeSwapHandler(path: string) {
return (params: unknown) =>
axios.get(`${resolveVercelEndpoint(true)}/api/swap/${path}`, { params });
}
const swapFlowTypeToHandler = {
// permit: permitHandler,
// "transfer-with-auth": authHandler,
permit: handlePermitSwap,
"transfer-with-auth": handleAuthSwap,
approval: handleApprovalSwap,
};

Expand Down Expand Up @@ -54,17 +47,16 @@ export default async function handler(
getReceiveWithAuthArgsFromContract(args),
]);

// if (permitArgsResult.status === "fulfilled") {
// swapFlowType = "permit";
// } else if (transferWithAuthArgsResult.status === "fulfilled") {
// swapFlowType = "transfer-with-auth";
// } else {
// swapFlowType = "approval";
// }
swapFlowType = "approval";
if (permitArgsResult.status === "fulfilled") {
swapFlowType = "permit";
} else if (transferWithAuthArgsResult.status === "fulfilled") {
swapFlowType = "transfer-with-auth";
} else {
swapFlowType = "approval";
}

const handler = swapFlowTypeToHandler[swapFlowType];
const responseJson = await handler(request.query);
const handler = swapFlowTypeToHandler[swapFlowType as SwapFlowType];
const responseJson = await handler(request);
const enrichedResponseJson = {
...responseJson,
swapFlowType,
Expand Down
Loading

0 comments on commit b33f45b

Please sign in to comment.