Skip to content

Commit

Permalink
Merge branch 'master' into deterministic-relay-hash
Browse files Browse the repository at this point in the history
  • Loading branch information
dohaki authored Feb 3, 2025
2 parents e76302d + 11e27a4 commit 968aece
Show file tree
Hide file tree
Showing 56 changed files with 2,845 additions and 230 deletions.
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,24 @@ updates:
directory: "/"
schedule:
interval: "daily"
groups:
actions-deps:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
groups:
dev-deps:
dependency-type: "development"
prod-deps:
dependency-type: "production"
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
# Packages that need manual upgrades or should be pinned to a specific version
- dependency-name: "@across-protocol/sdk"
- dependency-name: "@across-protocol/contracts"
- dependency-name: "@across-protocol/constants"
- dependency-name: "@balancer-labs/sdk"
2 changes: 1 addition & 1 deletion api/_constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,4 @@ export const DEFAULT_LITE_CHAIN_USD_MAX_BALANCE = "250000";

export const DEFAULT_LITE_CHAIN_USD_MAX_DEPOSIT = "25000";

export const DEFAULT_FILL_DEADLINE_BUFFER_SECONDS = 2.5 * 60 * 60; // 2.5 hours
export const DEFAULT_FILL_DEADLINE_BUFFER_SECONDS = 3.25 * 60 * 60; // 3.25 hours
4 changes: 3 additions & 1 deletion api/available-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ const handler = async (
route.fromTokenSymbol.toUpperCase()) &&
(!destinationTokenSymbol ||
destinationTokenSymbol.toUpperCase() ===
route.toTokenSymbol.toUpperCase()),
route.toTokenSymbol.toUpperCase()) &&
(route as { externalProjectId?: string }).externalProjectId ===
undefined,
// Create a mapping of enabled routes to a route with the destination token resolved.
(route) => ({
originChainId: route.fromChain,
Expand Down
1 change: 1 addition & 0 deletions jest.config.cjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */

module.exports = {
setupFiles: ["<rootDir>/setup.jest.ts"],
preset: "ts-jest",
testEnvironment: "node",
moduleDirectories: ["node_modules", "<rootDir>"],
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
"react-router-dom": "v5",
"react-tooltip": "^5.18.0",
"superstruct": "^0.15.4",
"typescript": "^5.7.3"
"typescript": "^5.7.3",
"viem": "2.x",
"wagmi": "^2.14.9"
},
"scripts": {
"start": "export REACT_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) && vite",
Expand Down Expand Up @@ -132,7 +134,7 @@
"@types/react-dom": "v18",
"@types/react-router-dom": "5.3.3",
"@vercel/node": "^5.0.2",
"@vitejs/plugin-react": "^4.0.1",
"@vitejs/plugin-react": "^4.3.4",
"axios-mock-adapter": "^1.21.2",
"chalk": "^5.3.0",
"chromatic": "^11.25.1",
Expand All @@ -148,7 +150,7 @@
"jest-transform-stub": "^2.0.0",
"lint-staged": "^13.0.3",
"patch-package": "^7.0.0",
"prettier": "3.3.2",
"prettier": "^3.4.2",
"rollup-plugin-visualizer": "^5.12.0",
"storybook": "^7.5.3",
"ts-jest": "^29.1.1",
Expand Down
5 changes: 5 additions & 0 deletions scripts/extern-configs/hyperliquid/assets/grayscale-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions scripts/extern-configs/hyperliquid/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions scripts/extern-configs/hyperliquid/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CHAIN_IDs } from "@across-protocol/constants";
import { ExternalProjectConfig } from "../types";

export default {
name: "Hyperliquid",
projectId: "hyperliquid",
explorer: "https://arbiscan.io",
logoPath: "./assets/logo.svg",
grayscaleLogoPath: "./assets/grayscale-logo.svg",
publicRpcUrl: "https://arbitrum.publicnode.com",
intermediaryChain: CHAIN_IDs.ARBITRUM,
tokens: ["USDC", "USDC.e"],
} as ExternalProjectConfig;
1 change: 1 addition & 0 deletions scripts/extern-configs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as HYPERLIQUID } from "./hyperliquid";
13 changes: 13 additions & 0 deletions scripts/extern-configs/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Destination only projects that are supported through a message bridge
// at a known supported intermediary chain
export type ExternalProjectConfig = {
projectId: string;
name: string;
fullName?: string;
explorer: string;
publicRpcUrl: string;
logoPath: string;
grayscaleLogoPath: string;
intermediaryChain: number;
tokens: string[];
};
186 changes: 182 additions & 4 deletions scripts/generate-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { writeFileSync } from "fs";
import * as prettier from "prettier";
import path from "path";
import * as chainConfigs from "./chain-configs";
import * as externConfigs from "./extern-configs";
import assert from "assert";

function getTokenSymbolForLogo(tokenSymbol: string): string {
switch (tokenSymbol) {
Expand All @@ -29,6 +31,8 @@ type ToToken = ToChain["tokens"][number];
type SwapToken = ToChain["swapTokens"][number];
type ValidTokenSymbol = string;

const enabledMainnetExternalProjects = [externConfigs.HYPERLIQUID];

const enabledMainnetChainConfigs = [
chainConfigs.MAINNET,
chainConfigs.OPTIMISM,
Expand Down Expand Up @@ -109,7 +113,10 @@ const enabledRoutes = {
// [CHAIN_IDs.BASE]: "0xbcfbCE9D92A516e3e7b0762AE218B4194adE34b4",
},
},
routes: transformChainConfigs(enabledMainnetChainConfigs),
routes: transformChainConfigs(
enabledMainnetChainConfigs,
enabledMainnetExternalProjects
),
},
[CHAIN_IDs.SEPOLIA]: {
hubPoolChain: CHAIN_IDs.SEPOLIA,
Expand All @@ -136,18 +143,21 @@ const enabledRoutes = {
"0x17496824Ba574A4e9De80110A91207c4c63e552a", // Mocked
},
},
routes: transformChainConfigs(enabledSepoliaChainConfigs),
routes: transformChainConfigs(enabledSepoliaChainConfigs, []),
},
} as const;

function transformChainConfigs(
enabledChainConfigs: typeof enabledMainnetChainConfigs
enabledChainConfigs: typeof enabledMainnetChainConfigs,
enabledExternalProjects: typeof enabledMainnetExternalProjects
) {
const transformedChainConfigs: {
fromChain: number;
fromSpokeAddress: string;
externalProjectId?: string;
toChains: {
chainId: number;
externalProjectId?: string;
tokens: (
| string
| {
Expand Down Expand Up @@ -276,6 +286,7 @@ function transformChainConfigs(
];
}

// Handle WGRASS -> GRASS
if (
tokenSymbol === "WGRASS" &&
toChainConfig.tokens.includes("GRASS")
Expand Down Expand Up @@ -342,6 +353,47 @@ function transformChainConfigs(
toChains.push(toChain);
}

for (const externalProject of enabledExternalProjects) {
if (externalProject.intermediaryChain === fromChainId) {
continue;
}
const associatedChain = enabledChainConfigs.find(
(config) => config.chainId === externalProject.intermediaryChain
);
assert(associatedChain, "Associated chain not found");

let associatedRoutes = processTokenRoutes(
chainConfig,
{ ...associatedChain, enableCCTP: false },
externalProject.tokens
);

const externalProjectId = externalProject.projectId;

// Handle USDC swap tokens
const usdcSwapTokens = [];

const toChain = {
chainId: externalProject.intermediaryChain,
externalProjectId,
tokens: associatedRoutes,
swapTokens: usdcSwapTokens.filter(
({ acrossInputTokenSymbol, acrossOutputTokenSymbol }) =>
associatedRoutes.some((token) =>
typeof token === "string"
? token === acrossInputTokenSymbol
: token.inputTokenSymbol === acrossInputTokenSymbol
) &&
associatedRoutes.some((token) =>
typeof token === "string"
? token === acrossOutputTokenSymbol
: token.outputTokenSymbol === acrossOutputTokenSymbol
)
),
};
toChains.push(toChain);
}

transformedChainConfigs.push({
fromChain: fromChainId,
fromSpokeAddress,
Expand All @@ -352,6 +404,126 @@ function transformChainConfigs(
return transformedChainConfigs;
}

function processTokenRoutes(
fromConfig: typeof chainConfigs.MAINNET,
toConfig: typeof chainConfigs.MAINNET,
tokensToProcess?: string[]
) {
const toChainId = toConfig.chainId;
const tokens = tokensToProcess ?? fromConfig.tokens;
return tokens.flatMap((token) => {
const tokenSymbol = typeof token === "string" ? token : token.symbol;

// If the fromConfig does not support the token, return an empty array
if (!fromConfig.tokens.includes(tokenSymbol)) {
return [];
}

// Handle native USDC -> bridged USDC routes
if (tokenSymbol === "USDC") {
if (toConfig.enableCCTP) {
return [
"USDC",
{
inputTokenSymbol: "USDC",
outputTokenSymbol: getBridgedUsdcSymbol(toChainId),
},
];
} else if (
toConfig.tokens.find(
(token) => typeof token === "string" && sdkUtils.isBridgedUsdc(token)
)
) {
return [
{
inputTokenSymbol: "USDC",
outputTokenSymbol: getBridgedUsdcSymbol(toChainId),
},
];
}
}

// Handle bridged USDC -> native/bridged USDC routes
if (sdkUtils.isBridgedUsdc(tokenSymbol)) {
if (toConfig.enableCCTP) {
return [
{
inputTokenSymbol: tokenSymbol,
outputTokenSymbol: "USDC",
},
{
inputTokenSymbol: tokenSymbol,
outputTokenSymbol: getBridgedUsdcSymbol(toChainId),
},
];
} else if (toConfig.tokens.includes("USDC")) {
return [
{
inputTokenSymbol: tokenSymbol,
outputTokenSymbol: "USDC",
},
];
} else if (
toConfig.tokens.find(
(token) => typeof token === "string" && sdkUtils.isBridgedUsdc(token)
)
) {
return [
{
inputTokenSymbol: tokenSymbol,
outputTokenSymbol: getBridgedUsdcSymbol(toChainId),
},
];
}
}

// Handle USDB -> DAI
if (tokenSymbol === "USDB" && toConfig.tokens.includes("DAI")) {
return [
{
inputTokenSymbol: "USDB",
outputTokenSymbol: "DAI",
},
];
}
if (tokenSymbol === "DAI" && toConfig.tokens.includes("USDB")) {
return [
{
inputTokenSymbol: "DAI",
outputTokenSymbol: "USDB",
},
];
}

// Handle WETH Polygon & other non-eth chains
if (
tokenSymbol === "WETH" &&
!toConfig.tokens.includes("ETH") &&
fromConfig.tokens.includes("ETH")
) {
return ["WETH", "ETH"];
}

const chainIds = typeof token === "string" ? [toChainId] : token.chainIds;

const toToken = toConfig.tokens.find((token) =>
typeof token === "string"
? token === tokenSymbol
: token.symbol === tokenSymbol
);
if (
!toToken ||
(typeof toToken === "object" &&
!toToken.chainIds.includes(fromConfig.chainId)) ||
!chainIds.includes(toChainId)
) {
return [];
}

return tokenSymbol;
});
}

async function generateRoutes(hubPoolChainId = 1) {
const config = enabledRoutes[hubPoolChainId];

Expand Down Expand Up @@ -563,6 +735,11 @@ function transformToRoute(
throw new Error("Mismatching L1 addresses");
}

const fromChain = Object.values(chainConfigs).find(
(config) => config.chainId === route.fromChain
)!;
const isNative = inputTokenSymbol === fromChain.nativeToken;

return {
fromChain: route.fromChain,
toChain: toChain.chainId,
Expand All @@ -571,8 +748,9 @@ function transformToRoute(
fromSpokeAddress: utils.getAddress(route.fromSpokeAddress),
fromTokenSymbol: inputTokenSymbol,
toTokenSymbol: outputTokenSymbol,
isNative: inputTokenSymbol === TOKEN_SYMBOLS_MAP.ETH.symbol,
isNative,
l1TokenAddress: inputToken.l1TokenAddress,
externalProjectId: toChain.externalProjectId,
};
}

Expand Down
Loading

0 comments on commit 968aece

Please sign in to comment.