diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 36a68486af..4260f106c4 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ -blank_issues_enabled: false -contact_links: - - name: Ask Question - url: https://github.com/sushiswap/sushiswap/discussions/new?category=q-a - about: Ask questions and discuss with other community members - - name: Request Feature - url: https://github.com/sushiswap/sushiswap/discussions/new?category=ideas - about: Requests features or brainstorm ideas for new functionality \ No newline at end of file +# blank_issues_enabled: false +# contact_links: +# - name: Ask Question +# url: https://github.com/sushiswap/sushiswap/discussions/new?category=q-a +# about: Ask questions and discuss with other community members +# - name: Request Feature +# url: https://github.com/sushiswap/sushiswap/discussions/new?category=ideas +# about: Requests features or brainstorm ideas for new functionality \ No newline at end of file diff --git a/.github/workflows/apps-evm-e2e.yml b/.github/workflows/apps-evm-e2e.yml index f904322af4..9d31c18446 100644 --- a/.github/workflows/apps-evm-e2e.yml +++ b/.github/workflows/apps-evm-e2e.yml @@ -1,18 +1,18 @@ name: Sushi - apps / evm on: - pull_request: - types: [opened, synchronize] - paths: - - ".github/workflows/apps-evm-e2e.yml" - - "apps/evm/**" - - "config/nextjs/**" - - "config/router/**" - - "config/tailwindcss/**" - - "config/typescript/**" - - "config/viem/**" - - "config/wagmi/**" - - "packages/**" + # pull_request: + # types: [opened, synchronize] + # paths: + # - ".github/workflows/apps-evm-e2e.yml" + # - "apps/evm/**" + # - "config/nextjs/**" + # - "config/router/**" + # - "config/tailwindcss/**" + # - "config/typescript/**" + # - "config/viem/**" + # - "config/wagmi/**" + # - "packages/**" workflow_dispatch: env: diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 150bed71ea..52dd4c8bd5 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -1,12 +1,13 @@ name: 'Chromatic' on: - pull_request: - types: [opened, synchronize] - paths: - - ".github/workflows/chromatic.yml" - - "config/tailwindcss/**" - - "packages/ui/**" + # pull_request: + # types: [opened, synchronize] + # paths: + # - ".github/workflows/chromatic.yml" + # - "config/tailwindcss/**" + # - "packages/ui/**" + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true diff --git a/.github/workflows/git-clean.yml b/.github/workflows/git-clean.yml new file mode 100644 index 0000000000..407507c92c --- /dev/null +++ b/.github/workflows/git-clean.yml @@ -0,0 +1,38 @@ +name: Git is clean +on: [push] + +concurrency: + group: ${{ github.ref }}-git-clean + cancel-in-progress: ${{ github.ref != 'refs/heads/rain-fork' }} + +jobs: + git-clean: + permissions: + id-token: write + contents: read + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Install Nix 1/2 + uses: DeterminateSystems/nix-installer-action@main + with: + determinate: true + - name: Install Nix 2/2 + uses: DeterminateSystems/flakehub-cache-action@main + + - name: Install deps + run: nix develop -c pnpm install --frozen-lockfile + + - name: Build ./packages/sushi + run: nix develop -c pnpm exec turbo run build --filter=./packages/sushi + + - name: Lint + run: nix develop -c pnpm lint + + - run: git diff --exit-code + + - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main diff --git a/.github/workflows/rain-ci.yml b/.github/workflows/rain-ci.yml new file mode 100644 index 0000000000..4af696cf4b --- /dev/null +++ b/.github/workflows/rain-ci.yml @@ -0,0 +1,85 @@ +name: Rain CI +on: [push] + +concurrency: + group: ${{ github.ref }}-rainix + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + router-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: DeterminateSystems/nix-installer-action@v4 + - uses: DeterminateSystems/magic-nix-cache-action@v2 + + - name: Install deps + run: nix develop -c pnpm install --frozen-lockfile + + - name: Build ./packages/sushi + run: nix develop -c pnpm exec turbo run build --filter=./packages/sushi + + - name: Lint + run: nix develop -c pnpm lint + + - name: Check ./packages/sushi Types + run: nix develop -c pnpm exec turbo run check --filter=./packages/sushi + + - name: Test ./packages/sushi + run: nix develop -c pnpm exec turbo run test --filter=./packages/sushi + + datafetcher-test: + strategy: + fail-fast: false + # chains to run datafetcher on (all supported chains) + matrix: + chain: [ + ETHEREUM, + POLYGON, + FANTOM, + GNOSIS, + BSC, + ARBITRUM, + ARBITRUM_NOVA, + AVALANCHE, + HARMONY, + OKEX, + CELO, + MOONRIVER, + FUSE, + TELOS, + MOONBEAM, + OPTIMISM, + KAVA, + METIS, + BOBA, + BOBA_BNB, + BTTC, + POLYGON_ZKEVM, + THUNDERCORE, + FILECOIN, + HAQQ, + CORE, + LINEA, + BASE, + SCROLL, + ZETACHAIN, + CRONOS, + BLAST, + FLARE, + ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: DeterminateSystems/nix-installer-action@v4 + - uses: DeterminateSystems/magic-nix-cache-action@v2 + + - name: Install deps + run: nix develop -c pnpm install --frozen-lockfile + + - name: Test DataFecther + run: nix develop -c pnpm exec turbo run test --filter=./protocols/route-processor + env: + CHAIN: ${{ matrix.chain }} \ No newline at end of file diff --git a/.github/workflows/rain-release.yml b/.github/workflows/rain-release.yml new file mode 100644 index 0000000000..db6317ccf5 --- /dev/null +++ b/.github/workflows/rain-release.yml @@ -0,0 +1,57 @@ +# creates a github release with packed tarball (.tgz) for sushi pkg +name: Create GitHub Release +on: ["workflow_dispatch"] + +jobs: + release: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + steps: + - uses: actions/checkout@v4 + with: + ssh-key: ${{ secrets.PUBLISH_PRIVATE_KEY }} + + - uses: DeterminateSystems/nix-installer-action@main + with: + determinate: true + - uses: DeterminateSystems/flakehub-cache-action@main + + - run: nix develop -c pnpm install --frozen-lockfile + - run: nix develop -c pnpm exec turbo run build --filter=./packages/sushi + + - name: Git Config + run: | + git config --global user.email "${{ secrets.CI_GIT_EMAIL }}" + git config --global user.name "${{ secrets.CI_GIT_USER }}" + + # create tag + - name: Create Tag + run: git tag sushi-${{ github.sha }} + + # Push the tag to remote + - name: Push Changes To Remote + run: git push origin sushi-${{ github.sha }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Create sushi npm package tarball + - name: Create sushi NPM Package Tarball + run: echo "NPM_PACKAGE=$(nix develop -c pnpm pack)" >> $GITHUB_ENV + working-directory: packages/sushi + + - name: Rename sushi NPM Package Tarball + run: mv ${{ env.NPM_PACKAGE }} ../../sushi-${{ github.sha }}.tgz + working-directory: packages/sushi + + # Create a gitHub release with tarball + - name: Create GitHub Release with sushi pkg + id: gh_release + uses: softprops/action-gh-release@v2 + with: + tag_name: sushi-${{ github.sha }} + name: Sushi NPM Package Release ${{ github.sha }} + files: sushi-${{ github.sha }}.tgz + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index fc63f6dbc4..b696c5da82 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -3,8 +3,9 @@ name: Sushi - verify # workflow_call: # workflow_dispatch: on: - pull_request: - types: [opened, synchronize] + # pull_request: + # types: [opened, synchronize] + workflow_dispatch: env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }} diff --git a/.gitignore b/.gitignore index 128f57f1b7..756ce12afc 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,8 @@ exports # cache cache +mem-cache +test-cache # generated generated diff --git a/apis/extractor/package.json b/apis/extractor/package.json index 0827c75624..98c5926ddd 100644 --- a/apis/extractor/package.json +++ b/apis/extractor/package.json @@ -35,9 +35,9 @@ "dotenv": "16.3.1", "express": "4.18.2", "sushi": "workspace:*", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20", - "zod": "3.21.4" + "zod": "3.22.0" }, "devDependencies": { "@tsconfig/esm": "1.0.4", diff --git a/apis/router/package.json b/apis/router/package.json index 19ecadb05e..65ec2f06b3 100644 --- a/apis/router/package.json +++ b/apis/router/package.json @@ -36,9 +36,9 @@ "dotenv": "16.3.1", "express": "4.18.2", "sushi": "workspace:*", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20", - "zod": "3.21.4" + "zod": "3.22.0" }, "devDependencies": { "@tsconfig/esm": "1.0.4", diff --git a/apis/tokens/package.json b/apis/tokens/package.json index 2c16debcac..d28af20c12 100644 --- a/apis/tokens/package.json +++ b/apis/tokens/package.json @@ -34,8 +34,8 @@ "drizzle-orm": "^0.29.5", "postgres": "^3.4.3", "sushi": "workspace:*", - "viem": "2.8.14", - "zod": "3.21.4" + "viem": "2.21.35", + "zod": "3.22.0" }, "devDependencies": { "@sushiswap/jest-config": "workspace:*", diff --git a/apps/evm/package.json b/apps/evm/package.json index ff2656f74b..f404c43c1a 100644 --- a/apps/evm/package.json +++ b/apps/evm/package.json @@ -74,9 +74,9 @@ "sushi": "workspace:*", "swr": "2.1.5", "tiny-invariant": "1.3.1", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20", - "zod": "3.21.4" + "zod": "3.22.0" }, "devDependencies": { "@0xsquid/squid-types": "^0.1.59", diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..89f23ddbe0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,300 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "foundry": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1714727549, + "narHash": "sha256-CWXRTxxcgMfQubJugpeg3yVWIfm70MYTtgaKWKgD60U=", + "owner": "shazow", + "repo": "foundry.nix", + "rev": "47cf189ec395eda4b3e0623179d1075c8027ca97", + "type": "github" + }, + "original": { + "owner": "shazow", + "ref": "monthly", + "repo": "foundry.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1666753130, + "narHash": "sha256-Wff1dGPFSneXJLI2c0kkdWTgxnQ416KE6X4KnFkgPYQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f540aeda6f677354f1e7144ab04352f61aaa0118", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1714764285, + "narHash": "sha256-oeevp27kMeDjKdxaTyXyS14TLjJrpJhXp7UVEUdYqYs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d121ce778b2609ae9e749a711295ffca013a82c4", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1706487304, + "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1708564076, + "narHash": "sha256-KKkqoxlgx9n3nwST7O2kM8tliDOijiSSNaWuSkiozdQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "98b00b6947a9214381112bdb6f89c25498db4959", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "rainix": { + "inputs": { + "flake-utils": "flake-utils_2", + "foundry": "foundry", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay", + "solc": "solc" + }, + "locked": { + "lastModified": 1714764843, + "narHash": "sha256-7ae0pHvjlInc1V3QxjW5iNhXAYerO1/fhLgzQnPNPjE=", + "owner": "rainprotocol", + "repo": "rainix", + "rev": "f3bdb28f353f8cba28b2bba86f79c362dd65ee53", + "type": "github" + }, + "original": { + "owner": "rainprotocol", + "repo": "rainix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "rainix": "rainix" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1714702555, + "narHash": "sha256-/NoUbE5S5xpK1FU3nlHhQ/tL126+JcisXdzy3Ng4pDU=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "7f0e3ef7b7fbed78e12e5100851175d28af4b7c6", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "solc": { + "inputs": { + "flake-utils": "flake-utils_5", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1711538161, + "narHash": "sha256-rETVdEIQ2PyEcNgzXXFSiYAYl0koCeGDIWp9XYBTxoQ=", + "owner": "hellwolf", + "repo": "solc.nix", + "rev": "a995838545a7383a0b37776e969743b1346d5479", + "type": "github" + }, + "original": { + "owner": "hellwolf", + "repo": "solc.nix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..b58bce3335 --- /dev/null +++ b/flake.nix @@ -0,0 +1,22 @@ +{ + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + rainix.url = "github:rainprotocol/rainix"; + }; + + outputs = { self, flake-utils, rainix }: + + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = rainix.pkgs.${system}; + in { + # For `nix develop`: + devShell = pkgs.mkShell { + nativeBuildInputs = [ + rainix.node-build-inputs.${system} + pkgs.nodePackages.pnpm + ]; + }; + } + ); +} \ No newline at end of file diff --git a/jobs/pool/package.json b/jobs/pool/package.json index be955fb123..6e8494a113 100644 --- a/jobs/pool/package.json +++ b/jobs/pool/package.json @@ -71,8 +71,8 @@ "lodash.zip": "4.2.0", "sushi": "workspace:*", "tsx": "^4.7.1", - "viem": "2.8.14", - "zod": "3.21.4" + "viem": "2.21.35", + "zod": "3.22.0" }, "devDependencies": { "@sushiswap/jest-config": "workspace:*", diff --git a/package.json b/package.json index 6d643bcb16..e4fbc713b3 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "packageManager": "pnpm@8.15.3", "engines": { "node": ">=20.x", - "pnpm": "8.15.3" + "pnpm": ">=8.15.3" }, "pnpm": { "overrides": { diff --git a/packages/bonds-sdk/package.json b/packages/bonds-sdk/package.json index 308b00ec84..9fea95bd8c 100644 --- a/packages/bonds-sdk/package.json +++ b/packages/bonds-sdk/package.json @@ -67,7 +67,7 @@ "jest": "29.7.0", "ts-jest": "29.1.1", "typescript": "5.2.2", - "viem": "2.8.14" + "viem": "2.21.35" }, "peerDependencies": { "react": "18.2.0", diff --git a/packages/client/package.json b/packages/client/package.json index fd3c8881df..e4d306211f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -72,8 +72,8 @@ "@whatwg-node/fetch": "0.8.4", "deepmerge-ts": "^4.3.0", "tslib": "latest", - "viem": "2.8.14", - "zod": "3.21.4" + "viem": "2.21.35", + "zod": "3.22.0" }, "devDependencies": { "@sushiswap/jest-config": "workspace:*", diff --git a/packages/extractor/package.json b/packages/extractor/package.json index dc151c44c5..7e40cb893e 100644 --- a/packages/extractor/package.json +++ b/packages/extractor/package.json @@ -36,7 +36,7 @@ "@uniswap/v3-core": "1.0.1", "abitype": "0.9.8", "sushi": "workspace:*", - "viem": "2.8.14" + "viem": "2.21.35" }, "devDependencies": { "@sushiswap/jest-config": "workspace:*", diff --git a/packages/hooks/src/usePinnedTokens.ts b/packages/hooks/src/usePinnedTokens.ts index 7950e52b33..3b3e69f478 100644 --- a/packages/hooks/src/usePinnedTokens.ts +++ b/packages/hooks/src/usePinnedTokens.ts @@ -12,6 +12,11 @@ import { import { ARB, DAI, + ENOSYS_APS, + ENOSYS_BNZ, + ENOSYS_EETH, + ENOSYS_EQNT, + ENOSYS_HLN, FRAX, GNO, MATIC, @@ -353,6 +358,17 @@ export const DEFAULT_BASES = { USDC[ChainId.CRONOS], ], [ChainId.BLAST]: [Native.onChain(ChainId.BLAST), USDB[ChainId.BLAST]], + [ChainId.FLARE]: [ + Native.onChain(ChainId.FLARE), + WNATIVE[ChainId.FLARE], + WETH9[ChainId.FLARE], + USDT[ChainId.FLARE], + ENOSYS_BNZ, + ENOSYS_EQNT, + ENOSYS_HLN, + ENOSYS_APS, + ENOSYS_EETH, + ], // [ChainId.SEPOLIA]: [Native.onChain(ChainId.SEPOLIA), WNATIVE[ChainId.SEPOLIA]], } as const satisfies Record> diff --git a/packages/react-query/package.json b/packages/react-query/package.json index 2235894d7a..26abeffd25 100644 --- a/packages/react-query/package.json +++ b/packages/react-query/package.json @@ -50,7 +50,7 @@ "idb-keyval": "6.2.0", "ms": "2.1.3", "nanoid": "4.0.0", - "zod": "3.21.4" + "zod": "3.22.0" }, "devDependencies": { "@sentry/nextjs": "7.101.1", @@ -68,7 +68,7 @@ "react-dom": "18.2.0", "sushi": "workspace:*", "typescript": "5.2.2", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20" }, "peerDependencies": { @@ -78,7 +78,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "sushi": "*", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20" }, "peerDependenciesMeta": { diff --git a/packages/steer-sdk/package.json b/packages/steer-sdk/package.json index daffcd2092..47e0e2fdb9 100644 --- a/packages/steer-sdk/package.json +++ b/packages/steer-sdk/package.json @@ -62,7 +62,7 @@ "@whatwg-node/fetch": "0.8.4", "sushi": "workspace:*", "tslib": "latest", - "viem": "2.8.14" + "viem": "2.21.35" }, "devDependencies": { "@sushiswap/jest-config": "workspace:*", diff --git a/packages/sushi/README.md b/packages/sushi/README.md index 26720c70cd..86eb1c812f 100644 --- a/packages/sushi/README.md +++ b/packages/sushi/README.md @@ -1,3 +1,70 @@ # Sushi -Sushi library \ No newline at end of file +Sushi library + + +## RainDataFetcher (sushi indexer router) Usage Example +This is a simple example for using `RainDataFetcher`, read the docs of methods of `RainDataFetcher` for more details: + +```ts +import { ChainId } from "sushi/chain"; +import { Token } from "sushi/currency"; +import { publicClientConfig } from "sushi/config"; +import { createPublicClient, http, parseUnits } from "viem"; +import { LiquidityProviders, RainDataFetcher } from "sushi"; + +// create viem client +const chain = publicClientConfig[ChainId.ARBITRUM].chain; +const client = createPublicClient({ + chain, + transport: http("https://rpc.com"), +}); + +// specify a list liquidity providers +const specifiedLiquidityProviders = [LiquidityProviders.UniswapV2, LiquidityProviders.SushiSwapV3]; +const router = await RainDataFetcher.init( + ChainId.ARBITRUM, + client, + specifiedLiquidityProviders, // do not pass this param to have all available liquidity providers for the operating chain +); + +// sync the pools data every 10 secs in the background, this is very cheap using a few eth_getLogs calls but keeps all data synced +setInterval(async () => { + const untilBlockNumber = 123n; // optional, set to undefined to update pools data to latest block + await router.updatePools(untilBlockNumber); +}, 10_000); + +// build tokens +const fromToken = new Token({ + chainId: ChainId.ARBITRUM, + decimals: 18, + address: "0x123...", + symbol: "SYM" +}); +const toToken = new Token({ + chainId: ChainId.ARBITRUM, + decimals: 6, + address: "0x123...", + symbol: "SYM" +}); + +// 1.2 as amountIn +// also can set to 1 for a unit market result +const amountIn = parseUnits("1.2", fromToken.decimals); + +// get the best route +const gasPrice = await client.getGasPrice(); +const { pcMap, route } = await router.findBestRoute( + ChainId.ARBITRUM, + fromToken, + toToken, + amountIn, + Number(gasPrice), +); + +if (route.status == "NoWay") { + throw new Error("did not find any route"); +} else { + return route.amountOutBI; // the received amount of toToken for the given amountIn of fromToken +} +``` diff --git a/packages/sushi/package.json b/packages/sushi/package.json index 25cd6a9be0..8a517bc9da 100644 --- a/packages/sushi/package.json +++ b/packages/sushi/package.json @@ -22,158 +22,222 @@ ], "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./dist/types/index.d.ts", + "node": "./dist/cjs/index.js", + "require": "./dist/cjs/index.js", + "import": "./dist/esm/index.js", + "default": "./dist/cjs/index.js" }, "./abi": { - "types": "./dist/abi/index.d.ts", - "default": "./dist/abi/index.js" + "types": "./dist/types/abi/index.d.ts", + "node": "./dist/cjs/abi/index.js", + "require": "./dist/cjs/abi/index.js", + "import": "./dist/esm/abi/index.js", + "default": "./dist/cjs/abi/index.js" }, "./calculate": { - "types": "./dist/calculate/index.d.ts", - "default": "./dist/calculate/index.js" + "types": "./dist/types/calculate/index.d.ts", + "node": "./dist/cjs/calculate/index.js", + "require": "./dist/cjs/calculate/index.js", + "import": "./dist/esm/calculate/index.js", + "default": "./dist/cjs/calculate/index.js" }, "./chain": { - "types": "./dist/chain/index.d.ts", - "default": "./dist/chain/index.js" + "types": "./dist/types/chain/index.d.ts", + "node": "./dist/cjs/chain/index.js", + "require": "./dist/cjs/chain/index.js", + "import": "./dist/esm/chain/index.js", + "default": "./dist/cjs/chain/index.js" }, "./config": { - "types": "./dist/config/index.d.ts", - "default": "./dist/config/index.js" + "types": "./dist/types/config/index.d.ts", + "node": "./dist/cjs/config/index.js", + "require": "./dist/cjs/config/index.js", + "import": "./dist/esm/config/index.js", + "default": "./dist/cjs/config/index.js" }, "./contract": { - "types": "./dist/contract/index.d.ts", - "default": "./dist/contract/index.js" + "types": "./dist/types/contract/index.d.ts", + "node": "./dist/cjs/contract/index.js", + "require": "./dist/cjs/contract/index.js", + "import": "./dist/esm/contract/index.js", + "default": "./dist/cjs/contract/index.js" }, "./convert": { - "types": "./dist/convert/index.d.ts", - "default": "./dist/convert/index.js" + "types": "./dist/types/convert/index.d.ts", + "node": "./dist/cjs/convert/index.js", + "require": "./dist/cjs/convert/index.js", + "import": "./dist/esm/convert/index.js", + "default": "./dist/cjs/convert/index.js" }, "./currency": { - "types": "./dist/currency/index.d.ts", - "default": "./dist/currency/index.js" + "types": "./dist/types/currency/index.d.ts", + "node": "./dist/cjs/currency/index.js", + "require": "./dist/cjs/currency/index.js", + "import": "./dist/esm/currency/index.js", + "default": "./dist/cjs/currency/index.js" }, "./extractor": { - "types": "./dist/extractor/index.d.ts", - "default": "./dist/extractor/index.js" + "types": "./dist/types/extractor/index.d.ts", + "node": "./dist/cjs/extractor/index.js", + "require": "./dist/cjs/extractor/index.js", + "import": "./dist/esm/extractor/index.js", + "default": "./dist/cjs/extractor/index.js" }, "./dex": { - "types": "./dist/dex/index.d.ts", - "default": "./dist/dex/index.js" + "types": "./dist/types/dex/index.d.ts", + "node": "./dist/cjs/dex/index.js", + "require": "./dist/cjs/dex/index.js", + "import": "./dist/esm/dex/index.js", + "default": "./dist/cjs/dex/index.js" }, "./format": { - "types": "./dist/format/index.d.ts", - "default": "./dist/format/index.js" + "types": "./dist/types/format/index.d.ts", + "node": "./dist/cjs/format/index.js", + "require": "./dist/cjs/format/index.js", + "import": "./dist/esm/format/index.js", + "default": "./dist/cjs/format/index.js" }, "./log": { - "types": "./dist/log/index.d.ts", - "default": "./dist/log/index.js" + "types": "./dist/types/log/index.d.ts", + "node": "./dist/cjs/log/index.js", + "require": "./dist/cjs/log/index.js", + "import": "./dist/esm/log/index.js", + "default": "./dist/cjs/log/index.js" }, "./pool": { - "types": "./dist/pool/index.d.ts", - "default": "./dist/pool/index.js" + "types": "./dist/types/pool/index.d.ts", + "node": "./dist/cjs/pool/index.js", + "require": "./dist/cjs/pool/index.js", + "import": "./dist/esm/pool/index.js", + "default": "./dist/cjs/pool/index.js" }, "./router": { - "types": "./dist/router/index.d.ts", - "default": "./dist/router/index.js" + "types": "./dist/types/router/index.d.ts", + "node": "./dist/cjs/router/index.js", + "require": "./dist/cjs/router/index.js", + "import": "./dist/esm/router/index.js", + "default": "./dist/cjs/router/index.js" }, "./serializer": { - "types": "./dist/serializer/index.d.ts", - "default": "./dist/serializer/index.js" + "types": "./dist/types/serializer/index.d.ts", + "node": "./dist/cjs/serializer/index.js", + "require": "./dist/cjs/serializer/index.js", + "import": "./dist/esm/serializer/index.js", + "default": "./dist/cjs/serializer/index.js" }, "./math": { - "types": "./dist/math/index.d.ts", - "default": "./dist/math/index.js" + "types": "./dist/types/math/index.d.ts", + "node": "./dist/cjs/math/index.js", + "require": "./dist/cjs/math/index.js", + "import": "./dist/esm/math/index.js", + "default": "./dist/cjs/math/index.js" }, "./sort": { - "types": "./dist/sort/index.d.ts", - "default": "./dist/sort/index.js" + "types": "./dist/types/sort/index.d.ts", + "node": "./dist/cjs/sort/index.js", + "require": "./dist/cjs/sort/index.js", + "import": "./dist/esm/sort/index.js", + "default": "./dist/cjs/sort/index.js" }, "./tines": { - "types": "./dist/tines/index.d.ts", - "default": "./dist/tines/index.js" + "types": "./dist/types/tines/index.d.ts", + "node": "./dist/cjs/tines/index.js", + "require": "./dist/cjs/tines/index.js", + "import": "./dist/esm/tines/index.js", + "default": "./dist/cjs/tines/index.js" }, "./token-list": { - "types": "./dist/token-list/index.d.ts", - "default": "./dist/token-list/index.js" + "types": "./dist/types/token-list/index.d.ts", + "node": "./dist/cjs/token-list/index.js", + "require": "./dist/cjs/token-list/index.js", + "import": "./dist/esm/token-list/index.js", + "default": "./dist/cjs/token-list/index.js" }, "./types": { - "types": "./dist/types/index.d.ts", - "default": "./dist/types/index.js" + "types": "./dist/types/types/index.d.ts", + "node": "./dist/cjs/types/index.js", + "require": "./dist/cjs/types/index.js", + "import": "./dist/esm/types/index.js", + "default": "./dist/cjs/types/index.js" }, "./validate": { - "types": "./dist/validate/index.d.ts", - "default": "./dist/validate/index.js" + "types": "./dist/types/validate/index.d.ts", + "node": "./dist/cjs/validate/index.js", + "require": "./dist/cjs/validate/index.js", + "import": "./dist/esm/validate/index.js", + "default": "./dist/cjs/validate/index.js" }, "./package.json": "./package.json" }, - "main": "dist/index.js", + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", "source": "src/index.ts", - "types": "dist/index.d.ts", + "types": "dist/types/index.d.ts", "typesVersions": { "*": { "abi": [ - "./dist/abi/index.d.ts" + "./dist/types/abi/index.d.ts" ], "calculate": [ - "./dist/calculate/index.d.ts" + "./dist/types/calculate/index.d.ts" ], "chain": [ - "./dist/chain/index.d.ts" + "./dist/types/chain/index.d.ts" ], "config": [ - "./dist/config/index.d.ts" + "./dist/types/config/index.d.ts" ], "contract": [ - "./dist/contract/index.d.ts" + "./dist/types/contract/index.d.ts" ], "convert": [ - "./dist/convert/index.d.ts" + "./dist/types/convert/index.d.ts" ], "currency": [ - "./dist/currency/index.d.ts" + "./dist/types/currency/index.d.ts" ], "dex": [ - "./dist/dex/index.d.ts" + "./dist/types/dex/index.d.ts" ], "extractor": [ - "./dist/extractor/index.d.ts" + "./dist/types/extractor/index.d.ts" ], "format": [ - "./dist/format/index.d.ts" + "./dist/types/format/index.d.ts" ], "gas": [ - "./dist/gas/index.d.ts" + "./dist/types/gas/index.d.ts" ], "log": [ - "./dist/log/index.d.ts" + "./dist/types/log/index.d.ts" ], "serializer": [ - "./dist/serializer/index.d.ts" + "./dist/types/serializer/index.d.ts" ], "math": [ - "./dist/math/index.d.ts" + "./dist/types/math/index.d.ts" ], "pool": [ - "./dist/pool/index.d.ts" + "./dist/types/pool/index.d.ts" ], "router": [ - "./dist/router/index.d.ts" + "./dist/types/router/index.d.ts" ], "sort": [ - "./dist/sort/index.d.ts" + "./dist/types/sort/index.d.ts" ], "tines": [ - "./dist/tines/index.d.ts" + "./dist/types/tines/index.d.ts" ], "token-list": [ - "./dist/token-list/index.d.ts" + "./dist/types/token-list/index.d.ts" ], "types": [ - "./dist/types/index.d.ts" + "./dist/types/types/index.d.ts" ], "validate": [ - "./dist/validate/index.d.ts" + "./dist/types/validate/index.d.ts" ] } }, @@ -181,11 +245,13 @@ "dist" ], "scripts": { - "build": "tsc", + "build": "npm run build-cjs && npm run build-esm", + "build-cjs": "tsc -p tsconfig.json", + "build-esm": "tsc -p tsconfig.esm.json", "check": "tsc --pretty --noEmit", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", "dev": "tsc -w", - "generate": "npx tsx ./scripts/generate.ts", + "generate": "tsx ./scripts/generate.ts", "prepublishOnly": "pnpm build", "test": "vitest run -c ./test/vitest.config.ts", "test:debug": "vitest --inspect-brk --no-threads run -c ./test/vitest.config.ts", @@ -220,9 +286,9 @@ "@wagmi/core": "2.6.17", "ts-node": "10.9.2", "typescript": "5.2.2", - "viem": "2.8.14", + "viem": "2.21.35", "vitest": "0.34.6", - "zod": "3.21.4" + "zod": "3.22.0" }, "peerDependencies": { "viem": "*", diff --git a/packages/sushi/src/chain/constants.ts b/packages/sushi/src/chain/constants.ts index 815b95e308..5c4536859a 100644 --- a/packages/sushi/src/chain/constants.ts +++ b/packages/sushi/src/chain/constants.ts @@ -52,6 +52,9 @@ export const ChainId = { CRONOS: 25, BLAST: 81457, // RONIN: 2020, + FLARE: 14, + MATCHAIN: 698, + BERA: 80094, } as const export type ChainId = (typeof ChainId)[keyof typeof ChainId] @@ -130,5 +133,8 @@ export const ChainKey = { [ChainId.ZETACHAIN]: 'zetachain', [ChainId.CRONOS]: 'cronos', [ChainId.BLAST]: 'blast', + [ChainId.FLARE]: 'flare', + [ChainId.MATCHAIN]: 'matchain', + [ChainId.BERA]: 'berachain', } as const export type ChainKey = (typeof ChainKey)[keyof typeof ChainKey] diff --git a/packages/sushi/src/chain/generated.ts b/packages/sushi/src/chain/generated.ts index 0148eaf6b9..5961a0931d 100644 --- a/packages/sushi/src/chain/generated.ts +++ b/packages/sushi/src/chain/generated.ts @@ -57,6 +57,28 @@ export default [ name: 'OP Mainnet', shortName: 'oeth', }, + { + chainId: 14, + explorers: [ + { + name: 'blockscout', + url: 'https://flare-explorer.flare.network', + standard: 'EIP3091', + }, + { + name: 'Routescan', + url: 'https://mainnet.flarescan.com', + standard: 'EIP3091', + }, + ], + nativeCurrency: { + name: 'Flare', + symbol: 'FLR', + decimals: 18, + }, + name: 'Flare Mainnet', + shortName: 'flr', + }, { chainId: 25, explorers: [ @@ -245,12 +267,12 @@ export default [ }, ], nativeCurrency: { - name: 'MATIC', - symbol: 'MATIC', + name: 'POL', + symbol: 'POL', decimals: 18, }, name: 'Polygon Mainnet', - shortName: 'matic', + shortName: 'pol', }, { chainId: 199, @@ -301,11 +323,6 @@ export default [ url: 'https://bobascan.com', standard: 'none', }, - { - name: 'Blockscout', - url: 'https://blockexplorer.boba.network', - standard: 'none', - }, ], nativeCurrency: { name: 'Ether', @@ -393,6 +410,33 @@ export default [ ], }, }, + { + chainId: 698, + explorers: [ + { + name: 'Matchscan', + url: 'https://matchscan.io', + icon: 'matchain', + standard: 'EIP3091', + }, + ], + nativeCurrency: { + name: 'BNB', + symbol: 'BNB', + decimals: 18, + }, + name: 'Matchain', + shortName: 'Matchain', + parent: { + type: 'L2', + chain: 'eip155-56', + bridges: [ + { + url: 'https://bnb-bridge.matchain.io', + }, + ], + }, + }, { chainId: 1088, explorers: [ @@ -539,7 +583,7 @@ export default [ explorers: [ { name: 'ZetaChain Mainnet Explorer', - url: 'https://explorer.mainnet.zetachain.com', + url: 'https://explorer.zetachain.com', standard: 'none', }, ], @@ -557,7 +601,7 @@ export default [ { name: 'basescan', url: 'https://basescan.org', - standard: 'none', + standard: 'EIP3091', }, { name: 'basescout', @@ -693,7 +737,12 @@ export default [ chainId: 43113, explorers: [ { - name: 'snowtrace', + name: 'Etherscan', + url: 'https://testnet.snowscan.xyz', + standard: 'EIP3091', + }, + { + name: 'Routescan', url: 'https://testnet.snowtrace.io', standard: 'EIP3091', }, @@ -710,10 +759,20 @@ export default [ chainId: 43114, explorers: [ { - name: 'snowtrace', + name: 'Etherscan', + url: 'https://snowscan.xyz', + standard: 'EIP3091', + }, + { + name: 'Routescan', url: 'https://snowtrace.io', standard: 'EIP3091', }, + { + name: 'Avascan', + url: 'https://avascan.info', + standard: 'EIP3091', + }, ], nativeCurrency: { name: 'Avalanche', @@ -745,7 +804,7 @@ export default [ explorers: [ { name: 'Boba BNB block explorer', - url: 'https://blockexplorer.bnb.boba.network', + url: 'https://bobascan.com', standard: 'none', }, ], @@ -758,7 +817,7 @@ export default [ shortName: 'BobaBnb', parent: { type: 'L2', - chain: 'eip155-5', + chain: 'eip155-56', bridges: [ { url: 'https://gateway.boba.network', @@ -822,6 +881,28 @@ export default [ name: 'Mumbai', shortName: 'maticmum', }, + { + chainId: 80094, + explorers: [ + { + name: 'Berascan', + url: 'https://berascan.com', + standard: 'EIP3091', + }, + { + name: 'Beratrail', + url: 'https://beratrail.io', + standard: 'EIP3091', + }, + ], + nativeCurrency: { + name: 'BERA Token', + symbol: 'BERA', + decimals: 18, + }, + name: 'Berachain', + shortName: 'berachain', + }, { chainId: 81457, explorers: [ @@ -853,6 +934,11 @@ export default [ { chainId: 421614, explorers: [ + { + name: 'arbiscan-sepolia', + url: 'https://sepolia.arbiscan.io', + standard: 'EIP3091', + }, { name: 'Arbitrum Sepolia Rollup Testnet Explorer', url: 'https://sepolia-explorer.arbitrum.io', @@ -884,11 +970,6 @@ export default [ url: 'https://scrollscan.com', standard: 'EIP3091', }, - { - name: 'Blockscout', - url: 'https://blockscout.scroll.io', - standard: 'EIP3091', - }, ], nativeCurrency: { name: 'Ether', diff --git a/packages/sushi/src/config/bases-to-check-trades-against.ts b/packages/sushi/src/config/bases-to-check-trades-against.ts index a7d9aa8bfc..c36a1d0493 100644 --- a/packages/sushi/src/config/bases-to-check-trades-against.ts +++ b/packages/sushi/src/config/bases-to-check-trades-against.ts @@ -1,15 +1,15 @@ import { ChainId } from '../chain/index.js' -import { MUSD, Token, USDB } from '../currency/index.js' +import { MUSD, Token, USDB, USDe, cUSDX, sFLR } from '../currency/index.js' import { AAVE, BUSD, DAI, FRAX, - LINK, + // LINK, LUSD, MATIC, MIM, - OHM, + // OHM, OP, QUICK, SUSHI, @@ -47,9 +47,9 @@ export const BASES_TO_CHECK_TRADES_AGAINST: { DAI[ChainId.ETHEREUM], MIM[ChainId.ETHEREUM], FRAX[ChainId.ETHEREUM], - OHM[ChainId.ETHEREUM], - LINK[ChainId.ETHEREUM], - SUSHI[ChainId.ETHEREUM], + // OHM[ChainId.ETHEREUM], + // LINK[ChainId.ETHEREUM], + // SUSHI[ChainId.ETHEREUM], ], // [ChainId.RINKEBY]: [WNATIVE[ChainId.RINKEBY], USDC[ChainId.RINKEBY]], // [ChainId.KOVAN]: [WNATIVE[ChainId.KOVAN], USDC[ChainId.KOVAN]], @@ -62,7 +62,7 @@ export const BASES_TO_CHECK_TRADES_AGAINST: { DAI[ChainId.POLYGON], FRAX[ChainId.POLYGON], QUICK[ChainId.POLYGON], - LINK[ChainId.POLYGON], + // LINK[ChainId.POLYGON], AAVE[ChainId.POLYGON], new Token({ address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', @@ -112,13 +112,13 @@ export const BASES_TO_CHECK_TRADES_AGAINST: { symbol: 'BTCB', name: 'Binance-Peg BTCB Token', }), - new Token({ - chainId: ChainId.BSC, - address: '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82', - decimals: 18, - symbol: 'Cake', - name: 'PancakeSwap Token', - }), + // new Token({ + // chainId: ChainId.BSC, + // address: '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82', + // decimals: 18, + // symbol: 'Cake', + // name: 'PancakeSwap Token', + // }), ], [ChainId.ARBITRUM]: [ WNATIVE[ChainId.ARBITRUM], @@ -128,7 +128,7 @@ export const BASES_TO_CHECK_TRADES_AGAINST: { DAI[ChainId.ARBITRUM], MIM[ChainId.ARBITRUM], FRAX[ChainId.ARBITRUM], - LINK[ChainId.ARBITRUM], + // LINK[ChainId.ARBITRUM], new Token({ chainId: ChainId.ARBITRUM, address: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', @@ -143,27 +143,27 @@ export const BASES_TO_CHECK_TRADES_AGAINST: { symbol: 'ARB', name: 'Arbitrum', }), - new Token({ - chainId: ChainId.ARBITRUM, - address: '0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a', - decimals: 18, - symbol: 'GMX', - name: 'GMX', - }), - new Token({ - chainId: ChainId.ARBITRUM, - address: '0x539bdE0d7Dbd336b79148AA742883198BBF60342', - decimals: 18, - symbol: 'MAGIC', - name: 'MAGIC', - }), - new Token({ - chainId: ChainId.ARBITRUM, - address: '0x8D9bA570D6cb60C7e3e0F31343Efe75AB8E65FB1', - decimals: 18, - symbol: 'gOHM', - name: 'Governance OHM', - }), + // new Token({ + // chainId: ChainId.ARBITRUM, + // address: '0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a', + // decimals: 18, + // symbol: 'GMX', + // name: 'GMX', + // }), + // new Token({ + // chainId: ChainId.ARBITRUM, + // address: '0x539bdE0d7Dbd336b79148AA742883198BBF60342', + // decimals: 18, + // symbol: 'MAGIC', + // name: 'MAGIC', + // }), + // new Token({ + // chainId: ChainId.ARBITRUM, + // address: '0x8D9bA570D6cb60C7e3e0F31343Efe75AB8E65FB1', + // decimals: 18, + // symbol: 'gOHM', + // name: 'Governance OHM', + // }), ], [ChainId.ARBITRUM_NOVA]: [ WNATIVE[ChainId.ARBITRUM_NOVA], @@ -479,4 +479,24 @@ export const BASES_TO_CHECK_TRADES_AGAINST: { USDC[ChainId.CRONOS], ], [ChainId.BLAST]: [WNATIVE[ChainId.BLAST], USDB[ChainId.BLAST], MUSD], + [ChainId.FLARE]: [ + WNATIVE[ChainId.FLARE], + WETH9[ChainId.FLARE], + USDT[ChainId.FLARE], + USDC[ChainId.FLARE], + sFLR, + cUSDX, + ], + [ChainId.MATCHAIN]: [ + WNATIVE[ChainId.MATCHAIN], + WETH9[ChainId.MATCHAIN], + USDT[ChainId.MATCHAIN], + USDC[ChainId.MATCHAIN], + ], + [ChainId.BERA]: [ + WNATIVE[ChainId.BERA], + WBTC[ChainId.BERA], + USDC[ChainId.BERA], + USDe, + ], } diff --git a/packages/sushi/src/config/native-ids.ts b/packages/sushi/src/config/native-ids.ts index f034f6435c..147cc74072 100644 --- a/packages/sushi/src/config/native-ids.ts +++ b/packages/sushi/src/config/native-ids.ts @@ -54,4 +54,6 @@ export const nativeCurrencyIds = { [ChainId.ZETACHAIN]: 'ZETA', [ChainId.CRONOS]: 'CRO', [ChainId.BLAST]: 'ETH', + [ChainId.FLARE]: 'FLR', + [ChainId.MATCHAIN]: 'BNB', } as const diff --git a/packages/sushi/src/config/route-processor.ts b/packages/sushi/src/config/route-processor.ts index 6a36705ec7..e3972fa89f 100644 --- a/packages/sushi/src/config/route-processor.ts +++ b/packages/sushi/src/config/route-processor.ts @@ -132,6 +132,7 @@ export const ROUTE_PROCESSOR_3_SUPPORTED_CHAIN_IDS = [ ChainId.TELOS, ChainId.THUNDERCORE, ChainId.LINEA, + ChainId.FLARE, ] as const export type RouteProcessor3ChainId = (typeof ROUTE_PROCESSOR_3_SUPPORTED_CHAIN_IDS)[number] @@ -169,6 +170,7 @@ export const ROUTE_PROCESSOR_3_ADDRESS: Record< [ChainId.TELOS]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', [ChainId.THUNDERCORE]: '0x1b9d177CcdeA3c79B6c8F40761fc8Dc9d0500EAa', [ChainId.LINEA]: '0x0b17dF2CDEf8f0fCb7847e287726C6a8c1415A1f', + [ChainId.FLARE]: '0x9B3F1D56D9004e6C69d8247d402F38DE5F87A27c', } as const export const isRouteProcessor3ChainId = ( chainId: ChainId, @@ -225,6 +227,7 @@ export const ROUTE_PROCESSOR_3_2_SUPPORTED_CHAIN_IDS = [ ChainId.SCROLL, ChainId.FILECOIN, ChainId.ZETACHAIN, + ChainId.FLARE, ] as const export type RouteProcessor3_2ChainId = (typeof ROUTE_PROCESSOR_3_2_SUPPORTED_CHAIN_IDS)[number] @@ -251,6 +254,7 @@ export const ROUTE_PROCESSOR_3_2_ADDRESS: Record< [ChainId.SCROLL]: '0xCA6Fe749878841b96F620Ec79638B13dAaD3D320', [ChainId.FILECOIN]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', [ChainId.ZETACHAIN]: '0xb46e319390De313B8cc95EA5aa30C7bBFD79Da94', + [ChainId.FLARE]: '0x5CeEe9F4F49C106D5Bc049C8D649C332E6d365ad', } as const export const isRouteProcessor3_2ChainId = ( chainId: ChainId, @@ -292,6 +296,9 @@ export const ROUTE_PROCESSOR_4_SUPPORTED_CHAIN_IDS = [ ChainId.CORE, ChainId.CRONOS, ChainId.BLAST, + ChainId.FLARE, + ChainId.MATCHAIN, + ChainId.BERA, ] as const export type RouteProcessor4ChainId = (typeof ROUTE_PROCESSOR_4_SUPPORTED_CHAIN_IDS)[number] @@ -330,6 +337,9 @@ export const ROUTE_PROCESSOR_4_ADDRESS: Record< [ChainId.CORE]: '0x0389879e0156033202C44BF784ac18fC02edeE4f', [ChainId.CRONOS]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', [ChainId.BLAST]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [ChainId.FLARE]: '0x4Aa9AEf59C7B63CD5C4B2eDE81F65A4225a99d9d', + [ChainId.MATCHAIN]: '0xbD8849759749B4d8506bC851aceF0E19F34EaBEE', + [ChainId.BERA]: '0x', // needs deployment } as const export const isRouteProcessor4ChainId = ( chainId: ChainId, diff --git a/packages/sushi/src/config/stables.ts b/packages/sushi/src/config/stables.ts index e15ae8142a..ee03cf6fcc 100644 --- a/packages/sushi/src/config/stables.ts +++ b/packages/sushi/src/config/stables.ts @@ -208,6 +208,7 @@ export const STABLES = { ], [ChainId.CRONOS]: [USDC[ChainId.CRONOS]], [ChainId.BLAST]: [USDB[ChainId.BLAST], MUSD], + [ChainId.FLARE]: [USDT[ChainId.FLARE]], // TESTNETS // [ChainId.RINKEBY]: [USDC[ChainId.RINKEBY]], // [ChainId.ROPSTEN]: [ diff --git a/packages/sushi/src/config/viem.ts b/packages/sushi/src/config/viem.ts index e82f9e73e0..b4b8dc7275 100644 --- a/packages/sushi/src/config/viem.ts +++ b/packages/sushi/src/config/viem.ts @@ -4,6 +4,7 @@ import { Chain, type PublicClientConfig, Transport, + fallback, } from 'viem' import { arbitrum, @@ -32,6 +33,7 @@ import { // evmosTestnet, fantom, fantomTestnet, + flare as _flare, // fantomTestnet, // filecoinTestnet, foundry, @@ -90,6 +92,7 @@ export { // evmos, // evmosTestnet, fantom, + flare, // fantomTestnet, // filecoinTestnet, foundry, @@ -140,6 +143,16 @@ const haqq = { }, } as const +const flare = { + ..._flare, + contracts: { + multicall3: { + address: '0xcA11bde05977b3631167028862bE2a173976CA11', + blockCreated: 3002461, + }, + }, +} as const + // Chains missing from viem entirely export const kava = { id: ChainId.KAVA, @@ -490,312 +503,365 @@ export const blast = { }, } as const -// const alchemyId = -// process.env['ALCHEMY_ID'] || process.env['NEXT_PUBLIC_ALCHEMY_ID'] -const drpcId = process.env['DRPC_ID'] || process.env['NEXT_PUBLIC_DRPC_ID'] +export const matchain = { + id: ChainId.MATCHAIN, + name: 'MatChain', + network: 'matchain', + nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 }, + rpcUrls: { + default: { + http: ['https://rpc.matchain.io'], + }, + public: { + http: ['https://rpc.matchain.io'], + }, + }, + blockExplorers: { + etherscan: { + name: 'Matchain Explorer', + url: 'https://matchscan.io', + }, + default: { + name: 'Matchain Explorer', + url: 'https://matchscan.io', + }, + }, + contracts: { + multicall3: { + address: '0xcA11bde05977b3631167028862bE2a173976CA11' as Address, + blockCreated: 0, + }, + }, +} as const + +export const berachain = { + id: ChainId.BERA, + name: 'Berachain', + network: 'Berachain', + nativeCurrency: { name: 'BERA Token', symbol: 'BERA', decimals: 18 }, + rpcUrls: { + default: { + http: ['https://rpc.berachain.com'], + }, + public: { + http: ['https://berachain.drpc.org'], + }, + }, + blockExplorers: { + etherscan: { + name: 'Berachain Explorer', + url: 'https://berascan.com', + }, + default: { + name: 'Berachain Explorer', + url: 'https://berascan.com', + }, + }, + contracts: { + multicall3: { + address: '0xcA11bde05977b3631167028862bE2a173976CA11' as Address, + blockCreated: 0, + }, + }, +} as const -export const publicTransports = { - [ChainId.ARBITRUM_NOVA]: http( - `https://lb.drpc.org/ogrpc?network=arbitrum-nova&dkey=${drpcId}`, - ), - [ChainId.ARBITRUM]: http( - `https://lb.drpc.org/ogrpc?network=arbitrum&dkey=${drpcId}`, - ), - [ChainId.AVALANCHE]: http( - `https://lb.drpc.org/ogrpc?network=avalanche&dkey=${drpcId}`, - ), - [ChainId.BOBA]: http('https://mainnet.boba.network'), - [ChainId.BOBA_AVAX]: http('https://avax.boba.network'), - [ChainId.BOBA_BNB]: http('https://bnb.boba.network'), - [ChainId.BSC]: http(`https://lb.drpc.org/ogrpc?network=bsc&dkey=${drpcId}`), - [ChainId.BTTC]: http('https://rpc.bittorrentchain.io'), - [ChainId.CELO]: http(`https://lb.drpc.org/ogrpc?network=celo&dkey=${drpcId}`), - [ChainId.ETHEREUM]: http( - `https://lb.drpc.org/ogrpc?network=ethereum&dkey=${drpcId}`, - ), - [ChainId.FANTOM]: http( - `https://lb.drpc.org/ogrpc?network=fantom&dkey=${drpcId}`, - ), - [ChainId.FUSE]: http(`https://lb.drpc.org/ogrpc?network=fuse&dkey=${drpcId}`), - [ChainId.GNOSIS]: http( - `https://lb.drpc.org/ogrpc?network=gnosis&dkey=${drpcId}`, - ), - [ChainId.HARMONY]: http( - `https://lb.drpc.org/ogrpc?network=harmony-0&dkey=${drpcId}`, - ), - [ChainId.KAVA]: http(`https://lb.drpc.org/ogrpc?network=kava&dkey=${drpcId}`), - [ChainId.METIS]: http( - `https://lb.drpc.org/ogrpc?network=metis&dkey=${drpcId}`, - ), - [ChainId.MOONBEAM]: http( - `https://lb.drpc.org/ogrpc?network=moonbeam&dkey=${drpcId}`, - ), - [ChainId.MOONRIVER]: http( - `https://lb.drpc.org/ogrpc?network=moonriver&dkey=${drpcId}`, - ), - [ChainId.OPTIMISM]: http( - `https://lb.drpc.org/ogrpc?network=optimism&dkey=${drpcId}`, - ), - [ChainId.POLYGON]: http( - `https://lb.drpc.org/ogrpc?network=polygon&dkey=${drpcId}`, - ), - [ChainId.POLYGON_ZKEVM]: http( - `https://lb.drpc.org/ogrpc?network=polygon-zkevm&dkey=${drpcId}`, - ), - [ChainId.THUNDERCORE]: http('https://mainnet-rpc.thundercore.com'), - [ChainId.HAQQ]: http(`https://lb.drpc.org/ogrpc?network=haqq&dkey=${drpcId}`), - [ChainId.CORE]: http('https://rpc.coredao.org'), - [ChainId.TELOS]: http('https://rpc1.us.telos.net/evm'), +export const publicTransports: Record = { + [ChainId.ARBITRUM_NOVA]: http(arbitrumNova.rpcUrls.default.http[0]), + [ChainId.ARBITRUM]: http(arbitrum.rpcUrls.default.http[0]), + [ChainId.AVALANCHE]: http(avalanche.rpcUrls.default.http[0]), + [ChainId.BOBA]: http(boba.rpcUrls.default.http[0]), + [ChainId.BOBA_AVAX]: http(bobaAvax.rpcUrls.default.http[0]), + [ChainId.BOBA_BNB]: http(bobaBnb.rpcUrls.default.http[0]), + [ChainId.BSC]: http(bsc.rpcUrls.default.http[0]), + [ChainId.BTTC]: http(bttc.rpcUrls.default.http[0]), + [ChainId.CELO]: http(celo.rpcUrls.default.http[0]), + [ChainId.ETHEREUM]: http(mainnet.rpcUrls.default.http[0]), + [ChainId.FANTOM]: http(fantom.rpcUrls.default.http[0]), + [ChainId.FUSE]: http(fuse.rpcUrls.default.http[0]), + [ChainId.GNOSIS]: http(gnosis.rpcUrls.default.http[0]), + [ChainId.HARMONY]: http(harmonyOne.rpcUrls.default.http[0]), + [ChainId.KAVA]: http(kava.rpcUrls.default.http[0]), + [ChainId.METIS]: http(metis.rpcUrls.default.http[0]), + [ChainId.MOONBEAM]: http(moonbeam.rpcUrls.default.http[0]), + [ChainId.MOONRIVER]: http(moonriver.rpcUrls.default.http[0]), + [ChainId.OPTIMISM]: http(optimism.rpcUrls.default.http[0]), + [ChainId.POLYGON]: http(polygon.rpcUrls.default.http[0]), + [ChainId.POLYGON_ZKEVM]: http(polygonZkEvm.rpcUrls.default.http[0]), + [ChainId.THUNDERCORE]: http(thundercore.rpcUrls.default.http[0]), + [ChainId.HAQQ]: http(haqq.rpcUrls.default.http[0]), + [ChainId.CORE]: http(core.rpcUrls.default.http[0]), + [ChainId.TELOS]: http(telos.rpcUrls.default.http[0]), [ChainId.PALM]: http(palm.rpcUrls.default.http[0]), [ChainId.OKEX]: http(okc.rpcUrls.default.http[0]), [ChainId.HECO]: http(heco.rpcUrls.default.http[0]), [ChainId.ZKSYNC_ERA]: http(zkSync.rpcUrls.default.http[0]), - [ChainId.LINEA]: http( - `https://lb.drpc.org/ogrpc?network=linea&dkey=${drpcId}`, - ), - [ChainId.BASE]: http(`https://lb.drpc.org/ogrpc?network=base&dkey=${drpcId}`), - [ChainId.SCROLL]: http( - `https://lb.drpc.org/ogrpc?network=scroll&dkey=${drpcId}`, - ), - [ChainId.FILECOIN]: http( - `https://lb.drpc.org/ogrpc?network=filecoin&dkey=${drpcId}`, - // 'https://fil-mainnet-1.rpc.laconic.com/rpc/v1' - ), - [ChainId.ZETACHAIN]: http( - `https://lb.drpc.org/ogrpc?network=zeta-chain&dkey=${drpcId}`, - ), - [ChainId.CRONOS]: http( - `https://lb.drpc.org/ogrpc?network=cronos&dkey=${drpcId}`, - ), - [ChainId.BLAST]: http( - `https://lb.drpc.org/ogrpc?network=blast&dkey=${drpcId}`, - ), + [ChainId.LINEA]: http(linea.rpcUrls.default.http[0]), + [ChainId.BASE]: http(base.rpcUrls.default.http[0]), + [ChainId.SCROLL]: http(scroll.rpcUrls.default.http[0]), + [ChainId.FILECOIN]: http(filecoin.rpcUrls.default.http[0]), + [ChainId.ZETACHAIN]: http(zetachain.rpcUrls.default.http[0]), + [ChainId.CRONOS]: http(cronos.rpcUrls.default.http[0]), + [ChainId.BLAST]: http(blast.rpcUrls.default.http[0]), + [ChainId.FLARE]: http(flare.rpcUrls.default.http[0]), + [ChainId.BERA]: http(berachain.rpcUrls.default.http[0]), /* Testnets */ // TODO: add testnet transports - [ChainId.ARBITRUM_TESTNET]: http('https://sepolia-rollup.arbitrum.io/rpc'), - [ChainId.AVALANCHE_TESTNET]: http( - 'https://api.avax-test.network/ext/bc/C/rpc', - ), - [ChainId.BSC_TESTNET]: http('https://bsc-testnet.public.blastapi.io'), - [ChainId.FANTOM_TESTNET]: http('https://rpc.testnet.fantom.network'), - [ChainId.POLYGON_TESTNET]: http('https://rpc.ankr.com/polygon_mumbai'), - [ChainId.SEPOLIA]: http('https://sepolia.drpc.org'), + [ChainId.ARBITRUM_TESTNET]: http(arbitrumSepolia.rpcUrls.default.http[0]), + [ChainId.AVALANCHE_TESTNET]: http(avalancheFuji.rpcUrls.default.http[0]), + [ChainId.BSC_TESTNET]: http(bscTestnet.rpcUrls.default.http[0]), + [ChainId.FANTOM_TESTNET]: http(fantomTestnet.rpcUrls.default.http[0]), + [ChainId.POLYGON_TESTNET]: http(polygonMumbai.rpcUrls.default.http[0]), + [ChainId.SEPOLIA]: http(sepolia.rpcUrls.default.http[0]), + [ChainId.MATCHAIN]: http(matchain.rpcUrls.default.http[0]), } as const satisfies Record export const publicChains = [ - arbitrumNova, - arbitrum, - avalanche, - boba, + arbitrumNova as Chain, + arbitrum as Chain, + avalanche as Chain, + boba as Chain, bobaAvax, bobaBnb, - bsc, + bsc as Chain, bttc, blast, - celo as unknown as Omit & { id: 42220 }, - cronos, - mainnet, - fantom, - fuse, - gnosis, - harmonyOne, + celo as Chain, + cronos as Chain, + mainnet as Chain, + fantom as Chain, + fuse as Chain, + gnosis as Chain, + harmonyOne as Chain, kava, - metis, - optimism, - moonbeam, - moonriver, - polygon, - polygonZkEvm, + metis as Chain, + optimism as Chain, + moonbeam as Chain, + moonriver as Chain, + polygon as Chain, + polygonZkEvm as Chain, thundercore, - haqq, + haqq as Chain, core, - telos, + telos as Chain, palm, - okc, + okc as Chain, heco, - zkSync, - linea, - base, - scroll, + zkSync as Chain, + linea as Chain, + base as Chain, + scroll as Chain, filecoin, zetachain, + flare as Chain, + matchain, + berachain, /* Testnets */ - arbitrumSepolia, - avalancheFuji, - bscTestnet, - fantomTestnet, - polygonMumbai, - sepolia, + arbitrumSepolia as Chain, + avalancheFuji as Chain, + bscTestnet as Chain, + fantomTestnet as Chain, + polygonMumbai as Chain, + sepolia as Chain, ] as const satisfies Readonly export const publicClientConfig = { [ChainId.ARBITRUM_NOVA]: { - chain: arbitrumNova, + chain: arbitrumNova as Chain, transport: publicTransports[ChainId.ARBITRUM_NOVA], }, [ChainId.ARBITRUM]: { - chain: arbitrum, + chain: arbitrum as Chain, transport: publicTransports[ChainId.ARBITRUM], }, [ChainId.AVALANCHE]: { - chain: avalanche, + chain: avalanche as Chain, transport: publicTransports[ChainId.AVALANCHE], }, [ChainId.BOBA]: { - chain: boba, + chain: boba as Chain, transport: publicTransports[ChainId.BOBA], }, [ChainId.BOBA_AVAX]: { - chain: bobaAvax, + chain: bobaAvax as Chain, transport: publicTransports[ChainId.BOBA_AVAX], }, [ChainId.BOBA_BNB]: { - chain: bobaBnb, + chain: bobaBnb as Chain, transport: publicTransports[ChainId.BOBA_BNB], }, [ChainId.BSC]: { - chain: bsc, - transport: publicTransports[ChainId.BSC], + chain: bsc as Chain, + transport: fallback([ + http('https://bsc.drpc.org'), + publicTransports[ChainId.BSC], + ]), }, [ChainId.BTTC]: { - chain: bttc, + chain: bttc as Chain, transport: publicTransports[ChainId.BTTC], }, [ChainId.CELO]: { - chain: celo as unknown as typeof mainnet & { id: 42220 }, + chain: celo as unknown as typeof mainnet & { id: 42220 } as Chain, transport: publicTransports[ChainId.CELO], }, [ChainId.ETHEREUM]: { - chain: mainnet, - transport: publicTransports[ChainId.ETHEREUM], + chain: mainnet as Chain, + transport: fallback([ + http('https://eth.drpc.org'), + publicTransports[ChainId.ETHEREUM], + ]), }, [ChainId.FANTOM]: { - chain: fantom, - transport: publicTransports[ChainId.FANTOM], + chain: fantom as Chain, + transport: fallback([ + http('https://fantom.drpc.org'), + http('https://fantom-rpc.publicnode.com'), + publicTransports[ChainId.FANTOM], // default that uses ankr rpc is now only available as paid account + ]), }, [ChainId.FUSE]: { - chain: fuse, + chain: fuse as Chain, transport: publicTransports[ChainId.FUSE], }, [ChainId.GNOSIS]: { - chain: gnosis, + chain: gnosis as Chain, transport: publicTransports[ChainId.GNOSIS], }, [ChainId.HARMONY]: { - chain: harmonyOne, - transport: publicTransports[ChainId.HARMONY], + chain: harmonyOne as Chain, + transport: fallback([ + http('https://api.harmony.one'), + http('https://harmony-0.drpc.org'), + publicTransports[ChainId.HARMONY], + ]), }, [ChainId.KAVA]: { - chain: kava, + chain: kava as Chain, transport: publicTransports[ChainId.KAVA], }, [ChainId.METIS]: { - chain: metis, + chain: metis as Chain, transport: publicTransports[ChainId.METIS], }, [ChainId.MOONBEAM]: { - chain: moonbeam, + chain: moonbeam as Chain, transport: publicTransports[ChainId.MOONBEAM], }, [ChainId.MOONRIVER]: { - chain: moonriver, + chain: moonriver as Chain, transport: publicTransports[ChainId.MOONRIVER], }, [ChainId.OPTIMISM]: { - chain: optimism, + chain: optimism as Chain, transport: publicTransports[ChainId.OPTIMISM], }, [ChainId.POLYGON]: { - chain: polygon, + chain: polygon as Chain, transport: publicTransports[ChainId.POLYGON], }, [ChainId.POLYGON_ZKEVM]: { - chain: polygonZkEvm, + chain: polygonZkEvm as Chain, transport: publicTransports[ChainId.POLYGON_ZKEVM], }, [ChainId.THUNDERCORE]: { - chain: thundercore, + chain: thundercore as Chain, transport: publicTransports[ChainId.THUNDERCORE], }, [ChainId.HAQQ]: { - chain: haqq, + chain: haqq as Chain, transport: publicTransports[ChainId.HAQQ], }, [ChainId.CORE]: { - chain: core, + chain: core as Chain, transport: publicTransports[ChainId.CORE], }, [ChainId.TELOS]: { - chain: telos, + chain: telos as Chain, transport: publicTransports[ChainId.TELOS], }, [ChainId.PALM]: { - chain: palm, + chain: palm as Chain, transport: publicTransports[ChainId.PALM], }, [ChainId.OKEX]: { - chain: okc, + chain: okc as Chain, transport: publicTransports[ChainId.OKEX], }, [ChainId.HECO]: { - chain: heco, + chain: heco as Chain, transport: publicTransports[ChainId.HECO], }, [ChainId.ZKSYNC_ERA]: { - chain: zkSync, + chain: zkSync as Chain, transport: publicTransports[ChainId.ZKSYNC_ERA], }, [ChainId.LINEA]: { - chain: linea, + chain: linea as Chain, transport: publicTransports[ChainId.LINEA], }, [ChainId.BASE]: { - chain: base, - transport: publicTransports[ChainId.BASE], + chain: base as Chain, + transport: fallback([ + http('https://base.drpc.org'), + publicTransports[ChainId.BASE], + ]), }, [ChainId.SCROLL]: { - chain: scroll, + chain: scroll as Chain, transport: publicTransports[ChainId.SCROLL], }, [ChainId.FILECOIN]: { - chain: filecoin, + chain: filecoin as Chain, transport: publicTransports[ChainId.FILECOIN], }, [ChainId.ZETACHAIN]: { - chain: zetachain, + chain: zetachain as Chain, transport: publicTransports[ChainId.ZETACHAIN], }, [ChainId.CRONOS]: { - chain: cronos, + chain: cronos as Chain, transport: publicTransports[ChainId.CRONOS], }, [ChainId.BLAST]: { - chain: blast, + chain: blast as Chain, transport: publicTransports[ChainId.BLAST], }, + [ChainId.FLARE]: { + chain: flare as Chain, + transport: publicTransports[ChainId.FLARE], + }, + [ChainId.MATCHAIN]: { + chain: matchain as Chain, + transport: publicTransports[ChainId.MATCHAIN], + }, + [ChainId.BERA]: { + chain: berachain as Chain, + transport: publicTransports[ChainId.BERA], + }, + /* Testnets */ [ChainId.ARBITRUM_TESTNET]: { - chain: arbitrumSepolia, + chain: arbitrumSepolia as Chain, transport: publicTransports[ChainId.ARBITRUM_TESTNET], }, [ChainId.AVALANCHE_TESTNET]: { - chain: avalancheFuji, + chain: avalancheFuji as Chain, transport: publicTransports[ChainId.AVALANCHE_TESTNET], }, [ChainId.BSC_TESTNET]: { - chain: bscTestnet, + chain: bscTestnet as Chain, transport: publicTransports[ChainId.BSC_TESTNET], }, [ChainId.FANTOM_TESTNET]: { - chain: fantomTestnet, + chain: fantomTestnet as Chain, transport: publicTransports[ChainId.FANTOM_TESTNET], }, [ChainId.POLYGON_TESTNET]: { - chain: polygonMumbai, + chain: polygonMumbai as Chain, transport: publicTransports[ChainId.POLYGON_TESTNET], }, [ChainId.SEPOLIA]: { - chain: sepolia, + chain: sepolia as Chain, transport: publicTransports[ChainId.SEPOLIA], }, } as const satisfies Record< diff --git a/packages/sushi/src/currency/token-addresses.ts b/packages/sushi/src/currency/token-addresses.ts index 75eafd6731..e0bde1c387 100644 --- a/packages/sushi/src/currency/token-addresses.ts +++ b/packages/sushi/src/currency/token-addresses.ts @@ -198,6 +198,7 @@ export const WBTC_ADDRESS = { [ChainId.CELO]: '0xD629eb00dEced2a080B7EC630eF6aC117e614f1b', [ChainId.ZETACHAIN]: '0x13a0c5930c028511dc02665e7285134b6d11a5f4', [ChainId.CRONOS]: '0x062E66477Faf219F25D27dCED647BF57C3107d52', + [ChainId.BERA]: '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c', } as const export const UNI_ADDRESS = { @@ -311,6 +312,8 @@ export const WETH9_ADDRESS = { [ChainId.ZETACHAIN]: '0xd97B1de3619ed2c6BEb3860147E30cA8A7dC9891', [ChainId.CRONOS]: '0xe44Fd7fCb2b1581822D0c862B68222998a0c299a', [ChainId.BLAST]: '0x4300000000000000000000000000000000000004', + [ChainId.FLARE]: '0x1502FA4be69d526124D453619276FacCab275d3D', + [ChainId.MATCHAIN]: '0xFF13A7A12fd485BC9687fF88D8Ae1A6b655Ab469', } as const export const WNATIVE_ADDRESS = { @@ -367,6 +370,9 @@ export const WNATIVE_ADDRESS = { [ChainId.ZETACHAIN]: '0x5F0b1a82749cb4E2278EC87F8BF6B618dC71a8bf', [ChainId.CRONOS]: '0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23', [ChainId.BLAST]: WETH9_ADDRESS[ChainId.BLAST], + [ChainId.FLARE]: '0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d', + [ChainId.MATCHAIN]: '0x4200000000000000000000000000000000000006', + [ChainId.BERA]: '0x6969696969696969696969696969696969696969', } as const export const SUSHI_ADDRESS = { @@ -448,6 +454,11 @@ export const USDC_ADDRESS = { [ChainId.FILECOIN]: axlUSDC_ADDRESS[ChainId.FILECOIN], [ChainId.ZETACHAIN]: '0x0cbe0dF132a6c6B4a2974Fa1b7Fb953CF0Cc798a', [ChainId.CRONOS]: '0xc21223249CA28397B4B6541dfFaEcC539BfF0c59', + [ChainId.FANTOM]: '0xd9820a17053d6314B20642E465a84Bf01a3D64f5', + [ChainId.MOONBEAM]: '0x8f552a71EFE5eeFc207Bf75485b356A0b3f01eC9', + [ChainId.FLARE]: '0xFbDa5F676cB37624f28265A144A48B0d6e87d3b6', + [ChainId.MATCHAIN]: '0x97eec1c29f745dC7c267F90292AA663d997a601D', + [ChainId.BERA]: '0x549943e04f40284185054145c6E4e9568C1D3241', } as const export const USDT_ADDRESS = { @@ -481,6 +492,8 @@ export const USDT_ADDRESS = { [ChainId.HAQQ]: axlUSDT_ADDRESS[ChainId.HAQQ], [ChainId.SCROLL]: '0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df', [ChainId.ZETACHAIN]: '0x7c8dDa80bbBE1254a7aACf3219EBe1481c6E01d7', + [ChainId.FLARE]: '0x0B38e83B86d491735fEaa0a791F65c2B99535396', + [ChainId.MATCHAIN]: '0xB6dc6C8b71e88642cEAD3be1025565A9eE74d1C6', } as const export const DAI_ADDRESS = { @@ -509,6 +522,7 @@ export const DAI_ADDRESS = { [ChainId.BASE]: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', [ChainId.SCROLL]: '0xcA77eB3fEFe3725Dc33bccB54eDEFc3D9f764f97', [ChainId.FILECOIN]: axlDAI_ADDRESS[ChainId.FILECOIN], + [ChainId.FANTOM]: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', } as const export const MIM_ADDRESS = { diff --git a/packages/sushi/src/currency/tokens.ts b/packages/sushi/src/currency/tokens.ts index cc60febbec..780ae2b0e7 100644 --- a/packages/sushi/src/currency/tokens.ts +++ b/packages/sushi/src/currency/tokens.ts @@ -684,6 +684,27 @@ export const WNATIVE = { name: 'Wrapped CRO', }), [ChainId.BLAST]: WETH9[ChainId.BLAST], + [ChainId.FLARE]: new Token({ + chainId: ChainId.FLARE, + address: WNATIVE_ADDRESS[ChainId.FLARE], + decimals: 18, + symbol: 'WFLR', + name: 'Wrapped FLR', + }), + [ChainId.MATCHAIN]: new Token({ + chainId: ChainId.MATCHAIN, + address: WNATIVE_ADDRESS[ChainId.MATCHAIN], + decimals: 18, + symbol: 'WBNB', + name: 'Wrapped BNB', + }), + [ChainId.BERA]: new Token({ + chainId: ChainId.BERA, + address: WNATIVE_ADDRESS[ChainId.BERA], + decimals: 18, + symbol: 'WBERA', + name: 'Wrapped Bera', + }), } as const export const SUSHI = addressMapToTokenMap( @@ -802,7 +823,7 @@ export const USDT: Record = { USDT_ADDRESS, ) as Omit< Record, - typeof ChainId.BSC & typeof ChainId.BSC_TESTNET + typeof ChainId.BSC & typeof ChainId.BSC_TESTNET & typeof ChainId.FLARE >), [ChainId.BSC]: new Token({ chainId: ChainId.BSC, @@ -1152,3 +1173,91 @@ export const MUSD = new Token({ symbol: 'MUSD', decimals: 18, }) + +export const ENOSYS_USDT = new Token({ + chainId: ChainId.FLARE, + address: '0x96B41289D90444B8adD57e6F265DB5aE8651DF29', + decimals: 6, + symbol: 'eUSDT', + name: 'Enosys USDT', +}) + +export const ENOSYS_WETH = new Token({ + chainId: ChainId.FLARE, + address: '0x62bD084cbcD6c85347C50292A141EA4D3e7e3511', + decimals: 18, + symbol: 'WETH', + name: 'Enosys WETH', +}) + +export const ENOSYS_BNZ = new Token({ + chainId: ChainId.FLARE, + address: '0xfD3449E8Ee31117a848D41Ee20F497a9bCb53164', + decimals: 18, + symbol: 'BNZ', + name: 'BonezCoin', +}) + +export const ENOSYS_EQNT = new Token({ + chainId: ChainId.FLARE, + address: '0x60fDC7B744E886e96Aa0DEf5f69eE440dB9d8c77', + decimals: 18, + symbol: 'eQNT', + name: 'EnosysQuant', +}) + +export const ENOSYS_HLN = new Token({ + chainId: ChainId.FLARE, + address: '0x140D8d3649Ec605CF69018C627fB44cCC76eC89f', + decimals: 18, + symbol: 'HLN', + name: 'Helion', +}) + +export const ENOSYS_APS = new Token({ + chainId: ChainId.FLARE, + address: '0xff56eb5b1a7faa972291117e5e9565da29bc808d', + decimals: 18, + symbol: 'APS', + name: 'Apsis', +}) + +export const ENOSYS_EETH = new Token({ + chainId: 14, + address: '0xa76dcddce60a442d69bac7158f3660f50921b122', + decimals: 18, + symbol: 'eETH', + name: 'Enosys ETH', +}) + +export const cUSDX = new Token({ + chainId: 14, + address: '0xFE2907DFa8DB6e320cDbF45f0aa888F6135ec4f8', + decimals: 6, + symbol: 'cUSDX', + name: 'USDX', +}) + +export const sFLR = new Token({ + chainId: 14, + address: '0x12e605bc104e93B45e1aD99F9e555f659051c2BB', + decimals: 18, + symbol: 'sFLR', + name: 'Staked FLR', +}) + +export const USDe = new Token({ + chainId: ChainId.BERA, + address: '0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34', + decimals: 18, + symbol: 'USDe', + name: 'USDe', +}) + +export const weETH = new Token({ + chainId: ChainId.BERA, + address: '0x7DCC39B4d1C53CB31e1aBc0e358b43987FEF80f7', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', +}) diff --git a/packages/sushi/src/router/data-fetcher.ts b/packages/sushi/src/router/data-fetcher.ts index e6069096f2..de32703cd4 100644 --- a/packages/sushi/src/router/data-fetcher.ts +++ b/packages/sushi/src/router/data-fetcher.ts @@ -2,32 +2,110 @@ import { http, PublicClient, createPublicClient } from 'viem' import { ChainId, TestnetChainId } from '../chain/index.js' import { publicClientConfig } from '../config/index.js' import { Type } from '../currency/index.js' +import { AerodromeSlipstreamProvider } from './liquidity-providers/AerodromeSlipstream.js' +import { AerodromeSlipstreamV2Provider } from './liquidity-providers/AerodromeSlipstreamV2.js' +import { AlienBaseV2Provider } from './liquidity-providers/AlienBaseV2.js' +import { AlienBaseV3Provider } from './liquidity-providers/AlienBaseV3.js' import { ApeSwapProvider } from './liquidity-providers/ApeSwap.js' +import { BSCSwapProvider } from './liquidity-providers/BSCSwap.js' +import { BakerySwapProvider } from './liquidity-providers/BakerySwap.js' +import { BaseSwapProvider } from './liquidity-providers/BaseSwap.js' +import { BaseSwapV3Provider } from './liquidity-providers/BaseSwapV3.js' import { BiswapProvider } from './liquidity-providers/Biswap.js' +import { BladeSwapProvider } from './liquidity-providers/BladeSwap.js' +import { BlastDEXProvider } from './liquidity-providers/BlastDEX.js' +import { BlazeSwapProvider } from './liquidity-providers/BlazeSwap.js' +import { CORExProvider } from './liquidity-providers/COREx.js' +import { CamelotProvider } from './liquidity-providers/Camelot.js' +import { CroDefiSwapProvider } from './liquidity-providers/CroDefiSwap.js' import { CurveProvider } from './liquidity-providers/CurveProvider.js' +import { DackieSwapV2Provider } from './liquidity-providers/DackieSwapV2.js' +import { DackieSwapV3Provider } from './liquidity-providers/DackieSwapV3.js' import { DfynProvider } from './liquidity-providers/Dfyn.js' import { DovishV3Provider } from './liquidity-providers/DovishV3.js' +import { DyorV2Provider } from './liquidity-providers/DyorV2.js' +import { EddyFinanceProvider } from './liquidity-providers/EddyFinance.js' import { ElkProvider } from './liquidity-providers/Elk.js' +import { EnosysProvider } from './liquidity-providers/Enosys.js' +import { FenixProvider } from './liquidity-providers/Fenix.js' +import { GlyphV4Provider } from './liquidity-providers/GlyphV4.js' +import { GravityFinanceProvider } from './liquidity-providers/GravityFinance.js' import { HoneySwapProvider } from './liquidity-providers/HoneySwap.js' +import { HorizonProvider } from './liquidity-providers/Horizon.js' +import { HydrexProvider } from './liquidity-providers/Hydrex.js' +import { HyperBlastProvider } from './liquidity-providers/HyperBlast.js' import { JetSwapProvider } from './liquidity-providers/JetSwap.js' +import { KimV4Provider } from './liquidity-providers/KimV4.js' +import { KinetixV2Provider } from './liquidity-providers/KinetixV2.js' +import { KinetixV3Provider } from './liquidity-providers/KinetixV3.js' +import { KodiakV2Provider } from './liquidity-providers/KodiakV2.js' +import { KodiakV3Provider } from './liquidity-providers/KodiakV3.js' +import { KwikswapProvider } from './liquidity-providers/Kwikswap.js' import { LaserSwapV2Provider } from './liquidity-providers/LaserSwap.js' import { LiquidityProvider, LiquidityProviders, } from './liquidity-providers/LiquidityProvider.js' +import { LynexV1Provider } from './liquidity-providers/LynexV1.js' +import { LynexV2Provider } from './liquidity-providers/LynexV2.js' +import { MMFinanceProvider } from './liquidity-providers/MMFinance.js' +import { MSwapProvider } from './liquidity-providers/MSwap.js' +import { MonoswapV2Provider } from './liquidity-providers/MonoSwapV2.js' +import { MonoswapV3Provider } from './liquidity-providers/MonoSwapV3.js' import { NativeWrapProvider } from './liquidity-providers/NativeWrapProvider.js' import { NetSwapProvider } from './liquidity-providers/NetSwap.js' -import { PancakeSwapProvider } from './liquidity-providers/PancakeSwap.js' -import { QuickSwapProvider } from './liquidity-providers/QuickSwap.js' -import { SpookySwapProvider } from './liquidity-providers/SpookySwap.js' +import { NileV3Provider } from './liquidity-providers/NileV3.js' +import { NineInchProvider } from './liquidity-providers/NineInch.js' +import { PancakeSwapV2Provider } from './liquidity-providers/PancakeSwapV2.js' +import { PancakeSwapV3Provider } from './liquidity-providers/PancakeSwapV3.js' +import { PangolinProvider } from './liquidity-providers/Pangolin.js' +import { QuickSwapV2Provider } from './liquidity-providers/QuickSwapV2.js' +import { QuickSwapV3Provider } from './liquidity-providers/QuickswapV3.js' +import { RingExchangeV2Provider } from './liquidity-providers/RingExchangeV2.js' +import { RingExchangeV3Provider } from './liquidity-providers/RingExchangeV3.js' +import { ScribeProvider } from './liquidity-providers/Scribe.js' +import { ShibaSwapProvider } from './liquidity-providers/ShibaSwap.js' +import { SolarbeamProvider } from './liquidity-providers/Solarbeam.js' +import { SparkDexV2Provider } from './liquidity-providers/SparkDexV2.js' +import { SparkDexV3Provider } from './liquidity-providers/SparkDexV3.js' +import { SparkDexV3_1Provider } from './liquidity-providers/SparkDexV3_1.js' +import { SpookySwapV2Provider } from './liquidity-providers/SpookySwapV2.js' +import { SpookySwapV3Provider } from './liquidity-providers/SpookySwapV3.js' +import { SquadSwapV2Provider } from './liquidity-providers/SquadSwapV2.js' import { SushiSwapV2Provider } from './liquidity-providers/SushiSwapV2.js' import { SushiSwapV3Provider } from './liquidity-providers/SushiSwapV3.js' +import { SwapBlastProvider } from './liquidity-providers/SwapBlast.js' +import { SwapsicleProvider } from './liquidity-providers/Swapsicle.js' +import { + ThrusterV2_1Provider, + ThrusterV2_3Provider, +} from './liquidity-providers/ThrusterV2.js' +import { ThrusterV3Provider } from './liquidity-providers/ThrusterV3.js' import { TraderJoeProvider } from './liquidity-providers/TraderJoe.js' import { TridentProvider } from './liquidity-providers/Trident.js' import { UbeSwapProvider } from './liquidity-providers/UbeSwap.js' import { UniswapV2Provider } from './liquidity-providers/UniswapV2.js' import { UniswapV3Provider } from './liquidity-providers/UniswapV3.js' +import { VVSFlawlessProvider } from './liquidity-providers/VVSFlawless.js' +import { VVSStandardProvider } from './liquidity-providers/VVSStandard.js' +import { VelodromeSlipstreamProvider } from './liquidity-providers/VelodromeSlipstream.js' +import { WagmiProvider } from './liquidity-providers/Wagmi.js' +import { WigoswapProvider } from './liquidity-providers/Wigoswap.js' +import { ZebraV2Provider } from './liquidity-providers/ZebraV2.js' import type { PoolCode } from './pool-codes/index.js' +import { promiseTimeout } from './timeout.js' + +// options for data fetching, such as pinning block number and memoize +export type DataFetcherOptions = { + /** + * The pinned block number when getting onchain data + * this option is usefull for reproducing the route, + * price, etc of a certain block + */ + blockNumber?: bigint + /** Determines a timeout (in ms) for fetching pools for a token pair */ + fetchPoolsTimeout?: number +} // TODO: Should be a mode on the config for DataFetcher const isTest = @@ -110,26 +188,90 @@ export class DataFetcher { // concrete providers this.providers = [new NativeWrapProvider(this.chainId, this.web3Client)] ;[ + AerodromeSlipstreamProvider, + AerodromeSlipstreamV2Provider, + AlienBaseV2Provider, + AlienBaseV3Provider, ApeSwapProvider, + BakerySwapProvider, + BaseSwapProvider, + BaseSwapV3Provider, BiswapProvider, + BladeSwapProvider, + BlastDEXProvider, + BlazeSwapProvider, + BSCSwapProvider, + CamelotProvider, + CORExProvider, + CroDefiSwapProvider, CurveProvider, + DackieSwapV2Provider, + DackieSwapV3Provider, DfynProvider, DovishV3Provider, + DyorV2Provider, + EddyFinanceProvider, ElkProvider, + EnosysProvider, + FenixProvider, + GlyphV4Provider, + GravityFinanceProvider, HoneySwapProvider, + HorizonProvider, + HyperBlastProvider, + HydrexProvider, JetSwapProvider, + KimV4Provider, + KinetixV2Provider, + KinetixV3Provider, + KodiakV2Provider, + KodiakV3Provider, + KwikswapProvider, LaserSwapV2Provider, + LynexV1Provider, + LynexV2Provider, + MMFinanceProvider, + MonoswapV2Provider, + MonoswapV3Provider, + MSwapProvider, NetSwapProvider, - PancakeSwapProvider, - SpookySwapProvider, + // NileV2Provider, + NileV3Provider, + NineInchProvider, + PancakeSwapV2Provider, + PancakeSwapV3Provider, + PangolinProvider, + QuickSwapV2Provider, + QuickSwapV3Provider, + RingExchangeV2Provider, + RingExchangeV3Provider, + ScribeProvider, + ShibaSwapProvider, + SolarbeamProvider, + SparkDexV2Provider, + SparkDexV3Provider, + SparkDexV3_1Provider, + SpookySwapV2Provider, + SpookySwapV3Provider, + SquadSwapV2Provider, SushiSwapV2Provider, SushiSwapV3Provider, + SwapBlastProvider, + SwapsicleProvider, + ThrusterV2_1Provider, + ThrusterV2_3Provider, + ThrusterV3Provider, TraderJoeProvider, - QuickSwapProvider, TridentProvider, UbeSwapProvider, UniswapV2Provider, UniswapV3Provider, + VelodromeSlipstreamProvider, + VVSStandardProvider, + VVSFlawlessProvider, + WagmiProvider, + WigoswapProvider, + ZebraV2Provider, ].forEach((p) => { try { const provider = new p(this.chainId, this.web3Client) @@ -169,6 +311,7 @@ export class DataFetcher { currency0: Type, currency1: Type, excludePools?: Set, + options?: DataFetcherOptions, ): Promise { // console.log('PROVIDER COUNT', this.providers.length) // ensure that we only fetch the native wrap pools if the token is the native currency and wrapped native currency @@ -177,11 +320,26 @@ export class DataFetcher { (p) => p.getType() === LiquidityProviders.NativeWrap, ) if (provider) { - await provider.fetchPoolsForToken( - currency0.wrapped, - currency1.wrapped, - excludePools, - ) + try { + options?.fetchPoolsTimeout + ? await promiseTimeout( + provider.fetchPoolsForToken( + currency0.wrapped, + currency1.wrapped, + excludePools, + options, + ), + options.fetchPoolsTimeout, + ) + : await provider.fetchPoolsForToken( + currency0.wrapped, + currency1.wrapped, + excludePools, + options, + ) + } catch { + /**/ + } } } else { const [token0, token1] = @@ -189,11 +347,24 @@ export class DataFetcher { currency0.wrapped.sortsBefore(currency1.wrapped) ? [currency0.wrapped, currency1.wrapped] : [currency1.wrapped, currency0.wrapped] - await Promise.all( - this.providers.map((p) => - p.fetchPoolsForToken(token0, token1, excludePools), - ), - ) + try { + options?.fetchPoolsTimeout + ? await promiseTimeout( + Promise.allSettled( + this.providers.map((p) => + p.fetchPoolsForToken(token0, token1, excludePools, options), + ), + ), + options.fetchPoolsTimeout, + ) + : await Promise.allSettled( + this.providers.map((p) => + p.fetchPoolsForToken(token0, token1, excludePools, options), + ), + ) + } catch { + /**/ + } } } diff --git a/packages/sushi/src/router/index.ts b/packages/sushi/src/router/index.ts index b932bd8576..479badcd76 100644 --- a/packages/sushi/src/router/index.ts +++ b/packages/sushi/src/router/index.ts @@ -9,3 +9,4 @@ export * from './tines-to-route-processor-2.js' export * from './tines-to-route-processor-4.js' export * from './PoolBinarySerialization.js' export * from './Sankey.AnyChart.js' +export * from './rain/RainDataFetcher.js' diff --git a/packages/sushi/src/router/liquidity-providers/AerodromeSlipstream.ts b/packages/sushi/src/router/liquidity-providers/AerodromeSlipstream.ts new file mode 100644 index 0000000000..9dbe16e5ef --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/AerodromeSlipstream.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { VelodromeSlipstreamBaseProvider } from '../rain/VelodromeSlipstreamBase.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class AerodromeSlipstreamProvider extends VelodromeSlipstreamBaseProvider { + override DEFAULT_TICK_SPACINGS = [1, 50, 100, 200, 2000, 10] as any + override tickSpacings: number[] = [...this.DEFAULT_TICK_SPACINGS] + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x5e7BB104d84c7CB9B682AaC2F3d509f5F406809A', + } as const + const tickLens = { + [ChainId.BASE]: '0x3e1116ea5034f5d73a7b530071709d54a4109f5f', + } as const + super(chainId, web3Client, factory, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.AerodromeSlipstream + } + getPoolProviderName(): string { + return 'AerodromeSlipstream' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/AerodromeSlipstreamV2.ts b/packages/sushi/src/router/liquidity-providers/AerodromeSlipstreamV2.ts new file mode 100644 index 0000000000..055bbc53ed --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/AerodromeSlipstreamV2.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { VelodromeSlipstreamBaseProvider } from '../rain/VelodromeSlipstreamBase.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class AerodromeSlipstreamV2Provider extends VelodromeSlipstreamBaseProvider { + override DEFAULT_TICK_SPACINGS = [1, 50, 100, 200, 2000, 10, 500] as any + override tickSpacings: number[] = [...this.DEFAULT_TICK_SPACINGS] + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0xaDe65c38CD4849aDBA595a4323a8C7DdfE89716a', + } as const + const tickLens = { + [ChainId.BASE]: '0x3e1116ea5034f5d73a7b530071709d54a4109f5f', + } as const + super(chainId, web3Client, factory, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.AerodromeSlipstreamV2 + } + getPoolProviderName(): string { + return 'AerodromeSlipstreamV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/AlgebraIntegralV1Base.ts b/packages/sushi/src/router/liquidity-providers/AlgebraIntegralV1Base.ts new file mode 100644 index 0000000000..f8b0dccddb --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/AlgebraIntegralV1Base.ts @@ -0,0 +1,22 @@ +import { AlgebraV1BaseProvider } from '../rain/AlgebraV1Base.js' + +export const globalStateAbi = [ + { + inputs: [], + name: 'globalState', + outputs: [ + { internalType: 'uint160', name: 'price', type: 'uint160' }, + { internalType: 'int24', name: 'tick', type: 'int24' }, + { internalType: 'uint16', name: 'lastFee', type: 'uint16' }, + { internalType: 'uint8', name: 'pluginConfig', type: 'uint8' }, + { internalType: 'uint16', name: 'communityFee', type: 'uint16' }, + { internalType: 'bool', name: 'unlocked', type: 'bool' }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const + +export abstract class AlgebraIntegralV1BaseProvider extends AlgebraV1BaseProvider { + override gloablStateAbi = globalStateAbi as any +} diff --git a/packages/sushi/src/router/liquidity-providers/AlgebraIntegralV1_2Base.ts b/packages/sushi/src/router/liquidity-providers/AlgebraIntegralV1_2Base.ts new file mode 100644 index 0000000000..1d19cbad91 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/AlgebraIntegralV1_2Base.ts @@ -0,0 +1,225 @@ +import { Log, parseAbiItem, parseEventLogs } from 'viem' +import { RainV3Pool } from '../rain/UniswapV3Base.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' + +export const AlgebraIntegralV1_2EventsAbi = [ + parseAbiItem( + 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint24 overrideFee, uint24 pluginFee)', + ), + parseAbiItem( + 'event Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)', + ), + parseAbiItem( + 'event Collect(address indexed owner, address recipient, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount0, uint128 amount1)', + ), + parseAbiItem( + 'event Burn(address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1, uint24 pluginFee)', + ), + parseAbiItem( + 'event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1)', + ), + parseAbiItem('event Fee(uint16 fee)'), + parseAbiItem('event TickSpacing(int24 newTickSpacing)'), + parseAbiItem( + 'event Pool(address indexed token0, address indexed token1, address pool)', + ), +] + +export abstract class AlgebraIntegralV1_2BaseProvider extends AlgebraIntegralV1BaseProvider { + override eventsAbi = AlgebraIntegralV1_2EventsAbi + // used for pools that need reserve refetch upon swap with non zero plugin fee + onSwapPluginFeeUpdatePools: RainV3Pool[] = [] + + override async afterProcessLog(untilBlock: bigint) { + const reservesPromise = this.getReserves(this.onSwapPluginFeeUpdatePools, { + blockNumber: untilBlock, + }) + const ticksPromise = this.getTicks(this.onSwapPluginFeeUpdatePools, { + blockNumber: untilBlock, + }) + const newTicksQueue = [...this.newTicksQueue.splice(0)] + if (newTicksQueue.length) { + const newTicks = await this.getTicksInner(newTicksQueue, { + blockNumber: untilBlock, + }) + if (newTicks) { + newTicksQueue.forEach(([pool], i) => { + newTicks?.[i]?.forEach((newTick, index) => { + pool.ticks.set(index, newTick) + }) + }) + } else { + // if unsuccessfull to get new ticks, put them back on queue for next try + this.newTicksQueue.push(...newTicksQueue) + } + } + const reserves = await reservesPromise + const ticks = await ticksPromise + for (let i = 0; i < this.onSwapPluginFeeUpdatePools.length; i++) { + const pool = this.onSwapPluginFeeUpdatePools[i] + const reserve = reserves[i] + const tick = ticks?.[i] + if (!pool) continue + if (typeof reserve !== 'undefined') { + pool.reserve0 = reserve[0]! + pool.reserve1 = reserve[1]! + } + if (typeof tick !== 'undefined') { + pool.ticks = tick + } + } + this.onSwapPluginFeeUpdatePools = [] + } + + /** + * Handles pool events and updates the pool cache with the results + */ + override handlePoolEvents(log: Log) { + const logAddress = log.address.toLowerCase() + const pool = this.pools.get(logAddress) + if (pool) { + try { + const event = parseEventLogs({ logs: [log], abi: this.eventsAbi })[0]! + switch (event.eventName) { + case 'Mint': { + const { amount, amount0, amount1 } = event.args + const { tickLower, tickUpper } = event.args + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + const tick = pool.activeTick + if (tickLower <= tick && tick < tickUpper) + pool.liquidity += amount + } + if (amount1 !== undefined && amount0 !== undefined) { + pool.reserve0 += amount0 + pool.reserve1 += amount1 + } + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + this.addTick(tickLower, amount, pool) + this.addTick(tickUpper, -amount, pool) + } + } + break + } + case 'Burn': { + const { amount } = event.args + const { tickLower, tickUpper } = event.args + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + const tick = pool.activeTick + if (tickLower <= tick && tick < tickUpper) + pool.liquidity -= amount + } + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + this.addTick(tickLower, -amount, pool) + this.addTick(tickUpper, amount, pool) + } + } + break + } + case 'Collect': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + const { amount0, amount1 } = event.args + if (amount0 !== undefined && amount1 !== undefined) { + pool.reserve0 -= amount0 + pool.reserve1 -= amount1 + } + } + break + } + case 'Flash': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + const { paid0, paid1 } = event.args + if (paid0 !== undefined && paid1 !== undefined) { + pool.reserve0 += paid0 + pool.reserve1 += paid1 + } + } + break + } + case 'Swap': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + const { + amount0, + amount1, + sqrtPriceX96, + liquidity, + tick, + pluginFee, + overrideFee, + } = event.args + if (amount0 !== undefined && amount1 !== undefined) { + pool.reserve0 += amount0 + pool.reserve1 += amount1 + } + if (sqrtPriceX96 !== undefined) pool.sqrtPriceX96 = sqrtPriceX96 + if (liquidity !== undefined) pool.liquidity = liquidity + // need to refecth balance if there custom fee on swap + const onSwapPoolExists = this.onSwapPluginFeeUpdatePools.find( + (v) => v.address.toLowerCase() === pool.address.toLowerCase(), + ) + if (pluginFee > 0n || overrideFee > 0n) { + if (!onSwapPoolExists) { + this.onSwapPluginFeeUpdatePools.push(pool) + const index = this.newTicksQueue.findIndex( + (v) => v[0].address === pool.address, + ) + if (index > -1) { + this.newTicksQueue.splice(index, 1) + } + } + if (tick !== undefined) { + pool.tick = tick + pool.activeTick = + Math.floor(tick / pool.tickSpacing) * pool.tickSpacing + } + } else if (tick !== undefined) { + if (!onSwapPoolExists) { + pool.tick = tick + pool.activeTick = + Math.floor(tick / pool.tickSpacing) * pool.tickSpacing + const newTicks = this.onPoolTickChange(pool.activeTick, pool) + const queue = this.newTicksQueue.find( + (v) => v[0].address === pool.address, + ) + if (queue) { + for (const t of newTicks) { + if (!queue[1].includes(t)) queue[1].push(t) + } + } else { + this.newTicksQueue.push([pool, newTicks]) + } + } + } + } + break + } + default: { + this.otherEventCases(log, event, pool) + } + } + } catch {} + } + } +} diff --git a/packages/sushi/src/router/liquidity-providers/AlienBaseV2.ts b/packages/sushi/src/router/liquidity-providers/AlienBaseV2.ts new file mode 100644 index 0000000000..7d64f83212 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/AlienBaseV2.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class AlienBaseV2Provider extends UniswapV2BaseProvider { + override fee = 0.0016 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x3E84D913803b02A4a7f027165E8cA42C14C0FdE7', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0x7ede5bbb7d245103c4a6d59bfd62246fbc488e93f95f23a19d9d76f0d91bd0d0', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.AlienBaseV2 + } + getPoolProviderName(): string { + return 'AlienBaseV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/AlienBaseV3.ts b/packages/sushi/src/router/liquidity-providers/AlienBaseV3.ts new file mode 100644 index 0000000000..320cbb6c51 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/AlienBaseV3.ts @@ -0,0 +1,52 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +/** + * The default factory enabled fee amounts, denominated in hundredths of bips. + */ +export enum AlienBaseV3FeeAmount { + /** 0.02% */ + LOWEST = 200, + /** 0.075% */ + LOW = 750, + /** 0.3% */ + MEDIUM = 3000, + /** 1% */ + HIGH = 10000, +} + +export const ALIENBASE_V3_FEE_SPACING_MAP: Record< + AlienBaseV3FeeAmount, + number +> = { + [AlienBaseV3FeeAmount.LOWEST]: 4, + [AlienBaseV3FeeAmount.LOW]: 15, + [AlienBaseV3FeeAmount.MEDIUM]: 60, + [AlienBaseV3FeeAmount.HIGH]: 200, +} + +export class AlienBaseV3Provider extends UniswapV3BaseProvider { + override FEE = AlienBaseV3FeeAmount + override TICK_SPACINGS = ALIENBASE_V3_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x0Fd83557b2be93617c9C1C1B6fd549401C74558C', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.BASE]: '0xe3B6A547495c84A039D70A81178496220B5Fbd8e', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.AlienBaseV3 + } + getPoolProviderName(): string { + return 'AlienBaseV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/ApeSwap.ts b/packages/sushi/src/router/liquidity-providers/ApeSwap.ts index 71d8d5674f..3cef677d15 100644 --- a/packages/sushi/src/router/liquidity-providers/ApeSwap.ts +++ b/packages/sushi/src/router/liquidity-providers/ApeSwap.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class ApeSwapProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { @@ -10,6 +10,7 @@ export class ApeSwapProvider extends UniswapV2BaseProvider { [ChainId.POLYGON]: '0xCf083Be4164828f00cAE704EC15a36D711491284', [ChainId.BSC]: '0x0841BD0B734E4F5853f0dD8d7Ea041c241fb0Da6', [ChainId.TELOS]: '0x411172Dfcd5f68307656A1ff35520841C2F7fAec', + [ChainId.ARBITRUM]: '0xCf083Be4164828f00cAE704EC15a36D711491284', } as const const initCodeHash = { [ChainId.ETHEREUM]: @@ -20,6 +21,8 @@ export class ApeSwapProvider extends UniswapV2BaseProvider { '0xf4ccce374816856d11f00e4069e7cada164065686fbef53c6167a63ec2fd8c5b', [ChainId.TELOS]: '0x7d4b9bb0d5808344c0184aada7d10aae8f6b0cc8ceb5eba8dd084f63b8c32099', + [ChainId.ARBITRUM]: + '0xae7373e804a043c4c08107a81def627eeb3792e211fb4711fcfe32f0e4c45fd5', } as const super(chainId, web3Client, factory, initCodeHash) } diff --git a/packages/sushi/src/router/liquidity-providers/BSCSwap.ts b/packages/sushi/src/router/liquidity-providers/BSCSwap.ts new file mode 100644 index 0000000000..37068a9247 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BSCSwap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class BSCSwapProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BSC]: '0xCe8fd65646F2a2a897755A1188C04aCe94D2B8D0', + } as const + const initCodeHash = { + [ChainId.BSC]: + '0xacc1c81cc3e9fb496da555f6bd67c3a095e579b26c1b580070cc6afa8f0a94fa', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.BSCSwap + } + getPoolProviderName(): string { + return 'BSCSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/BakerySwap.ts b/packages/sushi/src/router/liquidity-providers/BakerySwap.ts new file mode 100644 index 0000000000..8c62d7e7e1 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BakerySwap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class BakerySwapProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BSC]: '0x01bF7C66c6BD861915CdaaE475042d3c4BaE16A7', + } as const + const initCodeHash = { + [ChainId.BSC]: + '0xe2e87433120e32c4738a7d8f3271f3d872cbe16241d67537139158d90bac61d3', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.BakerySwap + } + getPoolProviderName(): string { + return 'BakerySwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/BaseSwap.ts b/packages/sushi/src/router/liquidity-providers/BaseSwap.ts new file mode 100644 index 0000000000..a8cdcf9163 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BaseSwap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class BaseSwapProvider extends UniswapV2BaseProvider { + override fee = 0.0025 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0xFDa619b6d20975be80A10332cD39b9a4b0FAa8BB', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0xb618a2730fae167f5f8ac7bd659dd8436d571872655bcb6fd11f2158c8a64a3b', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.BaseSwap + } + getPoolProviderName(): string { + return 'BaseSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/BaseSwapV3.ts b/packages/sushi/src/router/liquidity-providers/BaseSwapV3.ts new file mode 100644 index 0000000000..e2dd0924c6 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BaseSwapV3.ts @@ -0,0 +1,53 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +/** + * The default factory enabled fee amounts, denominated in hundredths of bips. + */ +export enum BaseSwapV3FeeAmount { + /** 0.008% */ + LOWEST = 80, + /** 0.035% */ + LOW = 350, + /** 0.045% */ + MEDIUM = 450, + /** 0.25% */ + HIGH = 2500, + /** 1% */ + HIGHEST = 10000, +} + +export const BASESWAP_V3_FEE_SPACING_MAP: Record = + { + [BaseSwapV3FeeAmount.LOWEST]: 1, + [BaseSwapV3FeeAmount.LOW]: 10, + [BaseSwapV3FeeAmount.MEDIUM]: 10, + [BaseSwapV3FeeAmount.HIGH]: 60, + [BaseSwapV3FeeAmount.HIGHEST]: 200, + } + +export class BaseSwapV3Provider extends UniswapV3BaseProvider { + override FEE = BaseSwapV3FeeAmount + override TICK_SPACINGS = BASESWAP_V3_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x38015D05f4fEC8AFe15D7cc0386a126574e8077B', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.BASE]: '0xe3B6A547495c84A039D70A81178496220B5Fbd8e', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.BaseSwapV3 + } + getPoolProviderName(): string { + return 'BaseSwapV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Biswap.ts b/packages/sushi/src/router/liquidity-providers/Biswap.ts index 94291d30a0..8e8aab8b99 100644 --- a/packages/sushi/src/router/liquidity-providers/Biswap.ts +++ b/packages/sushi/src/router/liquidity-providers/Biswap.ts @@ -1,8 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' - +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class BiswapProvider extends UniswapV2BaseProvider { override fee = 0.002 diff --git a/packages/sushi/src/router/liquidity-providers/BladeSwap.ts b/packages/sushi/src/router/liquidity-providers/BladeSwap.ts new file mode 100644 index 0000000000..b80247e5c6 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BladeSwap.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class BladeSwapProvider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0xA87DbF5082Af26c9A6Ab2B854E378f704638CCa5', + } as const + const poolDeployer = { + [ChainId.BLAST]: '0xfFeEcb1fe0EAaEFeE69d122F6B7a0368637cb593', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0xa9df2657ce5872e94bdc9525588fd983b0aa5db2f3c7a83d7e6b6a99cd2003a1', + } as const + const tickLens = { + [ChainId.BLAST]: '0x969195B66f95D8B70fA414671b438134889Ba348', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.BladeSwap + } + getPoolProviderName(): string { + return 'BladeSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/BlastDEX.ts b/packages/sushi/src/router/liquidity-providers/BlastDEX.ts new file mode 100644 index 0000000000..81a12e83c6 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BlastDEX.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class BlastDEXProvider extends UniswapV2BaseProvider { + override fee = 0.002 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x66346aac17d0e61156AC5F2A934ccF2a9BDe4c65', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x376acff9b60b853f5ccc9f1caecb8dcf722793593330ac58aac8a880a3eb8b9e', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.BlastDEX + } + getPoolProviderName(): string { + return 'BlastDEX' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/BlazeSwap.ts b/packages/sushi/src/router/liquidity-providers/BlazeSwap.ts new file mode 100644 index 0000000000..6a5334b508 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/BlazeSwap.ts @@ -0,0 +1,23 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class BlazeSwapProvider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FLARE]: '0x440602f459D7Dd500a74528003e6A20A46d6e2A6', + } as const + const initCodeHash = { + [ChainId.FLARE]: + '0xbf4c1c435583a2bb8d763765a34a46e376071c3b3d80e5bbac0950aeecdf31cb', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.BlazeSwap + } + getPoolProviderName(): string { + return 'BlazeSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/COREx.ts b/packages/sushi/src/router/liquidity-providers/COREx.ts new file mode 100644 index 0000000000..45c60dbcc2 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/COREx.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class CORExProvider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.CORE]: '0x526190295AFB6b8736B14E4b42744FBd95203A3a', + } as const + const initCodeHash = { + [ChainId.CORE]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.CORE]: '0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.COREx + } + getPoolProviderName(): string { + return 'COREx' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Camelot.ts b/packages/sushi/src/router/liquidity-providers/Camelot.ts new file mode 100644 index 0000000000..e2f61130d9 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Camelot.ts @@ -0,0 +1,180 @@ +import { Address, PublicClient, parseAbi } from 'viem' +import { ChainId } from '../../chain/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' +import { type PoolCode } from '../pool-codes/index.js' +import { LiquidityProviders } from './LiquidityProvider.js' +import { UniswapV2BaseProvider } from './UniswapV2Base.js' + +type IsStableSwap = + | ( + | boolean + | { + error?: undefined + result: boolean + status: 'success' + } + | { + error: Error + result?: undefined + status: 'failure' + } + )[] + | undefined + +export class CamelotProvider extends UniswapV2BaseProvider { + // Camelot has a slightly different getReserves() abi + // so needs to be overriden + override getReservesAbi = parseAbi([ + 'function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint16 _token0FeePercent, uint16 _token1FeePercent)', + ]) + FEE_DENOMINATOR = 100_000n + FEE_INFO: [bigint, `0x${string}`] | undefined = undefined + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ARBITRUM]: '0x6EcCab422D763aC031210895C81787E87B43A652', + } as const + const initCodeHash = { + [ChainId.ARBITRUM]: + '0xa856464ae65f7619087bc369daaf7e387dae1e5af69cfa7935850ebf754b04c1', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.Camelot + } + getPoolProviderName(): string { + return 'Camelot' + } + + override async getReserves( + poolCodesToCreate: Address[], + options?: DataFetcherOptions, + ): Promise { + if (!this.FEE_INFO) { + try { + this.FEE_INFO = (await this.client.readContract({ + address: this.factory[ + this.chainId as keyof typeof this.factory + ]! as `0x${string}`, + abi: [ + { + constant: true, + inputs: [], + name: 'feeInfo', + outputs: [ + { + internalType: 'uint256', + name: '_ownerFeeShare', + type: 'uint256', + }, + { internalType: 'address', name: '_feeTo', type: 'address' }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + ] as const, + functionName: 'feeInfo', + })) as any + } catch (_error) { + /**/ + } + } + + const getReservesData = { + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: poolCodesToCreate.map( + (address) => + ({ + address, + chainId: this.chainId, + abi: this.getReservesAbi, + functionName: 'getReserves', + }) as const, + ), + } as const + const reserves = await this.client.multicall(getReservesData).catch((e) => { + console.warn( + `${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + const stableSwapData = { + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: poolCodesToCreate.map( + (address) => + ({ + address, + chainId: this.chainId, + abi: [ + { + constant: true, + inputs: [], + name: 'stableSwap', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + payable: false, + }, + ] as const, + functionName: 'stableSwap', + }) as const, + ), + } as const + const stableSwap: IsStableSwap = await this.client + .multicall(stableSwapData) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + return [reserves, stableSwap] + } + + override handleCreatePoolCode( + poolCodesToCreate: PoolCode[], + contractData: [any[], IsStableSwap], + validUntilTimestamp: number, + ) { + const [reserves, stableSwaps] = contractData + poolCodesToCreate.forEach((poolCode, i) => { + const thisStableSwap = stableSwaps?.[i] + const isStableSwap = + typeof thisStableSwap === 'boolean' + ? thisStableSwap + : thisStableSwap?.status === 'success' + ? thisStableSwap?.result + : undefined + const pool = poolCode.pool + const res0 = reserves?.[i]?.result?.[0] + const res1 = reserves?.[i]?.result?.[1] + + if (res0 !== undefined && res1 !== undefined) { + if (isStableSwap && this.FEE_INFO && pool.fee) { + try { + ;(pool.fee as any) += + (Number(this.FEE_INFO[0]) / Number(this.FEE_DENOMINATOR)) * + pool.fee + } catch {} + } + pool.updateReserves(res0, res1) + this.onDemandPools.set(pool.address, { poolCode, validUntilTimestamp }) + } else { + // Pool doesn't exist? + } + }) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/CroDefiSwap.ts b/packages/sushi/src/router/liquidity-providers/CroDefiSwap.ts new file mode 100644 index 0000000000..74572e96d5 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/CroDefiSwap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class CroDefiSwapProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ETHEREUM]: '0x9DEB29c9a4c7A88a3C0257393b7f3335338D9A9D', + } as const + const initCodeHash = { + [ChainId.ETHEREUM]: + '0x69d637e77615df9f235f642acebbdad8963ef35c5523142078c9b8f9d0ceba7e', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.CroDefiSwap + } + getPoolProviderName(): string { + return 'CroDefiSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/CurveProvider.ts b/packages/sushi/src/router/liquidity-providers/CurveProvider.ts index 837f850d44..0fba00bd66 100644 --- a/packages/sushi/src/router/liquidity-providers/CurveProvider.ts +++ b/packages/sushi/src/router/liquidity-providers/CurveProvider.ts @@ -18,6 +18,7 @@ import { } from '../../currency/index.js' import { Native, Token, Type } from '../../currency/index.js' import { RToken, createCurvePoolsForMultipool } from '../../tines/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' import { getCurrencyCombinations } from '../get-currency-combinations.js' import { CurvePoolCode } from '../pool-codes/CurvePool.js' import { PoolCode } from '../pool-codes/PoolCode.js' @@ -379,9 +380,11 @@ export class CurveProvider extends LiquidityProvider { t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise> { const pools: Map = new Map() let currencyCombinations = getCurrencyCombinations(this.chainId, t0, t1) + for (let i = 0; currencyCombinations.length > 0; ++i) { const calls = (CURVE_FACTORY_ADDRESSES[this.chainId] ?? []).flatMap( (factory) => @@ -401,8 +404,10 @@ export class CurveProvider extends LiquidityProvider { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as '0x${string}', allowFailure: true, + blockNumber: options?.blockNumber, contracts: calls, }) + newFoundPools.forEach((pool, i) => { if ( pool.status === 'success' && @@ -429,12 +434,14 @@ export class CurveProvider extends LiquidityProvider { async getPoolRatio( pools: [string, [CurvePoolType, Type[]]][], + options?: DataFetcherOptions, ): Promise<(number[] | undefined)[]> { if (this.chainId === ChainId.ETHEREUM) { const ratios = await this.client.multicall({ multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as '0x${string}', allowFailure: true, + blockNumber: options?.blockNumber, contracts: [ { address: '0xE95A203B1a91a908F9B9CE46459d101078c2c3cb', // ankr @@ -468,6 +475,7 @@ export class CurveProvider extends LiquidityProvider { }, ], }) + return pools.map(([poolAddress]) => { // collection of freaks switch (poolAddress.toLowerCase()) { @@ -498,9 +506,10 @@ export class CurveProvider extends LiquidityProvider { async getCurvePoolCodes( pools: Map, + options?: DataFetcherOptions, ): Promise { const poolArray = Array.from(pools.entries()) - const poolsMulticall = < + const poolsMulticall = async < T extends ContractFunctionParameters< (typeof curvePoolABI)[keyof typeof curvePoolABI] >['functionName'], @@ -516,6 +525,7 @@ export class CurveProvider extends LiquidityProvider { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as '0x${string}', allowFailure: true, + blockNumber: options?.blockNumber, contracts: poolArray.map(([address, [poolType]]) => ({ address: address as Address, // //chainId: this.chainId, @@ -581,9 +591,10 @@ export class CurveProvider extends LiquidityProvider { t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise { - const pools = await this.getPoolsForTokens(t0, t1, excludePools) - this.foundPools = await this.getCurvePoolCodes(pools) + const pools = await this.getPoolsForTokens(t0, t1, excludePools, options) + this.foundPools = await this.getCurvePoolCodes(pools, options) //console.log(JSON.stringify(this.foundPools, undefined, ' ')) } diff --git a/packages/sushi/src/router/liquidity-providers/DackieSwapV2.ts b/packages/sushi/src/router/liquidity-providers/DackieSwapV2.ts new file mode 100644 index 0000000000..556331f4e5 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/DackieSwapV2.ts @@ -0,0 +1,36 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class DackieSwapV2Provider extends UniswapV2BaseProvider { + override fee = 0.0025 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x591f122D1df761E616c13d265006fcbf4c6d6551', + [ChainId.OPTIMISM]: '0xaEdc38bD52b0380b2Af4980948925734fD54FbF4', + [ChainId.ARBITRUM]: '0x507940c2469e6E3B33032F1d4FF8d123BDDe2f5C', + [ChainId.BLAST]: '0xF5190E64dB4cbf7ee5E72B55cC5b2297e20264c2', + [ChainId.LINEA]: '0x9790713770039CeFcf4FAaf076E2846c9B7a4630', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0xaaaacde43ad77b69fcbcdc68ccb757c3c634ad20e330a951b4a267f1180c6520', + [ChainId.OPTIMISM]: + '0x6583f40d4a27d36b2f66ec686363a3fc9a3b0f4d748e788cd6e8e2773e4ee898', + [ChainId.ARBITRUM]: + '0x6583f40d4a27d36b2f66ec686363a3fc9a3b0f4d748e788cd6e8e2773e4ee898', + [ChainId.BLAST]: + '0x08b78b4ee8893b0d52edf9be019ea4e261e38b8eb1e0d7be8940645e8f95aa28', + [ChainId.LINEA]: + '0x6583f40d4a27d36b2f66ec686363a3fc9a3b0f4d748e788cd6e8e2773e4ee898', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.DackieSwapV2 + } + getPoolProviderName(): string { + return 'DackieSwapV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/DackieSwapV3.ts b/packages/sushi/src/router/liquidity-providers/DackieSwapV3.ts new file mode 100644 index 0000000000..67a9040e41 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/DackieSwapV3.ts @@ -0,0 +1,108 @@ +import { Address, PublicClient } from 'viem' +import { uniswapV3FactoryAbi } from '../../abi/uniswapV3FactoryAbi.js' +import { ChainId } from '../../chain/index.js' +import { + PANCAKESWAP_V3_FEE_SPACING_MAP, + PancakeSwapV3FeeAmount, +} from '../../config/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class DackieSwapV3Provider extends UniswapV3BaseProvider { + override FEE = PancakeSwapV3FeeAmount + override TICK_SPACINGS = PANCAKESWAP_V3_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x4f205D69834f9B101b9289F7AFFAc9B77B3fF9b7', + [ChainId.OPTIMISM]: '0xa466ebCfa58848Feb6D8022081f1C21a884889bB', + [ChainId.ARBITRUM]: '0xf79A36F6f440392C63AD61252a64d5d3C43F860D', + [ChainId.BLAST]: '0x6510E68561F04C1d111e616750DaC2a063FF5055', + [ChainId.LINEA]: '0x46B22CD275967DDf055A567E7f36EC89eE3F1139', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.OPTIMISM]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.ARBITRUM]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.BLAST]: + '0x9173e4373ab542649f2f059b10eaab2181ad82cc2e70cf51cf9d9fa8a144a2af', + [ChainId.LINEA]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + } as const + const tickLens = { + [ChainId.BASE]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.OPTIMISM]: '0x0367a647A68f304f2A6e453c25033a4249d7F2C6', + [ChainId.ARBITRUM]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.BLAST]: '0x039e87AB90205F9d87c5b40d4B28e2Be45dA4a20', + [ChainId.LINEA]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.DackieSwapV3 + } + getPoolProviderName(): string { + return 'DackieSwapV3' + } + override async ensureFeeAndTicks(): Promise { + const feeList = [ + this.FEE.LOWEST, + this.FEE.LOW, + this.FEE.MEDIUM, + this.FEE.HIGH, + ] as number[] + const factoryAddress = ( + await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: [ + { + address: this.factory[this.chainId as keyof typeof this.factory]!, + abi: [ + { + inputs: [], + name: 'factoryAddress', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'factoryAddress', + } as const, + ], + }) + )[0] + + const results = (await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: feeList.map( + (fee) => + ({ + chainId: this.chainId, + address: factoryAddress as Address, + abi: uniswapV3FactoryAbi, + functionName: 'feeAmountTickSpacing', + args: [fee], + }) as const, + ), + })) as number[] + + // fetched fee map to ticks should match correctly with hardcoded literals in the dex + return results.every( + (v, i) => + this.TICK_SPACINGS[feeList[i] as PancakeSwapV3FeeAmount] === v || + v === 0, + ) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Dfyn.ts b/packages/sushi/src/router/liquidity-providers/Dfyn.ts index 64cba9ea96..49475dfce1 100644 --- a/packages/sushi/src/router/liquidity-providers/Dfyn.ts +++ b/packages/sushi/src/router/liquidity-providers/Dfyn.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class DfynProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/DovishV3.ts b/packages/sushi/src/router/liquidity-providers/DovishV3.ts index 8484d61aeb..6b4eb9be26 100644 --- a/packages/sushi/src/router/liquidity-providers/DovishV3.ts +++ b/packages/sushi/src/router/liquidity-providers/DovishV3.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV3BaseProvider } from './UniswapV3Base.js' export class DovishV3Provider extends UniswapV3BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/DyorV2.ts b/packages/sushi/src/router/liquidity-providers/DyorV2.ts new file mode 100644 index 0000000000..f8c2b15dc2 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/DyorV2.ts @@ -0,0 +1,27 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class DyorV2Provider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0xA1da7a7eB5A858da410dE8FBC5092c2079B58413', + [ChainId.ZETACHAIN]: '0xA1da7a7eB5A858da410dE8FBC5092c2079B58413', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0xda2f1a903916d7de88d9357d27d763f123502a5d48e3b229d5fa049b3ffdeeb5', + [ChainId.ZETACHAIN]: + '0xda2f1a903916d7de88d9357d27d763f123502a5d48e3b229d5fa049b3ffdeeb5', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.DyorV2 + } + getPoolProviderName(): string { + return 'DyorV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/EddyFinance.ts b/packages/sushi/src/router/liquidity-providers/EddyFinance.ts new file mode 100644 index 0000000000..59a4d4a525 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/EddyFinance.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class EddyFinanceProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ZETACHAIN]: '0x9fd96203f7b22bCF72d9DCb40ff98302376cE09c', + } as const + const initCodeHash = { + [ChainId.ZETACHAIN]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.EddyFinance + } + getPoolProviderName(): string { + return 'EddyFinance' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Elk.ts b/packages/sushi/src/router/liquidity-providers/Elk.ts index 042e033ab8..34a6ebb074 100644 --- a/packages/sushi/src/router/liquidity-providers/Elk.ts +++ b/packages/sushi/src/router/liquidity-providers/Elk.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class ElkProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { @@ -18,14 +18,18 @@ export class ElkProvider extends UniswapV2BaseProvider { [ChainId.ARBITRUM]: '0xA59B2044EAFD15ee4deF138D410d764c9023E1F0', [ChainId.OPTIMISM]: '0xedfad3a0F42A8920B011bb0332aDe632e552d846', [ChainId.KAVA]: '0xC012C4b3d253A8F22d5e4ADA67ea2236FF9778fc', - // [ChainId.BTTC]: '0xc06348AEE3f3E92eE452816E0D3F25C919F6fB04' - // [ChainId.HARMONY]: '0xCdde1AbfF5Ae3Cbfbdb55c1e866Ac56380e18720', - // [ChainId.HECO]: '0x997fCE9164D630CC58eE366d4D275B9D773d54A4', - // [ChainId.OKEX]: '0x1116f8B82028324f2065078b4ff6b47F1Cc22B97', + [ChainId.BTTC]: '0xc06348AEE3f3E92eE452816E0D3F25C919F6fB04', + [ChainId.HARMONY]: '0xCdde1AbfF5Ae3Cbfbdb55c1e866Ac56380e18720', + [ChainId.HECO]: '0x997fCE9164D630CC58eE366d4D275B9D773d54A4', + [ChainId.OKEX]: '0x1116f8B82028324f2065078b4ff6b47F1Cc22B97', + [ChainId.CRONOS]: '0xEEa0e2830D09D8786Cb9F484cA20898b61819ef1', + [ChainId.METIS]: '0xfbb4E52FEcc90924c79F980eb24a9794ae4aFFA4', + [ChainId.BASE]: '0xfbb4E52FEcc90924c79F980eb24a9794ae4aFFA4', + [ChainId.LINEA]: '0xfbb4E52FEcc90924c79F980eb24a9794ae4aFFA4', } as const const initCodeHash = { [ChainId.AVALANCHE]: - '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + '0x33c4831a098654d3d20a78641a198ee6ffc1ceed49f2196b75bb244891c260e3', [ChainId.POLYGON]: '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', [ChainId.FANTOM]: @@ -48,10 +52,22 @@ export class ElkProvider extends UniswapV2BaseProvider { '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', [ChainId.KAVA]: '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', - // [ChainId.BTTC]: '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', - // [ChainId.HARMONY]: '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', - // [ChainId.HECO]: '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', - // [ChainId.OKEX]: '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.BTTC]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.HARMONY]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.HECO]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.OKEX]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.CRONOS]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.METIS]: + '0x074ce6e2b043b11e990c9b71d400ce5b2c39c96ddad65144d0a879d31c2bbaf9', + [ChainId.BASE]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', + [ChainId.LINEA]: + '0x84845e7ccb283dec564acfcd3d9287a491dec6d675705545a2ab8be22ad78f31', } as const super(chainId, web3Client, factory, initCodeHash) } diff --git a/packages/sushi/src/router/liquidity-providers/Enosys.ts b/packages/sushi/src/router/liquidity-providers/Enosys.ts new file mode 100644 index 0000000000..e6019e2071 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Enosys.ts @@ -0,0 +1,77 @@ +import { getCreate2Address } from '@ethersproject/address' +import { Address, PublicClient, encodePacked, keccak256 } from 'viem' +import { ChainId } from '../../chain/index.js' +import { Token } from '../../currency/Token.js' +import { getCurrencyCombinations } from '../get-currency-combinations.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' +import { StaticPool } from './UniswapV2Base.js' + +// Enosys has multiple initCodeHashes, so it is required to override the pool address +// calculations methods to use all the available initCodeHashes to generate multiple +// pool addresses for a pair and then the wrong ones will be filtered out automatically +// on multicall, just the same as any other non existant calculated pool addresses +export class EnosysProvider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FLARE]: '0x28b70f6Ed97429E40FE9a9CD3EB8E86BCBA11dd4', + } as const + const initCodeHash = { + [ChainId.FLARE]: [ + '0x99e82d1f1ab2914f983fb7f2b987a3e30a55ad1fa8c38239d1f7c1a24fb93e3d', + '0xa1ab3f6a293fb82d68afb63ad2a5352fc49d5f3dfa28b151a85c382a91dd574b', + ], + } as const + super(chainId, web3Client, factory, initCodeHash as any) + } + getType(): LiquidityProviders { + return LiquidityProviders.Enosys + } + getPoolProviderName(): string { + return 'Enosys' + } + + // same as _getPoolAddress() in RainUniswapV2BaseProvider, but instead of + // returning only 1 pool address, it returns array of calculated pool + // addressses by using all available initCodeHashes + _getPoolAddresses(t1: Token, t2: Token): Address[] { + return (this.initCodeHash[this.chainId] as any as string[]).map( + (initCodeHash) => { + return getCreate2Address( + this.factory[this.chainId as keyof typeof this.factory]!, + keccak256( + encodePacked( + ['address', 'address'], + [t1.address as Address, t2.address as Address], + ), + ), + initCodeHash, + ) as Address + }, + ) + } + + // same as original getStaticPools() in RainUniswapV2BaseProvider, but + // just overriden to do flatMap() to flatten array of pool addresses + // per token pair, since there will be multiple calculated pool addresses + // per token pair as a result of having multiple initCodeHashes + override getStaticPools(t1: Token, t2: Token): StaticPool[] { + const currencyCombination = getCurrencyCombinations( + this.chainId, + t1, + t2, + ).map(([c0, c1]) => (c0.sortsBefore(c1) ? [c0, c1] : [c1, c0])) + return currencyCombination.flatMap((combination) => { + const poolAddresses = this._getPoolAddresses( + combination[0]!, + combination[1]!, + ) + return poolAddresses.map((poolAddress) => ({ + address: poolAddress, + token0: combination[0]!, + token1: combination[1]!, + fee: this.fee, + })) + }) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Fenix.ts b/packages/sushi/src/router/liquidity-providers/Fenix.ts new file mode 100644 index 0000000000..9b11e7361b --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Fenix.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class FenixProvider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x7a44CD060afC1B6F4c80A2B9b37f4473E74E25Df', + } as const + const poolDeployer = { + [ChainId.BLAST]: '0x5aCCAc55f692Ae2F065CEdDF5924C8f6B53cDaa8', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0xf45e886a0794c1d80aeae5ab5befecd4f0f2b77c0cf627f7c46ec92dc1fa00e4', + } as const + const tickLens = { + [ChainId.BLAST]: '0x098cB852107a0b4508664C09917c00dcb0745aa9', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.Fenix + } + getPoolProviderName(): string { + return 'Fenix' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/GlyphV4.ts b/packages/sushi/src/router/liquidity-providers/GlyphV4.ts new file mode 100644 index 0000000000..eae27f407e --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/GlyphV4.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class GlyphV4Provider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.CORE]: '0x74EfE55beA4988e7D92D03EFd8ddB8BF8b7bD597', + } as const + const poolDeployer = { + [ChainId.CORE]: '0x24196b3f35E1B8313016b9f6641D605dCf48A76a', + } as const + const initCodeHash = { + [ChainId.CORE]: + '0xf96d2474815c32e070cd63233f06af5413efc5dcb430aee4ff18cc29007c562d', + } as const + const tickLens = { + [ChainId.CORE]: '0x433cef5888C701831360686e54668376330cED6D', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.GlyphV4 + } + getPoolProviderName(): string { + return 'GlyphV4' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/GravityFinance.ts b/packages/sushi/src/router/liquidity-providers/GravityFinance.ts new file mode 100644 index 0000000000..731dd9536a --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/GravityFinance.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class GravityFinanceProvider extends UniswapV2BaseProvider { + override fee = 0.0025 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.POLYGON]: '0x3ed75AfF4094d2Aaa38FaFCa64EF1C152ec1Cf20', + } as const + const initCodeHash = { + [ChainId.POLYGON]: + '0x59f0dd0ec2453a509915048cac1608e1a52938dbcdf6b4960b21592e7996743a', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.GravityFinance + } + getPoolProviderName(): string { + return 'GravityFinance' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/HoneySwap.ts b/packages/sushi/src/router/liquidity-providers/HoneySwap.ts index 7db919a9b8..64088ad9c6 100644 --- a/packages/sushi/src/router/liquidity-providers/HoneySwap.ts +++ b/packages/sushi/src/router/liquidity-providers/HoneySwap.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class HoneySwapProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/Horizon.ts b/packages/sushi/src/router/liquidity-providers/Horizon.ts new file mode 100644 index 0000000000..a83563cabb --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Horizon.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class HorizonProvider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.LINEA]: '0xec4f2937e57a6F39087187816eCc83191E6dB1aB', + } as const + const poolDeployer = { + [ChainId.LINEA]: '0xA76990a229961280200165c4e08c96Ea67304C3e', + } as const + const initCodeHash = { + [ChainId.LINEA]: + '0xf96d2474815c32e070cd63233f06af5413efc5dcb430aee4ff18cc29007c562d', + } as const + const tickLens = { + [ChainId.LINEA]: '0x8A3E7cc11E7B9A530b167cE4E0B921bD2610A888', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.Horizon + } + getPoolProviderName(): string { + return 'Horizon' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Hydrex.ts b/packages/sushi/src/router/liquidity-providers/Hydrex.ts new file mode 100644 index 0000000000..41306ede5f --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Hydrex.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1_2BaseProvider } from './AlgebraIntegralV1_2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class HydrexProvider extends AlgebraIntegralV1_2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x36077D39cdC65E1e3FB65810430E5b2c4D5fA29E', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0xa18736c3ee97fe3c96c9428c0cc2a9116facec18e84f95f9da30543f8238a782', + } as const + const poolDeployer = { + [ChainId.BASE]: '0x1595A5D101d69D2a2bAB2976839cC8eeEb13Ab94', + } as const + const tickLens = { + [ChainId.BASE]: '0x0044e9642381607Eee1CCF06bae2378C3cB9B863', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.Hydrex + } + getPoolProviderName(): string { + return 'Hydrex' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/HyperBlast.ts b/packages/sushi/src/router/liquidity-providers/HyperBlast.ts new file mode 100644 index 0000000000..b8776674ab --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/HyperBlast.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class HyperBlastProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0xD97fFc2041a8aB8f6bc4aeE7eE8ECA485381D088', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x2e6ab686c26cf8ecf0a8c01a9fb0ef96dbd4631c04b03005350fa49e8f2f32f8', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.HyperBlast + } + getPoolProviderName(): string { + return 'HyperBlast' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/JetSwap.ts b/packages/sushi/src/router/liquidity-providers/JetSwap.ts index 2ed2fbd0c7..29b3b6129f 100644 --- a/packages/sushi/src/router/liquidity-providers/JetSwap.ts +++ b/packages/sushi/src/router/liquidity-providers/JetSwap.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class JetSwapProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/KimV4.ts b/packages/sushi/src/router/liquidity-providers/KimV4.ts new file mode 100644 index 0000000000..d1d49fc0fd --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/KimV4.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class KimV4Provider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BASE]: '0x2F0d41f94d5D1550b79A83D2fe85C82d68c5a3ca', + } as const + const poolDeployer = { + [ChainId.BASE]: '0x872f5746B3D8CC46A876cBa2269813733A56eB1D', + } as const + const initCodeHash = { + [ChainId.BASE]: + '0xf96d2474815c32e070cd63233f06af5413efc5dcb430aee4ff18cc29007c562d', + } as const + const tickLens = { + [ChainId.BASE]: '0x44a6d9741cDF9C955eE89C14C739FB1aeaD82d6B', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.KimV4 + } + getPoolProviderName(): string { + return 'KimV4' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/KinetixV2.ts b/packages/sushi/src/router/liquidity-providers/KinetixV2.ts new file mode 100644 index 0000000000..38fdd8c75e --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/KinetixV2.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class KinetixV2Provider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.KAVA]: '0xE8E917BC80A26CDacc9aA42C0F4965d2E1Fa52da', + } as const + const initCodeHash = { + [ChainId.KAVA]: + '0x4b61b80b5bcfca0f9202f2aba1955b0cfda155e379cb36e0ab38598337c4c79a', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.KinetixV2 + } + getPoolProviderName(): string { + return 'KinetixV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/KinetixV3.ts b/packages/sushi/src/router/liquidity-providers/KinetixV3.ts new file mode 100644 index 0000000000..fe469e94a9 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/KinetixV3.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class KinetixV3Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.KAVA]: '0x2dBB6254231C5569B6A4313c6C1F5Fe1340b35C2', + } as const + const initCodeHash = { + [ChainId.KAVA]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.KAVA]: '0xdc7A5276aB4C6cd25e16b6118B230109945D2426', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.KinetixV3 + } + getPoolProviderName(): string { + return 'KinetixV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/KodiakV2.ts b/packages/sushi/src/router/liquidity-providers/KodiakV2.ts new file mode 100644 index 0000000000..f554d9cd87 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/KodiakV2.ts @@ -0,0 +1,23 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class KodiakV2Provider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BERA]: '0x5e705e184d233ff2a7cb1553793464a9d0c3028f', + } as const + const initCodeHash = { + [ChainId.BERA]: + '0x190cc7bdd70507a793b76d7bc2bf03e1866989ca7881812e0e1947b23e099534', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.KodiakV2 + } + getPoolProviderName(): string { + return 'KodiakV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/KodiakV3.ts b/packages/sushi/src/router/liquidity-providers/KodiakV3.ts new file mode 100644 index 0000000000..3a9730dc06 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/KodiakV3.ts @@ -0,0 +1,55 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +/** + * The default factory enabled fee amounts, denominated in hundredths of bips. + */ +export enum KodiakV3FeeAmount { + /** 0.01% */ + LOWEST = 100, + /** 0.05% */ + LOW = 500, + /** 0.3% */ + MEDIUM = 3000, + /** 1% */ + HIGH = 10000, + /** 2% */ + HIGHEST = 20000, +} + +/** + * The default factory tick spacings by fee amount. + */ +export const KODIAK_V3_FEE_SPACING_MAP: Record = { + [KodiakV3FeeAmount.LOWEST]: 1, + [KodiakV3FeeAmount.LOW]: 10, + [KodiakV3FeeAmount.MEDIUM]: 60, + [KodiakV3FeeAmount.HIGH]: 200, + [KodiakV3FeeAmount.HIGHEST]: 400, +} + +export class KodiakV3Provider extends UniswapV3BaseProvider { + override FEE = KodiakV3FeeAmount + override TICK_SPACINGS = KODIAK_V3_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BERA]: '0xD84CBf0B02636E7f53dB9E5e45A616E05d710990', + } as const + const initCodeHash = { + [ChainId.BERA]: + '0xd8e2091bc519b509176fc39aeb148cc8444418d3ce260820edc44e806c2c2339', + } as const + const tickLens = { + [ChainId.BERA]: '0xa73C6F1FeC76D5487dC30bdB8f11d1F390394b48', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.KodiakV3 + } + getPoolProviderName(): string { + return 'KodiakV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Kwikswap.ts b/packages/sushi/src/router/liquidity-providers/Kwikswap.ts new file mode 100644 index 0000000000..b447f6f14f --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Kwikswap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class KwikswapProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ETHEREUM]: '0xdD9EFCbDf9f422e2fc159eFe77aDD3730d48056d', + } as const + const initCodeHash = { + [ChainId.ETHEREUM]: + '0xbc919ae6f6f95dca1e223fc957286afa1da81529418e9f187db8a0b2d2e963bc', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.Kwikswap + } + getPoolProviderName(): string { + return 'Kwikswap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/LaserSwap.ts b/packages/sushi/src/router/liquidity-providers/LaserSwap.ts index a4e52dbc4a..03635dd1e6 100644 --- a/packages/sushi/src/router/liquidity-providers/LaserSwap.ts +++ b/packages/sushi/src/router/liquidity-providers/LaserSwap.ts @@ -1,7 +1,7 @@ import { Address, PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class LaserSwapV2Provider extends UniswapV2BaseProvider { override fee = 0.0025 diff --git a/packages/sushi/src/router/liquidity-providers/LiquidityProvider.ts b/packages/sushi/src/router/liquidity-providers/LiquidityProvider.ts index 59e73d54d4..f2a5bc6bfd 100644 --- a/packages/sushi/src/router/liquidity-providers/LiquidityProvider.ts +++ b/packages/sushi/src/router/liquidity-providers/LiquidityProvider.ts @@ -1,6 +1,7 @@ -import { PublicClient } from 'viem' +import { Log, PublicClient } from 'viem' import { ChainId, chainShortName } from '../../chain/index.js' import type { Token } from '../../currency/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' import type { PoolCode } from '../pool-codes/index.js' export enum LiquidityProviders { @@ -9,15 +10,17 @@ export enum LiquidityProviders { UniswapV2 = 'UniswapV2', UniswapV3 = 'UniswapV3', Trident = 'Trident', - QuickSwap = 'QuickSwap', + QuickSwapV2 = 'QuickSwapV2', + QuickSwapV3 = 'QuickSwapV3', ApeSwap = 'ApeSwap', - PancakeSwap = 'PancakeSwap', + PancakeSwapV2 = 'PancakeSwapV2', PancakeSwapV3 = 'PancakeSwapV3', TraderJoe = 'TraderJoe', Dfyn = 'Dfyn', Elk = 'Elk', JetSwap = 'JetSwap', - SpookySwap = 'SpookySwap', + SpookySwapV2 = 'SpookySwapV2', + SpookySwapV3 = 'SpookySwapV3', NetSwap = 'NetSwap', NativeWrap = 'NativeWrap', HoneySwap = 'HoneySwap', @@ -28,6 +31,7 @@ export enum LiquidityProviders { Wagmi = 'Wagmi', LaserSwap = 'LaserSwap', BaseSwap = 'BaseSwap', + BaseSwapV3 = 'BaseSwapV3', AlgebraIntegral = 'AlgebraIntegral', Solarbeam = 'Solarbeam', Swapsicle = 'Swapsicle', @@ -37,11 +41,56 @@ export enum LiquidityProviders { BlastDEX = 'BlastDEX', MonoswapV2 = 'MonoswapV2', MonoswapV3 = 'MonoswapV3', + MSwap = 'MSwap', ThrusterV2 = 'ThrusterV2', ThrusterV3 = 'ThrusterV3', DyorV2 = 'DyorV2', HyperBlast = 'HyperBlast', + KinetixV2 = 'KinetixV2', KinetixV3 = 'KinetixV3', + Camelot = 'Camelot', + Enosys = 'Enosys', + BlazeSwap = 'BlazeSwap', + LynexV1 = 'LynexV1', + LynexV2 = 'LynexV2', + SparkDexV2 = 'SparkDexV2', + SparkDexV3 = 'SparkDexV3', + SparkDexV3_1 = 'SparkDexV3_1', + GravityFinance = 'GravityFinance', + DackieSwapV2 = 'DackieSwapV2', + DackieSwapV3 = 'DackieSwapV3', + Pangolin = 'Pangolin', + AlienBaseV2 = 'AlienBaseV2', + AlienBaseV3 = 'AlienBaseV3', + KimV4 = 'KimV4', + RingExchangeV2 = 'RingExchangeV2', + RingExchangeV3 = 'RingExchangeV3', + BladeSwap = 'BladeSwap', + Fenix = 'Fenix', + BakerySwap = 'BakerySwap', + SquadSwapV2 = 'SquadSwapV2', + BSCSwap = 'BSCSwap', + COREx = 'COREx', + GlyphV4 = 'GlyphV4', + Kwikswap = 'Kwikswap', + ShibaSwap = 'ShibaSwap', + CroDefiSwap = 'CroDefiSwap', + NineInch = 'NineInch', + Wigoswap = 'Wigoswap', + ZebraV2 = 'ZebraV2', + Scribe = 'Scribe', + Horizon = 'Horizon', + EddyFinance = 'EddyFinance', + MMFinance = 'MMFinance', + VVSFlawless = 'VVSFlawless', + AerodromeSlipstream = 'AerodromeSlipstream', + Hydrex = 'Hydrex', + AerodromeSlipstreamV2 = 'AerodromeSlipstreamV2', + VelodromeSlipstream = 'VelodromeSlipstream', + NileV2 = 'NileV2', + NileV3 = 'NileV3', + KodiakV2 = 'KodiakV2', + KodiakV3 = 'KodiakV3', } export abstract class LiquidityProvider { @@ -49,6 +98,7 @@ export abstract class LiquidityProvider { client: PublicClient lastUpdateBlock = 0 isTest = false + initialized = false readonly ON_DEMAND_POOLS_LIFETIME_IN_SECONDS = 60 readonly FETCH_AVAILABLE_POOLS_AFTER_SECONDS = 900 @@ -79,6 +129,7 @@ export abstract class LiquidityProvider { t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise /** @@ -115,4 +166,114 @@ export abstract class LiquidityProvider { [t0.address.toLowerCase(), t1.address.toLowerCase()] .sort((first, second) => (first > second ? -1 : 1)) .join(':') + + /** + * Override this method to perform additional initialization tasks + * such as fetching initial data. + * @param _blockNumber - The block height at which should be initialized + */ + async init(_blockNumber: bigint) { + this.initialized = true + } + + /** + * Processes event logs to update pool data + * @param _log - The event log + */ + processLog(_log: Log): boolean { + return false + } + + /** + * Represents any process that needs to take place after event logs are processed + * @param _untilBlock - The block height that pool data are updated to at processLog + */ + async afterProcessLog(_untilBlock: bigint) {} } + +export const UniV2LiquidityProviders: LiquidityProviders[] = [ + LiquidityProviders.SushiSwapV2, + LiquidityProviders.UniswapV2, + LiquidityProviders.QuickSwapV2, + LiquidityProviders.ApeSwap, + LiquidityProviders.PancakeSwapV2, + LiquidityProviders.TraderJoe, + LiquidityProviders.Dfyn, + LiquidityProviders.Elk, + LiquidityProviders.JetSwap, + LiquidityProviders.SpookySwapV2, + LiquidityProviders.NetSwap, + LiquidityProviders.HoneySwap, + LiquidityProviders.UbeSwap, + LiquidityProviders.Biswap, + LiquidityProviders.LaserSwap, + LiquidityProviders.BaseSwap, + LiquidityProviders.Solarbeam, + LiquidityProviders.Swapsicle, + LiquidityProviders.VVSStandard, + LiquidityProviders.Fraxswap, + LiquidityProviders.SwapBlast, + LiquidityProviders.BlastDEX, + LiquidityProviders.MonoswapV2, + LiquidityProviders.ThrusterV2, + LiquidityProviders.DyorV2, + LiquidityProviders.HyperBlast, + LiquidityProviders.KinetixV2, + LiquidityProviders.Camelot, + LiquidityProviders.Enosys, + LiquidityProviders.BlazeSwap, + LiquidityProviders.LynexV1, + LiquidityProviders.SparkDexV2, + LiquidityProviders.MSwap, + LiquidityProviders.GravityFinance, + LiquidityProviders.DackieSwapV2, + LiquidityProviders.Pangolin, + LiquidityProviders.AlienBaseV2, + LiquidityProviders.RingExchangeV2, + LiquidityProviders.BakerySwap, + LiquidityProviders.SquadSwapV2, + LiquidityProviders.BSCSwap, + LiquidityProviders.Kwikswap, + LiquidityProviders.ShibaSwap, + LiquidityProviders.CroDefiSwap, + LiquidityProviders.NineInch, + LiquidityProviders.Wigoswap, + LiquidityProviders.EddyFinance, + LiquidityProviders.MMFinance, + LiquidityProviders.KodiakV2, + LiquidityProviders.NileV2, +] + +export const UniV3LiquidityProviders: LiquidityProviders[] = [ + LiquidityProviders.SushiSwapV3, + LiquidityProviders.UniswapV3, + LiquidityProviders.QuickSwapV3, + LiquidityProviders.DovishV3, + LiquidityProviders.KinetixV3, + LiquidityProviders.MonoswapV3, + LiquidityProviders.ThrusterV3, + LiquidityProviders.SpookySwapV3, + LiquidityProviders.PancakeSwapV3, + LiquidityProviders.Wagmi, + LiquidityProviders.LynexV2, + LiquidityProviders.SparkDexV3, + LiquidityProviders.SparkDexV3_1, + LiquidityProviders.DackieSwapV3, + LiquidityProviders.AlienBaseV3, + LiquidityProviders.KimV4, + LiquidityProviders.RingExchangeV3, + LiquidityProviders.BladeSwap, + LiquidityProviders.Fenix, + LiquidityProviders.COREx, + LiquidityProviders.GlyphV4, + LiquidityProviders.ZebraV2, + LiquidityProviders.Scribe, + LiquidityProviders.Horizon, + LiquidityProviders.VVSFlawless, + LiquidityProviders.AerodromeSlipstream, + LiquidityProviders.AerodromeSlipstreamV2, + LiquidityProviders.VelodromeSlipstream, + LiquidityProviders.NileV3, + LiquidityProviders.KodiakV3, + LiquidityProviders.Hydrex, +] diff --git a/packages/sushi/src/router/liquidity-providers/LynexV1.ts b/packages/sushi/src/router/liquidity-providers/LynexV1.ts new file mode 100644 index 0000000000..bdd731b335 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/LynexV1.ts @@ -0,0 +1,132 @@ +import { getCreate2Address } from '@ethersproject/address' +import { Address, PublicClient, encodePacked, keccak256, parseAbi } from 'viem' +import { ChainId } from '../../chain/index.js' +import { Token } from '../../currency/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' +import { getCurrencyCombinations } from '../get-currency-combinations.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' +import { StaticPool } from './UniswapV2Base.js' + +const GetFeesAbi = parseAbi([ + 'function getFee(bool _stable) public view returns(uint256)', +]) + +export class LynexV1Provider extends UniswapV2BaseProvider { + STABLE_FEE = 0.0001 + VOLATILE_FEE = 0.0025 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.LINEA]: '0xBc7695Fd00E3b32D08124b7a4287493aEE99f9ee', + } as const + const initCodeHash = { + [ChainId.LINEA]: + '0xf40e8808230a29863f9f7f99beb90d28bca2c60094e78d93cca67f746dbfd142', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.LynexV1 + } + getPoolProviderName(): string { + return 'LynexV1' + } + + // overriden to read the fees from the factory, + // LynexV1 can have different fee for pools that are `stable` or not + // so read the stable and non stable fees before generating pools + // addresses and use those fees for fetched pools and then reading the pools reserves + override async fetchPoolsForToken( + t0: Token, + t1: Token, + excludePools?: Set, + options?: DataFetcherOptions, + ): Promise { + // get current fees + const getFeesData = { + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + blockNumber: options?.blockNumber, + contracts: [true, false].map( + (isStable) => + ({ + address: this.factory[ + this.chainId as keyof typeof this.factory + ] as Address, + chainId: this.chainId, + abi: GetFeesAbi, + functionName: 'getFee', + args: [isStable], + }) as const, + ), + } as const + const fees = await this.client.multicall(getFeesData).catch((e) => { + console.warn( + `${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + // convert to % in number + // returned values are represented in 1/100th of a percent + // so returned value of 25 is 0.25%, ie 0.0025 in numeric value + this.STABLE_FEE = Number(fees?.[0]) * 0.0001 + this.VOLATILE_FEE = Number(fees?.[1]) * 0.0001 + + // proceed the rest as a normal univ2 based dex + await this.getOnDemandPools(t0, t1, excludePools, options) + } + + // LynexV1 has an extra bool variable in its pool address salt + _getPoolAddresses(t1: Token, t2: Token): Address[] { + return [ + getCreate2Address( + this.factory[this.chainId as keyof typeof this.factory]!, + keccak256( + encodePacked( + ['address', 'address', 'bool'], + [t1.address as Address, t2.address as Address, true], + ), + ), + this.initCodeHash[this.chainId as keyof typeof this.initCodeHash]!, + ) as Address, + getCreate2Address( + this.factory[this.chainId as keyof typeof this.factory]!, + keccak256( + encodePacked( + ['address', 'address', 'bool'], + [t1.address as Address, t2.address as Address, false], + ), + ), + this.initCodeHash[this.chainId as keyof typeof this.initCodeHash]!, + ) as Address, + ] + } + + // same as original getStaticPools() in RainUniswapV2BaseProvider, but + // just overriden to do flatMap() to flatten array of pool addresses + // per token pair, since LynexV1 also has bool variable in the pool address salt + // also has 2 fees if the pair is `stable` or not + override getStaticPools(t1: Token, t2: Token): StaticPool[] { + const currencyCombination = getCurrencyCombinations( + this.chainId, + t1, + t2, + ).map(([c0, c1]) => (c0.sortsBefore(c1) ? [c0, c1] : [c1, c0])) + return currencyCombination.flatMap((combination) => { + const poolAddresses = this._getPoolAddresses( + combination[0]!, + combination[1]!, + ) + return poolAddresses.map((poolAddress, i) => ({ + address: poolAddress, + token0: combination[0]!, + token1: combination[1]!, + // set fee for stable and volatile + fee: i === 0 ? this.STABLE_FEE : this.VOLATILE_FEE, + })) + }) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/LynexV2.ts b/packages/sushi/src/router/liquidity-providers/LynexV2.ts new file mode 100644 index 0000000000..30125f3de5 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/LynexV2.ts @@ -0,0 +1,30 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraV1BaseProvider } from '../rain/AlgebraV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class LynexV2Provider extends AlgebraV1BaseProvider { + override DEFAULT_TICK_SPACING = 1 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.LINEA]: '0x622b2c98123D303ae067DB4925CD6282B3A08D0F', + } as const + const poolDeployer = { + [ChainId.LINEA]: '0x9A89490F1056A7BC607EC53F93b921fE666A2C48', + } as const + const initCodeHash = { + [ChainId.LINEA]: + '0xc65e01e65f37c1ec2735556a24a9c10e4c33b2613ad486dd8209d465524bc3f4', + } as const + const tickLens = { + [ChainId.LINEA]: '0x23406481b28cb7C1914C460b8B96cE4b2580BCB9', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.LynexV2 + } + getPoolProviderName(): string { + return 'LynexV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/MMFinance.ts b/packages/sushi/src/router/liquidity-providers/MMFinance.ts new file mode 100644 index 0000000000..171560a03d --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/MMFinance.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class MMFinanceProvider extends UniswapV2BaseProvider { + override fee = 0.0017 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.CRONOS]: '0xd590cC180601AEcD6eeADD9B7f2B7611519544f4', + } as const + const initCodeHash = { + [ChainId.CRONOS]: + '0x7ae6954210575e79ea2402d23bc6a59c4146a6e6296118aa8b99c747afec8acf', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.MMFinance + } + getPoolProviderName(): string { + return 'MMFinance' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/MSwap.ts b/packages/sushi/src/router/liquidity-providers/MSwap.ts new file mode 100644 index 0000000000..be10e9d3b6 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/MSwap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class MSwapProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.MATCHAIN]: '0x338bCC4efd3cA000D123d7352b362Fc6D5B3D829', + } as const + const initCodeHash = { + [ChainId.MATCHAIN]: + '0x32c26bd70ba438539c5a5bf79114c634822021bef9c0ea35fe1d9842a36bd662', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.MSwap + } + getPoolProviderName(): string { + return 'MSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/MonoSwapV2.ts b/packages/sushi/src/router/liquidity-providers/MonoSwapV2.ts new file mode 100644 index 0000000000..49c8ad2d7c --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/MonoSwapV2.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class MonoswapV2Provider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0xE27cb06A15230A7480d02956a3521E78C5bFD2D0', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0xd1a99f7339108abbcc2eaa6478ee4a0394e2a63f04de08793721fb2f3eff5a38', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.MonoswapV2 + } + getPoolProviderName(): string { + return 'MonoswapV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/MonoSwapV3.ts b/packages/sushi/src/router/liquidity-providers/MonoSwapV3.ts new file mode 100644 index 0000000000..3733c49e5f --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/MonoSwapV3.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class MonoswapV3Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x48d0F09710794313f33619c95147F34458BF7C3b', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x7ea070216c7d9135010a36147394687bab92df4695e924000eed7c4b33eb922f', + } as const + const tickLens = { + [ChainId.BLAST]: '0x4a3930837f6E721A6Da5DE4E400A7e90f907fb54', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.MonoswapV3 + } + getPoolProviderName(): string { + return 'MonoswapV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/NetSwap.ts b/packages/sushi/src/router/liquidity-providers/NetSwap.ts index 68132ad64a..076e2e429c 100644 --- a/packages/sushi/src/router/liquidity-providers/NetSwap.ts +++ b/packages/sushi/src/router/liquidity-providers/NetSwap.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class NetSwapProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/NileV2.ts b/packages/sushi/src/router/liquidity-providers/NileV2.ts new file mode 100644 index 0000000000..554e7f207b --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/NileV2.ts @@ -0,0 +1,154 @@ +import { getCreate2Address } from '@ethersproject/address' +import { Address, PublicClient, encodePacked, keccak256 } from 'viem' +import { ChainId } from '../../chain/index.js' +import { Token } from '../../currency/Token.js' +import { getCurrencyCombinations } from '../get-currency-combinations.js' +import { RainDataFetcherOptions } from '../rain/RainDataFetcher.js' +import { RainV2Pool, UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' +import { StaticPool } from './UniswapV2Base.js' + +export class NileV2Provider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.LINEA]: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', + } as const + const initCodeHash = { + [ChainId.LINEA]: + '0xbf2404274de2b11f05e5aebd49e508de933034cb5fa2d0ac3de8cbd4bcef47dc', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.NileV2 + } + getPoolProviderName(): string { + return 'NileV2' + } + + override async getOnDemandPools( + t0: Token, + t1: Token, + excludePools?: Set, + options?: RainDataFetcherOptions, + ): Promise { + let pools = this.getStaticPools(t0, t1) + if (excludePools) pools = pools.filter((p) => !excludePools.has(p.address)) + + if (pools.length === 0) { + return + } + + this.poolsByTrade.set( + this.getTradeId(t0, t1), + pools.map((pool) => pool.address), + ) + + // filter out cached pools + // this ensures backward compatibility for original DataFetcher + if (typeof options?.ignoreCache === 'boolean' && !options.ignoreCache) { + pools = this.filterCachedPools(pools as StaticPool[]) + } + + const fees = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: pools.map( + (poolCode) => + ({ + address: this.factory[this.chainId]!, + chainId: this.chainId, + abi: [ + { + inputs: [ + { internalType: 'address', name: '_pool', type: 'address' }, + ], + name: 'pairFee', + outputs: [ + { internalType: 'uint256', name: 'fee', type: 'uint256' }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'pairFee', + args: [poolCode.address], + }) as const, + ), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + if (!fees) return + + const poolCodesToCreate: RainV2Pool[] = [] + pools.forEach((pool, i) => { + const fee = fees?.[i]?.result + if (typeof fee === 'undefined') return + poolCodesToCreate.push({ + ...pool, + fee, + blockNumber: options?.blockNumber ?? 0n, + } as any as RainV2Pool) + }) + if (!poolCodesToCreate.length) return + + const reserves = await this.getReserves( + poolCodesToCreate.map((v) => v.address), + options, + ) + this.setPool(poolCodesToCreate, reserves) + } + + override getStaticPools(t1: Token, t2: Token): StaticPool[] { + const currencyCombination = getCurrencyCombinations( + this.chainId, + t1, + t2, + ).map(([c0, c1]) => (c0.sortsBefore(c1) ? [c0, c1] : [c1, c0])) + return currencyCombination.flatMap((combination) => [ + { + address: this.computePoolAddress( + combination[0]!, + combination[1]!, + true, + ), + token0: combination[0]!, + token1: combination[1]!, + fee: 0, + }, + { + address: this.computePoolAddress( + combination[0]!, + combination[1]!, + false, + ), + token0: combination[0]!, + token1: combination[1]!, + fee: 0, + }, + ]) + } + + computePoolAddress(t1: Token, t2: Token, stable: boolean): Address { + return getCreate2Address( + this.factory[this.chainId as keyof typeof this.factory]!, + keccak256( + encodePacked( + ['address', 'address', 'bool'], + [t1.address as Address, t2.address as Address, stable], + ), + ), + this.initCodeHash[this.chainId as keyof typeof this.initCodeHash]!, + ) as Address + } +} diff --git a/packages/sushi/src/router/liquidity-providers/NileV3.ts b/packages/sushi/src/router/liquidity-providers/NileV3.ts new file mode 100644 index 0000000000..d7e29eeded --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/NileV3.ts @@ -0,0 +1,64 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +/** + * The default factory enabled fee amounts, denominated in hundredths of bips. + */ +export enum NileV3FeeAmount { + /** 0.01% */ + LOWEST = 100, + /** 0.025% */ + LOWER = 250, + /** 0.05% */ + LOW = 500, + /** 0.3% */ + LOWMID = 3000, + /** 0.5% */ + MEDIUM = 5000, + /** 0.75% */ + HIGHMID = 7500, + /** 1% */ + HIGH = 10000, + /** 2% */ + HIGHEST = 20000, +} + +/** + * The default factory tick spacings by fee amount. + */ +export const NILE_V3_FEE_SPACING_MAP: Record = { + [NileV3FeeAmount.LOWEST]: 1, + [NileV3FeeAmount.LOWER]: 5, + [NileV3FeeAmount.LOW]: 10, + [NileV3FeeAmount.LOWMID]: 60, + [NileV3FeeAmount.MEDIUM]: 25, + [NileV3FeeAmount.HIGHMID]: 50, + [NileV3FeeAmount.HIGH]: 200, + [NileV3FeeAmount.HIGHEST]: 500, +} + +export class NileV3Provider extends UniswapV3BaseProvider { + override FEE = NileV3FeeAmount + override TICK_SPACINGS = NILE_V3_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.LINEA]: '0xAAA32926fcE6bE95ea2c51cB4Fcb60836D320C42', + } as const + const initCodeHash = { + [ChainId.LINEA]: + '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', + } as const + const tickLens = { + [ChainId.LINEA]: '0xAAAD7F8b00B5ce6F8516AC595f0Bb175Ae755c63', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.NileV3 + } + getPoolProviderName(): string { + return 'NileV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/NineInch.ts b/packages/sushi/src/router/liquidity-providers/NineInch.ts new file mode 100644 index 0000000000..ceb1100fb2 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/NineInch.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class NineInchProvider extends UniswapV2BaseProvider { + override fee = 0.0029 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ETHEREUM]: '0xcBAE5C3f8259181EB7E2309BC4c72fDF02dD56D8', + } as const + const initCodeHash = { + [ChainId.ETHEREUM]: + '0xd2cf61d4acad30e9fe5ec59d0f94de554d88701f1bd8fc635546866716718511', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.NineInch + } + getPoolProviderName(): string { + return 'NineInch' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/PancakeSwap.ts b/packages/sushi/src/router/liquidity-providers/PancakeSwap.ts deleted file mode 100644 index e12d78af9d..0000000000 --- a/packages/sushi/src/router/liquidity-providers/PancakeSwap.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { PublicClient } from 'viem' -import { ChainId } from '../../chain/index.js' -import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' - -export class PancakeSwapProvider extends UniswapV2BaseProvider { - override fee = 0.0025 - constructor(chainId: ChainId, web3Client: PublicClient) { - const factory = { - [ChainId.ETHEREUM]: '0x1097053Fd2ea711dad45caCcc45EfF7548fCB362', - [ChainId.BSC]: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73', - } as const - const initCodeHash = { - [ChainId.ETHEREUM]: - '0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d', - [ChainId.BSC]: - '0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5', - } as const - super(chainId, web3Client, factory, initCodeHash) - } - getType(): LiquidityProviders { - return LiquidityProviders.PancakeSwap - } - getPoolProviderName(): string { - return 'PancakeSwap' - } -} diff --git a/packages/sushi/src/router/liquidity-providers/PancakeSwapV2.ts b/packages/sushi/src/router/liquidity-providers/PancakeSwapV2.ts new file mode 100644 index 0000000000..60cc7c74b4 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/PancakeSwapV2.ts @@ -0,0 +1,42 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class PancakeSwapV2Provider extends UniswapV2BaseProvider { + override fee = 0.0025 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ETHEREUM]: '0x1097053Fd2ea711dad45caCcc45EfF7548fCB362', + [ChainId.BSC]: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73', + [ChainId.POLYGON_ZKEVM]: '0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E', + [ChainId.ZKSYNC_ERA]: '0xd03D8D566183F0086d8D09A84E1e30b58Dd5619d', + [ChainId.ARBITRUM]: '0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E', + [ChainId.LINEA]: '0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E', + [ChainId.BASE]: '0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E', + } as const + const initCodeHash = { + [ChainId.ETHEREUM]: + '0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d', + [ChainId.BSC]: + '0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5', + [ChainId.POLYGON_ZKEVM]: + '0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d', + [ChainId.ZKSYNC_ERA]: + '0x1cb011040b91cd937ddff2327f17c9690653b05b6506e830baadf2493468d657', + [ChainId.ARBITRUM]: + '0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d', + [ChainId.LINEA]: + '0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d', + [ChainId.BASE]: + '0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.PancakeSwapV2 + } + getPoolProviderName(): string { + return 'PancakeSwapV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/PancakeSwapV3.ts b/packages/sushi/src/router/liquidity-providers/PancakeSwapV3.ts new file mode 100644 index 0000000000..b36b27cb3d --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/PancakeSwapV3.ts @@ -0,0 +1,126 @@ +import { Address, PublicClient, parseAbiItem } from 'viem' +import { uniswapV3FactoryAbi } from '../../abi/uniswapV3FactoryAbi.js' +import { ChainId } from '../../chain/index.js' +import { + PANCAKESWAP_V3_FEE_SPACING_MAP, + PancakeSwapV3FeeAmount, +} from '../../config/index.js' +import { UniV3EventsAbi, UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export const PancakeV3EventsAbi = [ + ...UniV3EventsAbi.slice(1), // univ3 events except Swap + parseAbiItem( + // PancakeV3 specific Swap event + 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint128 protocolFeesToken0, uint128 protocolFeesToken1)', + ), +] + +export class PancakeSwapV3Provider extends UniswapV3BaseProvider { + override FEE = PancakeSwapV3FeeAmount + override TICK_SPACINGS = PANCAKESWAP_V3_FEE_SPACING_MAP + override eventsAbi = PancakeV3EventsAbi as any + + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ARBITRUM]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + [ChainId.BASE]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + [ChainId.BSC]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + [ChainId.ETHEREUM]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + [ChainId.LINEA]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + [ChainId.POLYGON_ZKEVM]: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + [ChainId.ZKSYNC_ERA]: '0x7f71382044A6a62595D5D357fE75CA8199123aD6', + } as const + const initCodeHash = { + [ChainId.ARBITRUM]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.BASE]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.BSC]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.ETHEREUM]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.LINEA]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.POLYGON_ZKEVM]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + [ChainId.ZKSYNC_ERA]: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + } as const + const tickLens = { + [ChainId.ARBITRUM]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.BASE]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.BSC]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.ETHEREUM]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.LINEA]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.POLYGON_ZKEVM]: '0x9a489505a00cE272eAa5e07Dba6491314CaE3796', + [ChainId.ZKSYNC_ERA]: '0x7b08978FA77910f77d273c353C62b5BFB9E6D17B', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.PancakeSwapV3 + } + getPoolProviderName(): string { + return 'PancakeSwapV3' + } + override async ensureFeeAndTicks(): Promise { + const feeList = [ + this.FEE.LOWEST, + this.FEE.LOW, + this.FEE.MEDIUM, + this.FEE.HIGH, + ] as number[] + const factoryAddress = ( + await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: [ + { + address: this.factory[this.chainId as keyof typeof this.factory]!, + abi: [ + { + inputs: [], + name: 'factoryAddress', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'factoryAddress', + } as const, + ], + }) + )[0] + + const results = (await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: feeList.map( + (fee) => + ({ + chainId: this.chainId, + address: factoryAddress as Address, + abi: uniswapV3FactoryAbi, + functionName: 'feeAmountTickSpacing', + args: [fee], + }) as const, + ), + })) as number[] + + // fetched fee map to ticks should match correctly with hardcoded literals in the dex + return results.every( + (v, i) => + this.TICK_SPACINGS[feeList[i] as PancakeSwapV3FeeAmount] === v || + v === 0, + ) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Pangolin.ts b/packages/sushi/src/router/liquidity-providers/Pangolin.ts new file mode 100644 index 0000000000..6d4c33ea10 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Pangolin.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class PangolinProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.AVALANCHE]: '0xefa94DE7a4656D787667C749f7E1223D71E9FD88', + } as const + const initCodeHash = { + [ChainId.AVALANCHE]: + '0x40231f6b438bce0797c9ada29b718a87ea0a5cea3fe9a771abdd76bd41a3e545', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.Pangolin + } + getPoolProviderName(): string { + return 'Pangolin' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/QuickSwap.ts b/packages/sushi/src/router/liquidity-providers/QuickSwapV2.ts similarity index 75% rename from packages/sushi/src/router/liquidity-providers/QuickSwap.ts rename to packages/sushi/src/router/liquidity-providers/QuickSwapV2.ts index ccadf12a1c..69f863b674 100644 --- a/packages/sushi/src/router/liquidity-providers/QuickSwap.ts +++ b/packages/sushi/src/router/liquidity-providers/QuickSwapV2.ts @@ -1,9 +1,9 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' -export class QuickSwapProvider extends UniswapV2BaseProvider { +export class QuickSwapV2Provider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { const factory = { [ChainId.POLYGON]: '0x5757371414417b8C6CAad45bAeF941aBc7d3Ab32', @@ -15,9 +15,9 @@ export class QuickSwapProvider extends UniswapV2BaseProvider { super(chainId, web3Client, factory, initCodeHash) } getType(): LiquidityProviders { - return LiquidityProviders.QuickSwap + return LiquidityProviders.QuickSwapV2 } getPoolProviderName(): string { - return 'QuickSwap' + return 'QuickSwapV2' } } diff --git a/packages/sushi/src/router/liquidity-providers/QuickswapV3.ts b/packages/sushi/src/router/liquidity-providers/QuickswapV3.ts new file mode 100644 index 0000000000..37515c5b49 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/QuickswapV3.ts @@ -0,0 +1,34 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraV1BaseProvider } from '../rain/AlgebraV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class QuickSwapV3Provider extends AlgebraV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.POLYGON]: '0x411b0fAcC3489691f28ad58c47006AF5E3Ab3A28', + [ChainId.POLYGON_ZKEVM]: '0x4B9f4d2435Ef65559567e5DbFC1BbB37abC43B57', + } as const + const poolDeployer = { + [ChainId.POLYGON]: '0x2D98E2FA9da15aa6dC9581AB097Ced7af697CB92', + [ChainId.POLYGON_ZKEVM]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', + } as const + const initCodeHash = { + [ChainId.POLYGON]: + '0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4', + [ChainId.POLYGON_ZKEVM]: + '0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4', + } as const + const tickLens = { + [ChainId.POLYGON]: '0x5e9793f398c68A55F9C85A965CdB0d0c9a094d70', + [ChainId.POLYGON_ZKEVM]: '0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.QuickSwapV3 + } + getPoolProviderName(): string { + return 'QuickswapV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/RingExchangeV2.ts b/packages/sushi/src/router/liquidity-providers/RingExchangeV2.ts new file mode 100644 index 0000000000..dd2ac811e2 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/RingExchangeV2.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class RingExchangeV2Provider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x24F5Ac9A706De0cF795A8193F6AB3966B14ECfE6', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x501ce753061ab6e75837b15f074633bb775f5972f8dc1112fcc829c2e88dc689', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.RingExchangeV2 + } + getPoolProviderName(): string { + return 'RingExchangeV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/RingExchangeV3.ts b/packages/sushi/src/router/liquidity-providers/RingExchangeV3.ts new file mode 100644 index 0000000000..94bd1d540e --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/RingExchangeV3.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class RingExchangeV3Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x890509Fab3dD11D4Ff57d8471b5eAC74687E4C75', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.BLAST]: '0x160958266EA8fe90D3be91474BaF633eebaD17a0', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.RingExchangeV3 + } + getPoolProviderName(): string { + return 'RingExchangeV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Scribe.ts b/packages/sushi/src/router/liquidity-providers/Scribe.ts new file mode 100644 index 0000000000..d62d4d8d48 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Scribe.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class ScribeProvider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.SCROLL]: '0xDc62aCDF75cc7EA4D93C69B2866d9642E79d5e2e', + } as const + const poolDeployer = { + [ChainId.SCROLL]: '0xbAE27269D777D6fc0AefFa9DfAbA8960291E51eB', + } as const + const initCodeHash = { + [ChainId.SCROLL]: + '0x4b9e4a8044ce5695e06fce9421a63b6f5c3db8a561eebb30ea4c775469e36eaf', + } as const + const tickLens = { + [ChainId.SCROLL]: '0xECd0DD811B55f5b7e20e7999f1e986Ba7d7df901', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.Scribe + } + getPoolProviderName(): string { + return 'Scribe' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/ShibaSwap.ts b/packages/sushi/src/router/liquidity-providers/ShibaSwap.ts new file mode 100644 index 0000000000..8f6368eaac --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/ShibaSwap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class ShibaSwapProvider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ETHEREUM]: '0x115934131916C8b277DD010Ee02de363c09d037c', + } as const + const initCodeHash = { + [ChainId.ETHEREUM]: + '0x65d1a3b1e46c6e4f1be1ad5f99ef14dc488ae0549dc97db9b30afe2241ce1c7a', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.ShibaSwap + } + getPoolProviderName(): string { + return 'ShibaSwap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Solarbeam.ts b/packages/sushi/src/router/liquidity-providers/Solarbeam.ts new file mode 100644 index 0000000000..638d3361f9 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Solarbeam.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SolarbeamProvider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.MOONRIVER]: '0x049581aEB6Fe262727f290165C29BDAB065a1B68', + [ChainId.MOONBEAM]: '0x19B85ae92947E0725d5265fFB3389e7E4F191FDa', + } as const + const initCodeHash = { + [ChainId.MOONRIVER]: + '0x9a100ded5f254443fbd264cb7e87831e398a8b642e061670a9bc35ba27293dbf', + [ChainId.MOONBEAM]: + '0xe21386787732ef8059a646602f85a5ebb23848cddd90ef5a8d111ec84a4cb71f', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.Solarbeam + } + getPoolProviderName(): string { + return 'Solarbeam' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/SparkDexV2.ts b/packages/sushi/src/router/liquidity-providers/SparkDexV2.ts new file mode 100644 index 0000000000..749f973b92 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/SparkDexV2.ts @@ -0,0 +1,23 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SparkDexV2Provider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FLARE]: '0x16b619B04c961E8f4F06C10B42FDAbb328980A89', + } as const + const initCodeHash = { + [ChainId.FLARE]: + '0x60cc0e9ad39c5fa4ee52571f511012ed76fbaa9bbaffd2f3fafffcb3c47cff6e', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.SparkDexV2 + } + getPoolProviderName(): string { + return 'SparkDexV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/SparkDexV3.ts b/packages/sushi/src/router/liquidity-providers/SparkDexV3.ts new file mode 100644 index 0000000000..ecc9fd5c56 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/SparkDexV3.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SparkDexV3Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FLARE]: '0xb3fB4f96175f6f9D716c17744e5A6d4BA9da8176', + } as const + const initCodeHash = { + [ChainId.FLARE]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.FLARE]: '0x80BE099457DF46e7EA0C38A7B4bB8DAF74079957', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.SparkDexV3 + } + getPoolProviderName(): string { + return 'SparkDexV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/SparkDexV3_1.ts b/packages/sushi/src/router/liquidity-providers/SparkDexV3_1.ts new file mode 100644 index 0000000000..d1a3b2c59b --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/SparkDexV3_1.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SparkDexV3_1Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FLARE]: '0x8A2578d23d4C532cC9A98FaD91C0523f5efDE652', + } as const + const initCodeHash = { + [ChainId.FLARE]: + '0x209015062f691a965df159762a8d966b688e328361c53ec32da2ad31287e3b72', + } as const + const tickLens = { + [ChainId.FLARE]: '0xdB5F2Ca65aAeB277E36be69553E0e7aA3585204d', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.SparkDexV3_1 + } + getPoolProviderName(): string { + return 'SparkDexV3_1' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/SpookySwap.ts b/packages/sushi/src/router/liquidity-providers/SpookySwapV2.ts similarity index 74% rename from packages/sushi/src/router/liquidity-providers/SpookySwap.ts rename to packages/sushi/src/router/liquidity-providers/SpookySwapV2.ts index 66fbcbb760..f06c2e65eb 100644 --- a/packages/sushi/src/router/liquidity-providers/SpookySwap.ts +++ b/packages/sushi/src/router/liquidity-providers/SpookySwapV2.ts @@ -1,9 +1,9 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' -export class SpookySwapProvider extends UniswapV2BaseProvider { +export class SpookySwapV2Provider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { const factory = { [ChainId.FANTOM]: '0x152eE697f2E276fA89E96742e9bB9aB1F2E61bE3', @@ -15,9 +15,9 @@ export class SpookySwapProvider extends UniswapV2BaseProvider { super(chainId, web3Client, factory, initCodeHash) } getType(): LiquidityProviders { - return LiquidityProviders.SpookySwap + return LiquidityProviders.SpookySwapV2 } getPoolProviderName(): string { - return 'SpookySwap' + return 'SpookySwapV2' } } diff --git a/packages/sushi/src/router/liquidity-providers/SpookySwapV3.ts b/packages/sushi/src/router/liquidity-providers/SpookySwapV3.ts new file mode 100644 index 0000000000..c95b6ae879 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/SpookySwapV3.ts @@ -0,0 +1,26 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SpookySwapV3Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FANTOM]: '0x7928a2c48754501f3a8064765ECaE541daE5c3E6', + } as const + const initCodeHash = { + [ChainId.FANTOM]: + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54', + } as const + const tickLens = { + [ChainId.FANTOM]: '0xbaA8353CC9d02733eF12f9556ed999521f6E554c', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.SpookySwapV3 + } + getPoolProviderName(): string { + return 'SpookySwapV3' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/SquadSwapV2.ts b/packages/sushi/src/router/liquidity-providers/SquadSwapV2.ts new file mode 100644 index 0000000000..4453f1099f --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/SquadSwapV2.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SquadSwapV2Provider extends UniswapV2BaseProvider { + override fee = 0.002 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BSC]: '0x1D9F43a6195054313ac1aE423B1f810f593b6ac1', + } as const + const initCodeHash = { + [ChainId.BSC]: + '0xd424455c1204e4f46a4a380651928652376a351698d3d97e2da05d3041c15fbe', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.SquadSwapV2 + } + getPoolProviderName(): string { + return 'SquadSwapV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/SushiSwapV2.ts b/packages/sushi/src/router/liquidity-providers/SushiSwapV2.ts index deb99dc463..24992fb131 100644 --- a/packages/sushi/src/router/liquidity-providers/SushiSwapV2.ts +++ b/packages/sushi/src/router/liquidity-providers/SushiSwapV2.ts @@ -4,8 +4,8 @@ import { SUSHISWAP_V2_FACTORY_ADDRESS, SUSHISWAP_V2_INIT_CODE_HASH, } from '../../config/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class SushiSwapV2Provider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/SushiSwapV3.ts b/packages/sushi/src/router/liquidity-providers/SushiSwapV3.ts index 7139b54a70..878989a91e 100644 --- a/packages/sushi/src/router/liquidity-providers/SushiSwapV3.ts +++ b/packages/sushi/src/router/liquidity-providers/SushiSwapV3.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV3BaseProvider } from './UniswapV3Base.js' export class SushiSwapV3Provider extends UniswapV3BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/SwapBlast.ts b/packages/sushi/src/router/liquidity-providers/SwapBlast.ts new file mode 100644 index 0000000000..0ec4856bfe --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/SwapBlast.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SwapBlastProvider extends UniswapV2BaseProvider { + override fee = 0.001 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x04C9f118d21e8B767D2e50C946f0cC9F6C367300', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x89f2ba5c4e1e84307b0efac8ff56efab2786d9becd741ff83b1b6397de76dafc', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.SwapBlast + } + getPoolProviderName(): string { + return 'SwapBlast' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Swapsicle.ts b/packages/sushi/src/router/liquidity-providers/Swapsicle.ts new file mode 100644 index 0000000000..6a2c6c2401 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Swapsicle.ts @@ -0,0 +1,29 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { AlgebraIntegralV1BaseProvider } from './AlgebraIntegralV1Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class SwapsicleProvider extends AlgebraIntegralV1BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.TELOS]: '0xA09BAbf9A48003ae9b9333966a8Bda94d820D0d9', + } as const + const poolDeployer = { + [ChainId.TELOS]: '0x061e47Ab9f31D293172efb88674782f80eCa88de', + } as const + const initCodeHash = { + [ChainId.TELOS]: + '0x177d5fbf994f4d130c008797563306f1a168dc689f81b2fa23b4396931014d91', + } as const + const tickLens = { + [ChainId.TELOS]: '0x9dE2dEA5c68898eb4cb2DeaFf357DFB26255a4aa', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens, poolDeployer) + } + getType(): LiquidityProviders { + return LiquidityProviders.Swapsicle + } + getPoolProviderName(): string { + return 'Swapsicle' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/ThrusterV2.ts b/packages/sushi/src/router/liquidity-providers/ThrusterV2.ts new file mode 100644 index 0000000000..7b9e84288c --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/ThrusterV2.ts @@ -0,0 +1,44 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class ThrusterV2_3Provider extends UniswapV2BaseProvider { + override fee = 0.003 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0xb4A7D971D0ADea1c73198C97d7ab3f9CE4aaFA13', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x6f0346418750a1a53597a51ceff4f294b5f0e87f09715525b519d38ad3fab2cb', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.ThrusterV2 + } + getPoolProviderName(): string { + return 'ThrusterV2' + } +} + +export class ThrusterV2_1Provider extends UniswapV2BaseProvider { + override fee = 0.01 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0x37836821a2c03c171fB1a595767f4a16e2b93Fc4', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0x32a9ff5a51b653cbafe88e38c4da86b859135750d3ca435f0ce732c8e3bb8335', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.ThrusterV2 + } + getPoolProviderName(): string { + return 'ThrusterV2' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/ThrusterV3.ts b/packages/sushi/src/router/liquidity-providers/ThrusterV3.ts new file mode 100644 index 0000000000..53a2d1e018 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/ThrusterV3.ts @@ -0,0 +1,87 @@ +import { Address, PublicClient } from 'viem' +import { uniswapV3FactoryAbi } from '../../abi/uniswapV3FactoryAbi.js' +import { ChainId } from '../../chain/index.js' +import { SushiSwapV3FeeAmount } from '../../config/sushiswap-v3.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class ThrusterV3Provider extends UniswapV3BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.BLAST]: '0xa08ae3d3f4dA51C22d3c041E468bdF4C61405AaB', + } as const + const initCodeHash = { + [ChainId.BLAST]: + '0xd0c3a51b16dbc778f000c620eaabeecd33b33a80bd145e1f7cbc0d4de335193d', + } as const + const tickLens = { + [ChainId.BLAST]: '0x796B39328b92472b2Bd950AEB20D950611e02EF6', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.ThrusterV3 + } + getPoolProviderName(): string { + return 'ThrusterV3' + } + + override async ensureFeeAndTicks(): Promise { + const feeList = [ + this.FEE.LOWEST, + this.FEE.LOW, + this.FEE.MEDIUM, + this.FEE.HIGH, + ] as number[] + const factoryAddress = ( + await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: [ + { + address: this.factory[this.chainId as keyof typeof this.factory]!, + abi: [ + { + inputs: [], + name: 'factory', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'factory', + } as const, + ], + }) + )[0] + + const results = (await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: feeList.map( + (fee) => + ({ + chainId: this.chainId, + address: factoryAddress as Address, + abi: uniswapV3FactoryAbi, + functionName: 'feeAmountTickSpacing', + args: [fee], + }) as const, + ), + })) as number[] + + // fetched fee map to ticks should match correctly with hardcoded literals in the dex + return results.every( + (v, i) => + this.TICK_SPACINGS[feeList[i] as SushiSwapV3FeeAmount] === v || v === 0, + ) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/TraderJoe.ts b/packages/sushi/src/router/liquidity-providers/TraderJoe.ts index bac9b35ce8..81938a3622 100644 --- a/packages/sushi/src/router/liquidity-providers/TraderJoe.ts +++ b/packages/sushi/src/router/liquidity-providers/TraderJoe.ts @@ -1,16 +1,22 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class TraderJoeProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { const factory = { [ChainId.AVALANCHE]: '0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10', + [ChainId.ARBITRUM]: '0xaE4EC9901c3076D0DdBe76A520F9E90a6227aCB7', + [ChainId.BSC]: '0x4f8bdc85E3eec5b9dE67097c3f59B6Db025d9986', } as const const initCodeHash = { [ChainId.AVALANCHE]: '0x0bbca9af0511ad1a1da383135cf3a8d2ac620e549ef9f6ae3a4c33c2fed0af91', + [ChainId.ARBITRUM]: + '0x5c9d12e487d245c53fb0b8dd1ba2ccc48810e6b9671311502b8632e88b0d605b', + [ChainId.BSC]: + '0x75e986a1d8c57bd5530b4b59ab7dd63c4d4ad267f147e17774264956de33c282', } as const super(chainId, web3Client, factory, initCodeHash) } diff --git a/packages/sushi/src/router/liquidity-providers/Trident.ts b/packages/sushi/src/router/liquidity-providers/Trident.ts index bfaf64e0c2..45e87dfd71 100644 --- a/packages/sushi/src/router/liquidity-providers/Trident.ts +++ b/packages/sushi/src/router/liquidity-providers/Trident.ts @@ -23,6 +23,7 @@ import { convertTokenToBento, toShareBI, } from '../../tines/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' import { PoolResponse2, filterOnDemandPools, @@ -577,6 +578,7 @@ export class TridentProvider extends LiquidityProvider { t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise { const topPoolAddresses = [ ...Array.from(this.topClassicPools.keys()), @@ -609,6 +611,7 @@ export class TridentProvider extends LiquidityProvider { this.chainId, t0, t1, + options, ) if (excludePools) onDemandClassicPools = (onDemandClassicPools as PoolResponse2[]).filter( @@ -728,6 +731,7 @@ export class TridentProvider extends LiquidityProvider { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: classicPoolCodesToCreate.map( (pc) => ({ @@ -752,6 +756,7 @@ export class TridentProvider extends LiquidityProvider { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: stablePoolCodesToCreate.map( (pc) => ({ @@ -776,6 +781,7 @@ export class TridentProvider extends LiquidityProvider { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: bridgesToCreate.map( (b) => ({ @@ -803,6 +809,7 @@ export class TridentProvider extends LiquidityProvider { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: bridgesToCreate.map( (b) => ({ @@ -1094,23 +1101,23 @@ export class TridentProvider extends LiquidityProvider { this.topStablePools = new Map() this.bridges = new Map() - this.unwatchBlockNumber = this.client.watchBlockNumber({ - onBlockNumber: (blockNumber) => { - this.lastUpdateBlock = Number(blockNumber) - if (!this.isInitialized) { - this.initialize() - } else { - this.updatePools() - } - }, - onError: (error) => { - console.error( - `${this.getLogPrefix()} - Error watching block number: ${ - error.message - }`, - ) - }, - }) + // this.unwatchBlockNumber = this.client.watchBlockNumber({ + // onBlockNumber: (blockNumber) => { + // this.lastUpdateBlock = Number(blockNumber) + // if (!this.isInitialized) { + // this.initialize() + // } else { + // this.updatePools() + // } + // }, + // onError: (error) => { + // console.error( + // `${this.getLogPrefix()} - Error watching block number: ${ + // error.message + // }`, + // ) + // }, + // }) } private removeStalePools() { @@ -1139,8 +1146,9 @@ export class TridentProvider extends LiquidityProvider { t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise { - await this.getOnDemandPools(t0, t1, excludePools) + await this.getOnDemandPools(t0, t1, excludePools, options) } getCurrentPoolList(t0: Token, t1: Token): PoolCode[] { diff --git a/packages/sushi/src/router/liquidity-providers/UbeSwap.ts b/packages/sushi/src/router/liquidity-providers/UbeSwap.ts index 288b1882a1..4e7a0d0030 100644 --- a/packages/sushi/src/router/liquidity-providers/UbeSwap.ts +++ b/packages/sushi/src/router/liquidity-providers/UbeSwap.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class UbeSwapProvider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/UniswapV2.ts b/packages/sushi/src/router/liquidity-providers/UniswapV2.ts index 21a10b0871..1a08470af8 100644 --- a/packages/sushi/src/router/liquidity-providers/UniswapV2.ts +++ b/packages/sushi/src/router/liquidity-providers/UniswapV2.ts @@ -1,16 +1,37 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV2BaseProvider } from './UniswapV2Base.js' export class UniswapV2Provider extends UniswapV2BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { const factory = { [ChainId.ETHEREUM]: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', + [ChainId.ARBITRUM]: '0xf1D7CC64Fb4452F05c498126312eBE29f30Fbcf9', + [ChainId.AVALANCHE]: '0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C', + [ChainId.BSC]: '0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6', + [ChainId.OPTIMISM]: '0x0c3c1c532F1e39EdF36BE9Fe0bE1410313E074Bf', + [ChainId.POLYGON]: '0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C', + [ChainId.BLAST]: '0x5C346464d33F90bABaf70dB6388507CC889C1070', + [ChainId.BASE]: '0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6', } as const const initCodeHash = { [ChainId.ETHEREUM]: '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.ARBITRUM]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.AVALANCHE]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.BSC]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.OPTIMISM]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.POLYGON]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.BLAST]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + [ChainId.BASE]: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', } as const super(chainId, web3Client, factory, initCodeHash) } diff --git a/packages/sushi/src/router/liquidity-providers/UniswapV2Base.ts b/packages/sushi/src/router/liquidity-providers/UniswapV2Base.ts index d9d31ec9b7..d8c700b91e 100644 --- a/packages/sushi/src/router/liquidity-providers/UniswapV2Base.ts +++ b/packages/sushi/src/router/liquidity-providers/UniswapV2Base.ts @@ -1,7 +1,7 @@ import { getCreate2Address } from '@ethersproject/address' import { add, getUnixTime } from 'date-fns' import { Address, Hex, PublicClient, encodePacked, keccak256 } from 'viem' -import { getReservesAbi } from '../../abi/index.js' +import { getReservesAbi as abi } from '../../abi/index.js' import { ChainId } from '../../chain/index.js' import { ADDITIONAL_BASES, @@ -9,6 +9,7 @@ import { } from '../../config/index.js' import { Token } from '../../currency/index.js' import { ConstantProductRPool, RToken } from '../../tines/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' import { getCurrencyCombinations } from '../get-currency-combinations.js' import { PoolResponse2, @@ -24,7 +25,7 @@ interface PoolInfo { validUntilTimestamp: number } -interface StaticPool { +export interface StaticPool { address: Address token0: Token token1: Token @@ -57,6 +58,7 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { refreshAvailablePoolsTimestamp = getUnixTime( add(Date.now(), { seconds: this.FETCH_AVAILABLE_POOLS_AFTER_SECONDS }), ) + getReservesAbi: any = abi constructor( chainId: ChainId, @@ -105,7 +107,7 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { ({ address: pool.address as Address, chainId: this.chainId, - abi: getReservesAbi, + abi, functionName: 'getReserves', }) as const, ), @@ -156,10 +158,40 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { return new Map() } + async getReserves( + poolCodesToCreate: Address[], + options?: DataFetcherOptions, + ): Promise { + const multicallData = { + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: poolCodesToCreate.map( + (address) => + ({ + address, + chainId: this.chainId, + abi: this.getReservesAbi, + functionName: 'getReserves', + }) as const, + ), + } + return await this.client.multicall(multicallData).catch((e) => { + console.warn( + `${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + } + async getOnDemandPools( t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise { const topPoolAddresses = Array.from(this.topPools.keys()) let pools = @@ -203,7 +235,7 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { pool.address, token0, token1, - this.fee, + 'fee' in pool ? pool.fee : this.fee, 0n, 0n, ) @@ -219,30 +251,21 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { } }) - const reserves = await this.client - .multicall({ - multicallAddress: this.client.chain?.contracts?.multicall3 - ?.address as Address, - allowFailure: true, - contracts: poolCodesToCreate.map( - (poolCode) => - ({ - address: poolCode.pool.address as Address, - chainId: this.chainId, - abi: getReservesAbi, - functionName: 'getReserves', - }) as const, - ), - }) - .catch((e) => { - console.warn( - `${this.getLogPrefix()} - UPDATE: on-demand pools multicall failed, message: ${ - e.message - }`, - ) - return undefined - }) + const reserves = await this.getReserves( + poolCodesToCreate.map((v) => v.pool.address), + options, + ) + this.handleCreatePoolCode(poolCodesToCreate, reserves, validUntilTimestamp) + // console.debug( + // `${this.getLogPrefix()} - ON DEMAND: Created and fetched reserves for ${created} pools, extended 'lifetime' for ${updated} pools` + // ) + } + handleCreatePoolCode( + poolCodesToCreate: PoolCode[], + reserves: any[], + validUntilTimestamp: number, + ) { poolCodesToCreate.forEach((poolCode, i) => { const pool = poolCode.pool const res0 = reserves?.[i]?.result?.[0] @@ -260,10 +283,6 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { // console.error(`${this.getLogPrefix()} - ERROR FETCHING RESERVES, initialize on demand pool: ${pool.address}`) } }) - - // console.debug( - // `${this.getLogPrefix()} - ON DEMAND: Created and fetched reserves for ${created} pools, extended 'lifetime' for ${updated} pools` - // ) } async updatePools() { @@ -293,7 +312,7 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { ({ address: poolCode.pool.address as Address, chainId: this.chainId, - abi: getReservesAbi, + abi, functionName: 'getReserves', }) as const, ), @@ -316,7 +335,7 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { ({ address: poolCode.pool.address as Address, chainId: this.chainId, - abi: getReservesAbi, + abi, functionName: 'getReserves', }) as const, ), @@ -499,23 +518,23 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { startFetchPoolsData() { this.stopFetchPoolsData() this.topPools = new Map() - this.unwatchBlockNumber = this.client.watchBlockNumber({ - onBlockNumber: (blockNumber) => { - this.lastUpdateBlock = Number(blockNumber) - if (!this.isInitialized) { - this.initialize() - } else { - this.updatePools() - } - }, - onError: (error) => { - console.error( - `${this.getLogPrefix()} - Error watching block number: ${ - error.message - }`, - ) - }, - }) + // this.unwatchBlockNumber = this.client.watchBlockNumber({ + // onBlockNumber: (blockNumber) => { + // this.lastUpdateBlock = Number(blockNumber) + // if (!this.isInitialized) { + // this.initialize() + // } else { + // this.updatePools() + // } + // }, + // onError: (error) => { + // console.error( + // `${this.getLogPrefix()} - Error watching block number: ${ + // error.message + // }`, + // ) + // }, + // }) } private removeStalePools() { @@ -536,8 +555,9 @@ export abstract class UniswapV2BaseProvider extends LiquidityProvider { t0: Token, t1: Token, excludePools?: Set, + options?: DataFetcherOptions, ): Promise { - await this.getOnDemandPools(t0, t1, excludePools) + await this.getOnDemandPools(t0, t1, excludePools, options) } /** diff --git a/packages/sushi/src/router/liquidity-providers/UniswapV3.ts b/packages/sushi/src/router/liquidity-providers/UniswapV3.ts index 1fb4f36665..819cf10478 100644 --- a/packages/sushi/src/router/liquidity-providers/UniswapV3.ts +++ b/packages/sushi/src/router/liquidity-providers/UniswapV3.ts @@ -1,7 +1,7 @@ import { PublicClient } from 'viem' import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' import { LiquidityProviders } from './LiquidityProvider.js' -import { UniswapV3BaseProvider } from './UniswapV3Base.js' export class UniswapV3Provider extends UniswapV3BaseProvider { constructor(chainId: ChainId, web3Client: PublicClient) { diff --git a/packages/sushi/src/router/liquidity-providers/UniswapV3Base.ts b/packages/sushi/src/router/liquidity-providers/UniswapV3Base.ts index c3ab1201b7..92bbbc257e 100644 --- a/packages/sushi/src/router/liquidity-providers/UniswapV3Base.ts +++ b/packages/sushi/src/router/liquidity-providers/UniswapV3Base.ts @@ -1,47 +1,56 @@ import { Address, PublicClient } from 'viem' -import { erc20Abi, tickLensAbi } from '../../abi/index.js' +import { erc20Abi, tickLensAbi, uniswapV3FactoryAbi } from '../../abi/index.js' import { ChainId } from '../../chain/index.js' import { SushiSwapV3FeeAmount, TICK_SPACINGS } from '../../config/index.js' import { Currency, Token, Type } from '../../currency/index.js' import { computeSushiSwapV3PoolAddress } from '../../pool/index.js' import { RToken, UniV3Pool } from '../../tines/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' import { getCurrencyCombinations } from '../get-currency-combinations.js' import { type PoolCode, UniV3PoolCode } from '../pool-codes/index.js' import { LiquidityProvider } from './LiquidityProvider.js' -interface StaticPool { +export interface UniV3FeeType { + readonly LOWEST: number + readonly LOW: number + readonly MEDIUM: number + readonly HIGH: number +} + +export type UniV3TickSpacingType = { + readonly [key: UniV3FeeType[keyof UniV3FeeType]]: number +} + +export interface StaticPoolUniV3 { address: Address token0: Token token1: Token - fee: SushiSwapV3FeeAmount + fee: UniV3FeeType[keyof UniV3FeeType] } -interface V3Pool { +export interface V3Pool { address: Address token0: Token token1: Token - fee: SushiSwapV3FeeAmount + fee: UniV3FeeType[keyof UniV3FeeType] sqrtPriceX96: bigint activeTick: number + tick: number } export const NUMBER_OF_SURROUNDING_TICKS = 1000 // 10% price impact -const getActiveTick = (tickCurrent: number, feeAmount: SushiSwapV3FeeAmount) => - typeof tickCurrent === 'number' && feeAmount - ? Math.floor(tickCurrent / TICK_SPACINGS[feeAmount]) * - TICK_SPACINGS[feeAmount] - : undefined - -const bitmapIndex = (tick: number, tickSpacing: number) => { +export const bitmapIndex = (tick: number, tickSpacing: number) => { return Math.floor(tick / tickSpacing / 256) } -type PoolFilter = { has: (arg: string) => boolean } +export type PoolFilter = { has: (arg: string) => boolean } export abstract class UniswapV3BaseProvider extends LiquidityProvider { + TICK_SPACINGS: UniV3TickSpacingType = TICK_SPACINGS + FEE: UniV3FeeType = SushiSwapV3FeeAmount poolsByTrade: Map = new Map() - pools: Map = new Map() + poolsCodes: Map = new Map() blockListener?: (() => void) | undefined unwatchBlockNumber?: () => void @@ -74,74 +83,84 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { } } - async fetchPoolsForToken( + getActiveTick = ( + tickCurrent: number, + feeAmount: UniV3FeeType[keyof UniV3FeeType], + ) => + typeof tickCurrent === 'number' && feeAmount + ? Math.floor(tickCurrent / this.TICK_SPACINGS[feeAmount]!) * + this.TICK_SPACINGS[feeAmount]! + : undefined + + async fetchPoolData( t0: Token, t1: Token, excludePools?: Set | PoolFilter, - ): Promise { + options?: DataFetcherOptions, + ): Promise { let staticPools = this.getStaticPools(t0, t1) if (excludePools) staticPools = staticPools.filter((p) => !excludePools.has(p.address)) - const slot0 = await this.client - .multicall({ - multicallAddress: this.client.chain?.contracts?.multicall3 - ?.address as Address, - allowFailure: true, - contracts: staticPools.map( - (pool) => - ({ - address: pool.address as Address, - chainId: this.chainId, - abi: [ - { - inputs: [], - name: 'slot0', - outputs: [ - { - internalType: 'uint160', - name: 'sqrtPriceX96', - type: 'uint160', - }, - { internalType: 'int24', name: 'tick', type: 'int24' }, - { - internalType: 'uint16', - name: 'observationIndex', - type: 'uint16', - }, - { - internalType: 'uint16', - name: 'observationCardinality', - type: 'uint16', - }, - { - internalType: 'uint16', - name: 'observationCardinalityNext', - type: 'uint16', - }, - { - internalType: 'uint8', - name: 'feeProtocol', - type: 'uint8', - }, - { internalType: 'bool', name: 'unlocked', type: 'bool' }, - ], - stateMutability: 'view', - type: 'function', - }, - ], - functionName: 'slot0', - }) as const, - ), - }) - .catch((e) => { - console.warn( - `${this.getLogPrefix()} - INIT: multicall failed, message: ${ - e.message - }`, - ) - return undefined - }) + const slot0Data = { + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: staticPools.map( + (pool) => + ({ + address: pool.address as Address, + chainId: this.chainId, + abi: [ + { + inputs: [], + name: 'slot0', + outputs: [ + { + internalType: 'uint160', + name: 'sqrtPriceX96', + type: 'uint160', + }, + { internalType: 'int24', name: 'tick', type: 'int24' }, + { + internalType: 'uint16', + name: 'observationIndex', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'observationCardinality', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'observationCardinalityNext', + type: 'uint16', + }, + { + internalType: 'uint8', + name: 'feeProtocol', + type: 'uint8', + }, + { internalType: 'bool', name: 'unlocked', type: 'bool' }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'slot0', + }) as const, + ), + } as const + const slot0 = await this.client.multicall(slot0Data).catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) const existingPools: V3Pool[] = [] @@ -151,21 +170,87 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { const tick = slot0[i]!.result?.[1] if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number') return - const activeTick = getActiveTick(tick, pool.fee) + const activeTick = this.getActiveTick(tick, pool.fee) if (typeof activeTick !== 'number') return existingPools.push({ ...pool, sqrtPriceX96, activeTick, + tick, }) }) + return existingPools + } + + getIndexes(existingPools: V3Pool[]): [number[], number[]] { + const minIndexes = existingPools.map((pool) => + bitmapIndex( + pool.activeTick - NUMBER_OF_SURROUNDING_TICKS, + this.TICK_SPACINGS[pool.fee]!, + ), + ) + const maxIndexes = existingPools.map((pool) => + bitmapIndex( + pool.activeTick + NUMBER_OF_SURROUNDING_TICKS, + this.TICK_SPACINGS[pool.fee]!, + ), + ) + return [minIndexes, maxIndexes] + } + + handleTickBoundries( + i: number, + pool: V3Pool, + poolTicks: { + index: number + DLiquidity: bigint + }[], + minIndexes: number[], + maxIndexes: number[], + ) { + const lowerUnknownTick = + minIndexes[i]! * this.TICK_SPACINGS[pool.fee]! * 256 - + this.TICK_SPACINGS[pool.fee]! + console.assert( + poolTicks.length === 0 || lowerUnknownTick < poolTicks[0]!.index, + 'Error 236: unexpected min tick index', + ) + poolTicks.unshift({ + index: lowerUnknownTick, + DLiquidity: 0n, + }) + const upperUnknownTick = + (maxIndexes[i]! + 1) * this.TICK_SPACINGS[pool.fee]! * 256 + console.assert( + poolTicks[poolTicks.length - 1]!.index < upperUnknownTick, + 'Error 244: unexpected max tick index', + ) + poolTicks.push({ + index: upperUnknownTick, + DLiquidity: 0n, + }) + } + + async fetchPoolsForToken( + t0: Token, + t1: Token, + excludePools?: Set | PoolFilter, + options?: DataFetcherOptions, + ): Promise { + const existingPools = await this.fetchPoolData( + t0, + t1, + excludePools, + options, + ) if (existingPools.length === 0) return - const liquidityContracts = this.client.multicall({ + const liquidityContractsData = { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: existingPools.map( (pool) => ({ @@ -185,12 +270,14 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { functionName: 'liquidity', }) as const, ), - }) + } as const + const liquidityContracts = this.client.multicall(liquidityContractsData) - const token0Contracts = this.client.multicall({ + const token0ContractsData = { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: existingPools.map( (pool) => ({ @@ -201,12 +288,14 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { functionName: 'balanceOf', }) as const, ), - }) + } as const + const token0Contracts = this.client.multicall(token0ContractsData) - const token1Contracts = this.client.multicall({ + const token1ContractsData = { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: existingPools.map( (pool) => ({ @@ -217,20 +306,10 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { functionName: 'balanceOf', }) as const, ), - }) + } as const + const token1Contracts = this.client.multicall(token1ContractsData) - const minIndexes = existingPools.map((pool) => - bitmapIndex( - pool.activeTick - NUMBER_OF_SURROUNDING_TICKS, - TICK_SPACINGS[pool.fee], - ), - ) - const maxIndexes = existingPools.map((pool) => - bitmapIndex( - pool.activeTick + NUMBER_OF_SURROUNDING_TICKS, - TICK_SPACINGS[pool.fee], - ), - ) + const [minIndexes, maxIndexes] = this.getIndexes(existingPools) const wordList = existingPools.flatMap((pool, i) => { const minIndex = minIndexes[i]! @@ -242,6 +321,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { ).flatMap((j) => ({ chainId: this.chainId, address: this.tickLens[ + // @ts-ignore this.chainId as keyof typeof this.tickLens ] as Address, args: [pool.address, j] as const, @@ -251,12 +331,14 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { })) }) - const ticksContracts = this.client.multicall({ + const ticksContractsData = { multicallAddress: this.client.chain?.contracts?.multicall3 ?.address as Address, allowFailure: true, contracts: wordList, - }) + blockNumber: options?.blockNumber, + } as const + const ticksContracts = this.client.multicall(ticksContractsData) const [liquidityResults, token0Balances, token1Balances, tickResults] = await Promise.all([ @@ -295,26 +377,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { DLiquidity: tick.liquidityNet, })).sort((a, b) => a.index - b.index) - const lowerUnknownTick = - minIndexes[i]! * TICK_SPACINGS[pool.fee] * 256 - TICK_SPACINGS[pool.fee] - console.assert( - poolTicks.length === 0 || lowerUnknownTick < poolTicks[0]!.index, - 'Error 236: unexpected min tick index', - ) - poolTicks.unshift({ - index: lowerUnknownTick, - DLiquidity: 0n, - }) - const upperUnknownTick = - (maxIndexes[i]! + 1) * TICK_SPACINGS[pool.fee] * 256 - console.assert( - poolTicks[poolTicks.length - 1]!.index < upperUnknownTick, - 'Error 244: unexpected max tick index', - ) - poolTicks.push({ - index: upperUnknownTick, - DLiquidity: 0n, - }) + this.handleTickBoundries(i, pool, poolTicks, minIndexes, maxIndexes) //console.log(pool.fee, TICK_SPACINGS[pool.fee], pool.activeTick, minIndexes[i], maxIndexes[i], poolTicks) const v3Pool = new UniV3Pool( @@ -336,7 +399,7 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { this.getPoolProviderName(), ) transformedV3Pools.push(pc) - this.pools.set(pool.address.toLowerCase(), pc) + this.poolsCodes.set(pool.address.toLowerCase(), pc) }) this.poolsByTrade.set( @@ -345,28 +408,22 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { ) } - getStaticPools(t1: Token, t2: Token): StaticPool[] { + getStaticPools(t1: Token, t2: Token): StaticPoolUniV3[] { + const feeList = Object.values(this.FEE).filter((v) => typeof v === 'number') const currencyCombinations = getCurrencyCombinations(this.chainId, t1, t2) - const allCurrencyCombinationsWithAllFees: [ - Type, - Type, - SushiSwapV3FeeAmount, - ][] = currencyCombinations.reduce< - [Currency, Currency, SushiSwapV3FeeAmount][] - >((list, [tokenA, tokenB]) => { - if (tokenA !== undefined && tokenB !== undefined) { - return list.concat([ - [tokenA, tokenB, SushiSwapV3FeeAmount.LOWEST], - [tokenA, tokenB, SushiSwapV3FeeAmount.LOW], - [tokenA, tokenB, SushiSwapV3FeeAmount.MEDIUM], - [tokenA, tokenB, SushiSwapV3FeeAmount.HIGH], - ]) - } - return [] - }, []) - - const filtered: [Token, Token, SushiSwapV3FeeAmount][] = [] + const allCurrencyCombinationsWithAllFees: [Type, Type, number][] = + currencyCombinations.reduce<[Currency, Currency, number][]>( + (list, [tokenA, tokenB]) => { + if (tokenA !== undefined && tokenB !== undefined) { + return list.concat(feeList.map((fee) => [tokenA, tokenB, fee])) + } + return [] + }, + [], + ) + + const filtered: [Token, Token, number][] = [] allCurrencyCombinationsWithAllFees.forEach( ([currencyA, currencyB, feeAmount]) => { if (currencyA && currencyB && feeAmount) { @@ -400,26 +457,26 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { startFetchPoolsData() { this.stopFetchPoolsData() // this.topPools = new Map() - this.unwatchBlockNumber = this.client.watchBlockNumber({ - onBlockNumber: (blockNumber) => { - this.lastUpdateBlock = Number(blockNumber) - // if (!this.isInitialized) { - // this.initialize() - // } else { - // this.updatePools() - // } - }, - onError: (error) => { - console.error( - `${this.getLogPrefix()} - Error watching block number: ${ - error.message - }`, - ) - }, - }) + // this.unwatchBlockNumber = this.client.watchBlockNumber({ + // onBlockNumber: (blockNumber) => { + // this.lastUpdateBlock = Number(blockNumber) + // // if (!this.isInitialized) { + // // this.initialize() + // // } else { + // // this.updatePools() + // // } + // }, + // onError: (error) => { + // console.error( + // `${this.getLogPrefix()} - Error watching block number: ${ + // error.message + // }`, + // ) + // }, + // }) } - getCurrentPoolList(): PoolCode[] { + getCurrentPoolList(_t0: Token, _t1: Token): PoolCode[] { // const tradeId = this.getTradeId(t0, t1) // const poolsByTrade = this.poolsByTrade.get(tradeId) ?? [] // return poolsByTrade @@ -427,11 +484,37 @@ export abstract class UniswapV3BaseProvider extends LiquidityProvider { // .filter(([poolAddress]) => poolsByTrade.includes(poolAddress)) // .map(([, p]) => p) // : [] - return Array.from(this.pools.values()) + return Array.from(this.poolsCodes.values()) } stopFetchPoolsData() { if (this.unwatchBlockNumber) this.unwatchBlockNumber() this.blockListener = undefined } + + async ensureFeeAndTicks(): Promise { + const feeList = Object.values(this.FEE).filter((v) => typeof v === 'number') + const results = (await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: feeList.map( + (fee) => + ({ + chainId: this.chainId, + address: this.factory[this.chainId as keyof typeof this.factory]!, + abi: uniswapV3FactoryAbi, + functionName: 'feeAmountTickSpacing', + args: [fee], + }) as const, + ), + })) as number[] + + // fetched fee map to ticks should match correctly with hardcoded literals in the dex + // a tick can be 0 if there is no pools deployed with that fee yet + return results.every( + (v, i) => + this.TICK_SPACINGS[feeList[i] as SushiSwapV3FeeAmount] === v || v === 0, + ) + } } diff --git a/packages/sushi/src/router/liquidity-providers/VVSFlawless.ts b/packages/sushi/src/router/liquidity-providers/VVSFlawless.ts new file mode 100644 index 0000000000..8bfbb9add2 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/VVSFlawless.ts @@ -0,0 +1,113 @@ +import { Address, PublicClient } from 'viem' +import { uniswapV3FactoryAbi } from '../../abi/uniswapV3FactoryAbi.js' +import { ChainId } from '../../chain/index.js' +import { SushiSwapV3FeeAmount } from '../../config/sushiswap-v3.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +/** + * The default factory enabled fee amounts, denominated in hundredths of bips. + */ +export enum VVSFlawlessFeeAmount { + /** 0.01% */ + LOWEST = 100, + /** 0.05% */ + LOW = 500, + /** 0.3% */ + MEDIUM = 3000, + /** 1% */ + HIGH = 10000, +} + +export const VVS_FLAWLESS_FEE_SPACING_MAP: Record< + VVSFlawlessFeeAmount, + number +> = { + [VVSFlawlessFeeAmount.LOWEST]: 1, + [VVSFlawlessFeeAmount.LOW]: 10, + [VVSFlawlessFeeAmount.MEDIUM]: 60, + [VVSFlawlessFeeAmount.HIGH]: 200, +} + +export class VVSFlawlessProvider extends UniswapV3BaseProvider { + override FEE = VVSFlawlessFeeAmount + override TICK_SPACINGS = VVS_FLAWLESS_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.CRONOS]: '0x6757E8E1B694e60285D733D8684eF2F60b2407ff', + } as const + const initCodeHash = { + [ChainId.CRONOS]: + '0x3ea5f55d6524ce396b6eb0054ae36a854425f2ed4c48b04b78e228656dc0b7de', + } as const + const tickLens = { + [ChainId.CRONOS]: '0xFe2b370F14Efe064Ae6ef17f44EB3F72594F2939', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.VVSFlawless + } + getPoolProviderName(): string { + return 'VVSFlawless' + } + + override async ensureFeeAndTicks(): Promise { + const feeList = [ + this.FEE.LOWEST, + this.FEE.LOW, + this.FEE.MEDIUM, + this.FEE.HIGH, + ] as number[] + const factoryAddress = ( + await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: [ + { + address: this.factory[this.chainId as keyof typeof this.factory]!, + abi: [ + { + inputs: [], + name: 'factoryAddress', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'factoryAddress', + } as const, + ], + }) + )[0] + + const results = (await this.client.multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: false, + contracts: feeList.map( + (fee) => + ({ + chainId: this.chainId, + address: factoryAddress as Address, + abi: uniswapV3FactoryAbi, + functionName: 'feeAmountTickSpacing', + args: [fee], + }) as const, + ), + })) as number[] + + // fetched fee map to ticks should match correctly with hardcoded literals in the dex + return results.every( + (v, i) => + this.TICK_SPACINGS[feeList[i] as SushiSwapV3FeeAmount] === v || v === 0, + ) + } +} diff --git a/packages/sushi/src/router/liquidity-providers/VVSStandard.ts b/packages/sushi/src/router/liquidity-providers/VVSStandard.ts new file mode 100644 index 0000000000..f5f9a13380 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/VVSStandard.ts @@ -0,0 +1,23 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class VVSStandardProvider extends UniswapV2BaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.CRONOS]: '0x3B44B2a187a7b3824131F8db5a74194D0a42Fc15', + } as const + const initCodeHash = { + [ChainId.CRONOS]: + '0xa77ee1cc0f39570ddde947459e293d7ebc2c30ff4e8fc45860afdcb2c2d3dc17', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.VVSStandard + } + getPoolProviderName(): string { + return 'VVSStandard' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/VelodromeSlipstream.ts b/packages/sushi/src/router/liquidity-providers/VelodromeSlipstream.ts new file mode 100644 index 0000000000..15c192f65c --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/VelodromeSlipstream.ts @@ -0,0 +1,22 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { VelodromeSlipstreamBaseProvider } from '../rain/VelodromeSlipstreamBase.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class VelodromeSlipstreamProvider extends VelodromeSlipstreamBaseProvider { + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.OPTIMISM]: '0xCc0bDDB707055e04e497aB22a59c2aF4391cd12F', + } as const + const tickLens = { + [ChainId.OPTIMISM]: '0x49C6FDCb3D5b2CecD8baff66c8e94b9B261ad925', + } as const + super(chainId, web3Client, factory, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.VelodromeSlipstream + } + getPoolProviderName(): string { + return 'VelodromeSlipstream' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Wagmi.ts b/packages/sushi/src/router/liquidity-providers/Wagmi.ts new file mode 100644 index 0000000000..e49cc2cfc3 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Wagmi.ts @@ -0,0 +1,85 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +enum WagmiFeeAmount { + /** 0.01% */ + LOWEST = 500, + /** 0.15% */ + LOW = 1500, + /** 0.3% */ + MEDIUM = 3000, + /** 1% */ + HIGH = 10000, +} + +const WagmiTickSpacing: Record = { + [WagmiFeeAmount.LOWEST]: 10, + [WagmiFeeAmount.LOW]: 30, + [WagmiFeeAmount.MEDIUM]: 60, + [WagmiFeeAmount.HIGH]: 200, +} + +export class WagmiProvider extends UniswapV3BaseProvider { + override FEE = WagmiFeeAmount + override TICK_SPACINGS = WagmiTickSpacing + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.ETHEREUM]: '0xB9a14EE1cd3417f3AcC988F61650895151abde24', + [ChainId.FANTOM]: '0xaf20f5f19698f1D19351028cd7103B63D30DE7d7', + [ChainId.KAVA]: '0x0e0Ce4D450c705F8a0B6Dd9d5123e3df2787D16B', + [ChainId.ZKSYNC_ERA]: '0x31be61CE896e8770B21e7A1CAFA28402Dd701995', + [ChainId.METIS]: '0x8112E18a34b63964388a3B2984037d6a2EFE5B8A', + [ChainId.BASE]: '0x576A1301B42942537d38FB147895fE83fB418fD4', + + // these chains dont have any pools deployed yet + // [ChainId.OPTIMISM]: '0xC49c177736107fD8351ed6564136B9ADbE5B1eC3', + // [ChainId.BSC]: '0xE3Dc1A5a7aB81F1cC1895FA55034725c24a5BD0e', + // [ChainId.POLYGON]: '0x8bb1Be7acD806BF6C9766486dC4c21284a472BaC', + // [ChainId.AVALANCHE]: '0x08d6E1aE0f91423dDBD16f083ca39ccDd1D79cE8', + // [ChainId.ARBITRUM]: '0x7301350CC76D669ea384e77aF38a70C61661CA48', + } as const + const initCodeHash = { + [ChainId.ETHEREUM]: + '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + [ChainId.FANTOM]: + '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + [ChainId.KAVA]: + '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + [ChainId.ZKSYNC_ERA]: + '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + [ChainId.METIS]: + '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + [ChainId.BASE]: + '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + + // [ChainId.OPTIMISM]: '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + // [ChainId.BSC]: '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + // [ChainId.POLYGON]: '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + // [ChainId.AVALANCHE]: '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + // [ChainId.ARBITRUM]: '0x30146866f3a846fe3c636beb2756dbd24cf321bc52c9113c837c21f47470dfeb', + } as const + const tickLens = { + [ChainId.ETHEREUM]: '0xb1F795776cB9DdAC6E7e162f31C7419Dd3d48297', + [ChainId.FANTOM]: '0x209050d81Aad536Ca2092466B221013B8de7AC6c', + [ChainId.KAVA]: '0xf914e1329e4588783Ee68f06B2b900adDC97f966', + [ChainId.ZKSYNC_ERA]: '0x09Cbf436DE2273dAC3f0971fB905aCBe41b1CC81', + [ChainId.METIS]: '0x428065998a96F82bf66A0A427A157429A6Fdd649', + [ChainId.BASE]: '0x2Dc123Ff6757fcEa46c025758E93bd8b98710cEA', + + // [ChainId.OPTIMISM]: '0xE1609682d9fA627301125C402078A8074151886d', + // [ChainId.BSC]: '0x67241f1a9471B366039bdBbc1810061A7312298f', + // [ChainId.POLYGON]: '0xA6D200ED01389b49E21D8A0018d5b81528bcFC0D', + // [ChainId.AVALANCHE]: '0x66034b71A749E655feE0005C5496D5c0949590F0', + // [ChainId.ARBITRUM]: '0x08d6E1aE0f91423dDBD16f083ca39ccDd1D79cE8', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.Wagmi + } + getPoolProviderName(): string { + return 'Wagmi' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/Wigoswap.ts b/packages/sushi/src/router/liquidity-providers/Wigoswap.ts new file mode 100644 index 0000000000..d1689f67c1 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/Wigoswap.ts @@ -0,0 +1,24 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV2BaseProvider } from '../rain/UniswapV2Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +export class WigoswapProvider extends UniswapV2BaseProvider { + override fee = 0.0019 + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.FANTOM]: '0xC831A5cBfb4aC2Da5ed5B194385DFD9bF5bFcBa7', + } as const + const initCodeHash = { + [ChainId.FANTOM]: + '0x55c39e9406ff3c89a193882b4752879e73c8a0ce1222fe1de34c5e8f6482d9b6', + } as const + super(chainId, web3Client, factory, initCodeHash) + } + getType(): LiquidityProviders { + return LiquidityProviders.Wigoswap + } + getPoolProviderName(): string { + return 'Wigoswap' + } +} diff --git a/packages/sushi/src/router/liquidity-providers/ZebraV2.ts b/packages/sushi/src/router/liquidity-providers/ZebraV2.ts new file mode 100644 index 0000000000..8636114020 --- /dev/null +++ b/packages/sushi/src/router/liquidity-providers/ZebraV2.ts @@ -0,0 +1,46 @@ +import { PublicClient } from 'viem' +import { ChainId } from '../../chain/index.js' +import { UniswapV3BaseProvider } from '../rain/UniswapV3Base.js' +import { LiquidityProviders } from './LiquidityProvider.js' + +/** + * The default factory enabled fee amounts, denominated in hundredths of bips. + */ +export enum ZebraV2FeeAmount { + /** 0.05% */ + LOW = 500, + /** 0.3% */ + MEDIUM = 3000, + /** 1% */ + HIGH = 10000, +} + +export const ZEBRA_V2_FEE_SPACING_MAP: Record = { + [ZebraV2FeeAmount.LOW]: 10, + [ZebraV2FeeAmount.MEDIUM]: 60, + [ZebraV2FeeAmount.HIGH]: 200, +} + +export class ZebraV2Provider extends UniswapV3BaseProvider { + override FEE = ZebraV2FeeAmount as any + override TICK_SPACINGS = ZEBRA_V2_FEE_SPACING_MAP + constructor(chainId: ChainId, web3Client: PublicClient) { + const factory = { + [ChainId.SCROLL]: '0x96a7F53f7636c93735bf85dE416A4Ace94B56Bd9', + } as const + const initCodeHash = { + [ChainId.SCROLL]: + '0xcf0b3414328c2bd327a4f093539d0d7d82fb94f893a2965c75cb470289cb5ac7', + } as const + const tickLens = { + [ChainId.SCROLL]: '0x1Daef3F1D97CcD9ae428641B23733cF1C619AeAA', + } as const + super(chainId, web3Client, factory, initCodeHash, tickLens) + } + getType(): LiquidityProviders { + return LiquidityProviders.ZebraV2 + } + getPoolProviderName(): string { + return 'ZebraV2' + } +} diff --git a/packages/sushi/src/router/rain/AlgebraV1Base.ts b/packages/sushi/src/router/rain/AlgebraV1Base.ts new file mode 100644 index 0000000000..08c5929318 --- /dev/null +++ b/packages/sushi/src/router/rain/AlgebraV1Base.ts @@ -0,0 +1,298 @@ +import { + Address, + Hex, + Log, + PublicClient, + encodeAbiParameters, + getAddress, + keccak256, + parseAbiItem, + parseEventLogs, +} from 'viem' +import { ChainId } from '../../chain/index.js' +import { Token } from '../../currency/index.js' +import { getCurrencyCombinations } from '../get-currency-combinations.js' +import { + PoolFilter, + StaticPoolUniV3, +} from '../liquidity-providers/UniswapV3Base.js' +import { RainDataFetcherOptions } from './RainDataFetcher.js' +import { + RainV3Pool, + UniV3EventsAbi, + UniswapV3BaseProvider, +} from './UniswapV3Base.js' + +export const AlgebraEventsAbi = [ + ...UniV3EventsAbi.slice(0, 5), // same as univ3 Swap, Mint, Collect, Burn, Flash events + // algebra specific events + parseAbiItem('event Fee(uint16 fee)'), + parseAbiItem('event TickSpacing(int24 newTickSpacing)'), + parseAbiItem( + 'event Pool(address indexed token0, address indexed token1, address pool)', + ), +] + +export const globalStateAbi = [ + { + inputs: [], + name: 'globalState', + outputs: [ + { internalType: 'uint160', name: 'price', type: 'uint160' }, + { internalType: 'int24', name: 'tick', type: 'int24' }, + { internalType: 'uint16', name: 'fee', type: 'uint16' }, + { + internalType: 'uint16', + name: 'timepointIndex', + type: 'uint16', + }, + { + internalType: 'uint8', + name: 'communityFeeToken0', + type: 'uint8', + }, + { + internalType: 'uint8', + name: 'communityFeeToken1', + type: 'uint8', + }, + { internalType: 'bool', name: 'unlocked', type: 'bool' }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const + +export abstract class AlgebraV1BaseProvider extends UniswapV3BaseProvider { + override TICK_SPACINGS: Record = {} + override eventsAbi = AlgebraEventsAbi as any + + readonly BASE_FEE = 100 + DEFAULT_TICK_SPACING = 1 + gloablStateAbi = globalStateAbi + + poolDeployer: Record = {} + + constructor( + chainId: ChainId, + web3Client: PublicClient, + factory: Record, + initCodeHash: Record, + tickLens: Record, + poolDeployer: Record, + isTest = false, + ) { + super(chainId, web3Client, factory, initCodeHash, tickLens, isTest) + this.poolDeployer = poolDeployer + if (!(chainId in this.poolDeployer)) { + throw new Error( + `${this.getType()} cannot be instantiated for chainid ${chainId}, no poolDeployer address`, + ) + } + } + + override async fetchPoolData( + t0: Token, + t1: Token, + excludePools?: Set | PoolFilter, + options?: RainDataFetcherOptions, + ): Promise { + let staticPools = this.getStaticPools(t0, t1) + if (excludePools) + staticPools = staticPools.filter((p) => !excludePools.has(p.address)) + + const tradeId = this.getTradeId(t0, t1) + if (!this.poolsByTrade.has(tradeId)) + this.poolsByTrade.set( + tradeId, + staticPools.map((pool) => pool.address.toLowerCase()), + ) + + // filter out cached pools + // this ensures backward compatibility for original DataFetcher + if (typeof options?.ignoreCache === 'boolean' && !options.ignoreCache) { + staticPools = this.filterCachedPools(staticPools) + } + if (staticPools.length === 0) return [] + + const globalStateData = { + multicallAddress: this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: staticPools.map( + (pool) => + ({ + address: pool.address, + chainId: this.chainId, + abi: this.gloablStateAbi, + functionName: 'globalState', + }) as const, + ), + } as const + const globalState = await this.client + .multicall(globalStateData) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + const tickSpacings = await this.getTickSpacing(staticPools, options) + + const existingPools: RainV3Pool[] = [] + staticPools.forEach((pool, i) => { + const poolAddress = pool.address.toLowerCase() + if (globalState === undefined || !globalState[i]) { + this.handleNullPool(poolAddress) + return + } + let tickSpacing = this.DEFAULT_TICK_SPACING + if (typeof tickSpacings?.[i]?.result === 'number') { + tickSpacing = tickSpacings[i]!.result! + } + const sqrtPriceX96 = globalState[i]!.result?.[0] // price + const tick = globalState[i]!.result?.[1] // tick + if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number') { + this.handleNullPool(poolAddress) + return + } + const fee = globalState[i]!.result?.[2] // fee + if (!fee) { + this.handleNullPool(poolAddress) + return + } + const activeTick = this.getActiveTick(tick, tickSpacing) + if (typeof activeTick !== 'number') { + this.handleNullPool(poolAddress) + return + } + existingPools.push({ + ...pool, + fee, + sqrtPriceX96, + activeTick, + tickSpacing, + ticks: new Map(), + reserve0: 0n, + reserve1: 0n, + liquidity: 0n, + blockNumber: options?.blockNumber ?? 0n, + tick, + }) + }) + + return existingPools + } + + override getStaticPools(t1: Token, t2: Token): StaticPoolUniV3[] { + const allCombinations = getCurrencyCombinations(this.chainId, t1, t2) + const currencyCombinations: [Token, Token][] = [] + allCombinations.forEach(([currencyA, currencyB]) => { + if (currencyA && currencyB) { + const tokenA = currencyA.wrapped + const tokenB = currencyB.wrapped + if (tokenA.equals(tokenB)) return + currencyCombinations.push( + tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA], + ) + } + }) + return currencyCombinations.map(([currencyA, currencyB]) => ({ + address: getAlgebraPoolAddress( + this.poolDeployer[this.chainId as keyof typeof this.poolDeployer]!, + currencyA.wrapped.address, + currencyB.wrapped.address, + this.initCodeHash[ + this.chainId as keyof typeof this.initCodeHash + ] as `0x${string}`, + ), + token0: currencyA, + token1: currencyB, + fee: this.BASE_FEE, + })) + } + + // algebra doesnt have the fee/ticks setup the same way univ3 has + override async ensureFeeAndTicks(): Promise { + return true + } + + // handle algebra specific pool creation event + override handleFactoryEvents(log: Log): boolean { + const factory = + this.factory[this.chainId as keyof typeof this.factory]!.toLowerCase() + const logAddress = log.address.toLowerCase() + if (logAddress === factory) { + try { + const event = parseEventLogs({ + logs: [log], + abi: AlgebraEventsAbi, + eventName: 'Pool', + })[0]! + return this.nullPools.delete(event.args.pool.toLowerCase()) + } catch {} + } + return false + } + + // handle extra events that Algebra has + override otherEventCases( + log: Log, + event: Log< + bigint, + number, + boolean, + (typeof AlgebraEventsAbi)[number], + true, + typeof AlgebraEventsAbi, + (typeof AlgebraEventsAbi)[number]['name'] + >, + pool: RainV3Pool, + ): void { + switch (event.eventName) { + case 'Fee': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + pool.fee = event.args.fee + } + break + } + case 'TickSpacing': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + pool.tickSpacing = event.args.newTickSpacing + } + break + } + default: + } + } +} + +// from packages/extractor/src/AlgebraExtractor.ts +export function getAlgebraPoolAddress( + poolDeployer: Address, + tokenA: Address, + tokenB: Address, + initCodeHash: Hex, +): Address { + const constructorArgumentsEncoded = encodeAbiParameters( + [ + { name: 'TokenA', type: 'address' }, + { name: 'TokenB', type: 'address' }, + ], + [tokenA, tokenB], + ) + const create2Inputs = [ + '0xff', + poolDeployer, + keccak256(constructorArgumentsEncoded as Hex), + initCodeHash, + ] + const sanitizedInputs = `0x${create2Inputs.map((i) => i.slice(2)).join('')}` + + return getAddress(`0x${keccak256(sanitizedInputs as Hex).slice(-40)}`) +} diff --git a/packages/sushi/src/router/rain/RainDataFetcher.test.ts b/packages/sushi/src/router/rain/RainDataFetcher.test.ts new file mode 100644 index 0000000000..bb64bddd01 --- /dev/null +++ b/packages/sushi/src/router/rain/RainDataFetcher.test.ts @@ -0,0 +1,198 @@ +import { PublicClient, createPublicClient } from 'viem' +import { beforeEach, describe, expect, it } from 'vitest' +import { ChainId } from '../../chain/constants.js' +import { ROUTE_PROCESSOR_4_ADDRESS } from '../../config/route-processor.js' +import { publicClientConfig } from '../../config/viem.js' +import { Token } from '../../currency/Token.js' +import { USDC, WNATIVE } from '../../currency/tokens.js' +import { LiquidityProviders } from '../liquidity-providers/index.js' +import { Router } from '../router.js' +import { RainDataFetcher } from './RainDataFetcher.js' + +describe('RainDataFetcher tests', async () => { + // we test on Base chain because it has at least one of each dex type + const client = createPublicClient(publicClientConfig[ChainId.BASE]) + + // 3000 blocks apart, to test pool data updates by event logs + const currentBlockNumber = await client.getBlockNumber() + const oldBlockNumber = currentBlockNumber - 3000n + + const fromToken = USDC[ChainId.BASE] + const toToken = WNATIVE[ChainId.BASE] + const amountIn = 10_000_000n // 10 USDC + const gasPrice = 30_000_000n + + // one of each type + const protocols = { + univ2: LiquidityProviders.UniswapV2, // Univ2 + univ3: LiquidityProviders.UniswapV3, // Univ3 + algebraV1: LiquidityProviders.KimV4, // Algebra Integral v1/v1.1 + slipstream: LiquidityProviders.AerodromeSlipstream, // Slipstream + algebraV1_2: LiquidityProviders.Hydrex, // Algebra Integral V1.2/v1.2.1 + } + + // wait 60 sec before each test to avoid rpc ratelimiting + beforeEach(async () => { + await new Promise((resolve) => setTimeout(() => resolve(1), 60_000)) + }) + + it('should correctly update pools data by logs for Univ2 protocol', async () => { + await testRainDataFetcher( + [protocols.univ2], + client, + fromToken, + toToken, + amountIn, + gasPrice, + currentBlockNumber, + oldBlockNumber, + ) + }) + + it('should correctly update pools data by logs for Univ3 protocol', async () => { + await testRainDataFetcher( + [protocols.univ3], + client, + fromToken, + toToken, + amountIn, + gasPrice, + currentBlockNumber, + oldBlockNumber, + ) + }) + + it('should correctly update pools data by logs for Algebra Integral v1/v1.1 protocol', async () => { + await testRainDataFetcher( + [protocols.algebraV1], + client, + fromToken, + toToken, + amountIn, + gasPrice, + currentBlockNumber, + oldBlockNumber, + ) + }) + + it('should correctly update pools data by logs for Slipstream protocol', async () => { + await testRainDataFetcher( + [protocols.slipstream], + client, + fromToken, + toToken, + amountIn, + gasPrice, + currentBlockNumber, + oldBlockNumber, + ) + }) + + it('should correctly update pools data by logs for Algebra Integral v1.2/v1.2.1 protocol', async () => { + await testRainDataFetcher( + [protocols.algebraV1_2], + client, + fromToken, + toToken, + amountIn, + gasPrice, + currentBlockNumber, + oldBlockNumber, + ) + }) +}) + +async function testRainDataFetcher( + lps: LiquidityProviders[], + client: PublicClient, + fromToken: Token, + toToken: Token, + amountIn: bigint, + gasPrice: bigint, + currentBlockNumber: bigint, + oldBlockNumber: bigint, +) { + // data fetcher without indexer (normal way ie raw pool data fecthed directly by contract calls) + const dataFetcherFresh = await RainDataFetcher.init(ChainId.BASE, client, lps) + + // data fetcher with indexer (pool data will be updated from older block to current block by event logs) + const dataFetcherIndexer = await RainDataFetcher.init( + ChainId.BASE, + client, + lps, + ) + + // get route at current block height for fresh dataFetcher + const { pcMap: freshPcMap, route: freshRoute } = + await dataFetcherFresh.findBestRoute( + ChainId.BASE, + fromToken, + toToken, + amountIn, + gasPrice, + false, + { blockNumber: currentBlockNumber }, + lps, + undefined, + 'single', + ) + + // get route at older block height for indexer dataFetcher, then ensure the + // amount out it gives is different to fresh datafetcher amount out + // and then update the pools data with contract logs from between the blocks + const { route: indexerRouteOld } = await dataFetcherIndexer.findBestRoute( + ChainId.BASE, + fromToken, + toToken, + amountIn, + gasPrice, + false, + { blockNumber: oldBlockNumber }, + lps, + undefined, + 'single', + ) + + // should not be equal + // just to make sure that pool data are actually different in current vs old block height + expect(freshRoute.amountOutBI).not.equal(indexerRouteOld.amountOutBI) + + // now get route at current block height for indexer dataFetcher with updating pool data + const { pcMap: indexerPcMap, route: indexerRoute } = + await dataFetcherIndexer.findBestRoute( + ChainId.BASE, + fromToken, + toToken, + amountIn, + gasPrice, + true, // update pool data by logs + { blockNumber: currentBlockNumber }, + lps, + undefined, + 'single', + ) + + // assert amount outs and status + expect(freshRoute.status).toEqual(indexerRoute.status) + expect(freshRoute.amountOutBI).toEqual(indexerRoute.amountOutBI) + expect(freshRoute.totalAmountOutBI).toEqual(indexerRoute.totalAmountOutBI) + + // assert produced route code + const freshRpParams = Router.routeProcessor4Params( + freshPcMap, + freshRoute, + fromToken, + toToken, + ROUTE_PROCESSOR_4_ADDRESS[ChainId.BASE], + ROUTE_PROCESSOR_4_ADDRESS[ChainId.BASE], + ) + const indexerRpParams = Router.routeProcessor4Params( + indexerPcMap, + indexerRoute, + fromToken, + toToken, + ROUTE_PROCESSOR_4_ADDRESS[ChainId.BASE], + ROUTE_PROCESSOR_4_ADDRESS[ChainId.BASE], + ) + expect(freshRpParams.routeCode).toEqual(indexerRpParams.routeCode) +} diff --git a/packages/sushi/src/router/rain/RainDataFetcher.ts b/packages/sushi/src/router/rain/RainDataFetcher.ts new file mode 100644 index 0000000000..756bce5d2e --- /dev/null +++ b/packages/sushi/src/router/rain/RainDataFetcher.ts @@ -0,0 +1,526 @@ +import { ParseAbiItem, PublicClient, toEventSignature } from 'viem' +import { ChainId } from '../../chain/constants.js' +import { Type } from '../../currency/index.js' +import { MultiRoute } from '../../tines/Graph.js' +import { DataFetcher, DataFetcherOptions } from '../data-fetcher.js' +import { AerodromeSlipstreamProvider } from '../liquidity-providers/AerodromeSlipstream.js' +import { AerodromeSlipstreamV2Provider } from '../liquidity-providers/AerodromeSlipstreamV2.js' +import { AlienBaseV2Provider } from '../liquidity-providers/AlienBaseV2.js' +import { AlienBaseV3Provider } from '../liquidity-providers/AlienBaseV3.js' +import { ApeSwapProvider } from '../liquidity-providers/ApeSwap.js' +import { BSCSwapProvider } from '../liquidity-providers/BSCSwap.js' +import { BakerySwapProvider } from '../liquidity-providers/BakerySwap.js' +import { BaseSwapProvider } from '../liquidity-providers/BaseSwap.js' +import { BaseSwapV3Provider } from '../liquidity-providers/BaseSwapV3.js' +import { BiswapProvider } from '../liquidity-providers/Biswap.js' +import { BladeSwapProvider } from '../liquidity-providers/BladeSwap.js' +import { BlastDEXProvider } from '../liquidity-providers/BlastDEX.js' +import { BlazeSwapProvider } from '../liquidity-providers/BlazeSwap.js' +import { CORExProvider } from '../liquidity-providers/COREx.js' +import { CroDefiSwapProvider } from '../liquidity-providers/CroDefiSwap.js' +import { DackieSwapV2Provider } from '../liquidity-providers/DackieSwapV2.js' +import { DackieSwapV3Provider } from '../liquidity-providers/DackieSwapV3.js' +import { DfynProvider } from '../liquidity-providers/Dfyn.js' +import { DovishV3Provider } from '../liquidity-providers/DovishV3.js' +import { DyorV2Provider } from '../liquidity-providers/DyorV2.js' +import { EddyFinanceProvider } from '../liquidity-providers/EddyFinance.js' +import { ElkProvider } from '../liquidity-providers/Elk.js' +import { EnosysProvider } from '../liquidity-providers/Enosys.js' +import { FenixProvider } from '../liquidity-providers/Fenix.js' +import { GlyphV4Provider } from '../liquidity-providers/GlyphV4.js' +import { GravityFinanceProvider } from '../liquidity-providers/GravityFinance.js' +import { HoneySwapProvider } from '../liquidity-providers/HoneySwap.js' +import { HorizonProvider } from '../liquidity-providers/Horizon.js' +import { HydrexProvider } from '../liquidity-providers/Hydrex.js' +import { HyperBlastProvider } from '../liquidity-providers/HyperBlast.js' +import { JetSwapProvider } from '../liquidity-providers/JetSwap.js' +import { KimV4Provider } from '../liquidity-providers/KimV4.js' +import { KinetixV2Provider } from '../liquidity-providers/KinetixV2.js' +import { KinetixV3Provider } from '../liquidity-providers/KinetixV3.js' +import { KodiakV2Provider } from '../liquidity-providers/KodiakV2.js' +import { KodiakV3Provider } from '../liquidity-providers/KodiakV3.js' +import { KwikswapProvider } from '../liquidity-providers/Kwikswap.js' +import { LaserSwapV2Provider } from '../liquidity-providers/LaserSwap.js' +import { LiquidityProviders } from '../liquidity-providers/LiquidityProvider.js' +import { LynexV1Provider } from '../liquidity-providers/LynexV1.js' +import { LynexV2Provider } from '../liquidity-providers/LynexV2.js' +import { MMFinanceProvider } from '../liquidity-providers/MMFinance.js' +import { MSwapProvider } from '../liquidity-providers/MSwap.js' +import { MonoswapV2Provider } from '../liquidity-providers/MonoSwapV2.js' +import { MonoswapV3Provider } from '../liquidity-providers/MonoSwapV3.js' +import { NativeWrapProvider } from '../liquidity-providers/NativeWrapProvider.js' +import { NetSwapProvider } from '../liquidity-providers/NetSwap.js' +import { NileV3Provider } from '../liquidity-providers/NileV3.js' +import { NineInchProvider } from '../liquidity-providers/NineInch.js' +import { PancakeSwapV2Provider } from '../liquidity-providers/PancakeSwapV2.js' +import { PancakeSwapV3Provider } from '../liquidity-providers/PancakeSwapV3.js' +import { PangolinProvider } from '../liquidity-providers/Pangolin.js' +import { QuickSwapV2Provider } from '../liquidity-providers/QuickSwapV2.js' +import { QuickSwapV3Provider } from '../liquidity-providers/QuickswapV3.js' +import { RingExchangeV2Provider } from '../liquidity-providers/RingExchangeV2.js' +import { RingExchangeV3Provider } from '../liquidity-providers/RingExchangeV3.js' +import { ScribeProvider } from '../liquidity-providers/Scribe.js' +import { ShibaSwapProvider } from '../liquidity-providers/ShibaSwap.js' +import { SolarbeamProvider } from '../liquidity-providers/Solarbeam.js' +import { SparkDexV2Provider } from '../liquidity-providers/SparkDexV2.js' +import { SparkDexV3Provider } from '../liquidity-providers/SparkDexV3.js' +import { SparkDexV3_1Provider } from '../liquidity-providers/SparkDexV3_1.js' +import { SpookySwapV2Provider } from '../liquidity-providers/SpookySwapV2.js' +import { SpookySwapV3Provider } from '../liquidity-providers/SpookySwapV3.js' +import { SquadSwapV2Provider } from '../liquidity-providers/SquadSwapV2.js' +import { SushiSwapV2Provider } from '../liquidity-providers/SushiSwapV2.js' +import { SushiSwapV3Provider } from '../liquidity-providers/SushiSwapV3.js' +import { SwapBlastProvider } from '../liquidity-providers/SwapBlast.js' +import { SwapsicleProvider } from '../liquidity-providers/Swapsicle.js' +import { + ThrusterV2_1Provider, + ThrusterV2_3Provider, +} from '../liquidity-providers/ThrusterV2.js' +import { ThrusterV3Provider } from '../liquidity-providers/ThrusterV3.js' +import { TraderJoeProvider } from '../liquidity-providers/TraderJoe.js' +import { UbeSwapProvider } from '../liquidity-providers/UbeSwap.js' +import { UniswapV2Provider } from '../liquidity-providers/UniswapV2.js' +import { UniswapV3Provider } from '../liquidity-providers/UniswapV3.js' +import { VVSFlawlessProvider } from '../liquidity-providers/VVSFlawless.js' +import { VVSStandardProvider } from '../liquidity-providers/VVSStandard.js' +import { VelodromeSlipstreamProvider } from '../liquidity-providers/VelodromeSlipstream.js' +import { WagmiProvider } from '../liquidity-providers/Wagmi.js' +import { WigoswapProvider } from '../liquidity-providers/Wigoswap.js' +import { ZebraV2Provider } from '../liquidity-providers/ZebraV2.js' +import { PoolCode } from '../pool-codes/PoolCode.js' +import { PoolFilter, Router } from '../router.js' +import { UniswapV2BaseProvider } from './UniswapV2Base.js' +import { UniswapV3BaseProvider } from './UniswapV3Base.js' +import { VelodromeSlipstreamBaseProvider } from './VelodromeSlipstreamBase.js' + +// options for data fetching, such as pinning block number and memoize +export interface RainDataFetcherOptions extends DataFetcherOptions { + /** + * Set to true for ignoring cached pools data and fetch them regardless + */ + ignoreCache?: boolean +} + +export class RainDataFetcher extends DataFetcher { + initBlockNumber = -1n + eventsAbi: ParseAbiItem[] = [] + factories: string[] = [] + + // make constructor private, must use init() for instantiation + private constructor(chainId: ChainId, publicClient?: PublicClient) { + super(chainId, publicClient) + } + + /** + * Creates an instance of RainDataFetcher, constructor of this class should + * not be used, instead, use this method to create a new instance + * @param chainId - The chain id + * @param publicClient - (optional) The viem client + * @param liquidityProviders - (optional) List of liquidity providers, includes all if undefined + * @param initBlockNumber - (optional) Block height to initialize at + * @returns A new instance of RainDataFetcher + */ + static async init( + chainId: ChainId, + publicClient?: PublicClient, + liquidityProviders?: LiquidityProviders[], + initBlockNumber?: bigint, + ): Promise { + const dataFetcher = new RainDataFetcher(chainId, publicClient) + if (typeof initBlockNumber === 'bigint') { + if (initBlockNumber < 0n) + throw 'expected block number greater than equal zero' + dataFetcher.initBlockNumber = initBlockNumber + } else { + dataFetcher.initBlockNumber = + await dataFetcher.web3Client.getBlockNumber() + } + await dataFetcher.initProviders(liquidityProviders) + dataFetcher.startDataFetching(liquidityProviders) + return dataFetcher + } + + /** + * Initializes list of liquidity providers + * @param providers - (optional) List of liquidity providers, includes all if undefined + */ + async initProviders(providers?: LiquidityProviders[]) { + this.providers = [new NativeWrapProvider(this.chainId, this.web3Client)] + const allProviders = [ + AerodromeSlipstreamProvider, + AerodromeSlipstreamV2Provider, + AlienBaseV2Provider, + AlienBaseV3Provider, + ApeSwapProvider, + BakerySwapProvider, + BaseSwapProvider, + BaseSwapV3Provider, + BiswapProvider, + BladeSwapProvider, + BlastDEXProvider, + BlazeSwapProvider, + BSCSwapProvider, + CORExProvider, + CroDefiSwapProvider, + DackieSwapV2Provider, + DackieSwapV3Provider, + DfynProvider, + DovishV3Provider, + DyorV2Provider, + EddyFinanceProvider, + ElkProvider, + EnosysProvider, + FenixProvider, + GlyphV4Provider, + GravityFinanceProvider, + HoneySwapProvider, + HorizonProvider, + HydrexProvider, + HyperBlastProvider, + JetSwapProvider, + KimV4Provider, + KinetixV2Provider, + KinetixV3Provider, + KodiakV2Provider, + KodiakV3Provider, + KwikswapProvider, + LaserSwapV2Provider, + LynexV1Provider, + LynexV2Provider, + MMFinanceProvider, + MonoswapV2Provider, + MonoswapV3Provider, + MSwapProvider, + NetSwapProvider, + NileV3Provider, + NineInchProvider, + PancakeSwapV2Provider, + PancakeSwapV3Provider, + PangolinProvider, + QuickSwapV2Provider, + QuickSwapV3Provider, + RingExchangeV2Provider, + RingExchangeV3Provider, + ScribeProvider, + ShibaSwapProvider, + SolarbeamProvider, + SparkDexV2Provider, + SparkDexV3Provider, + SparkDexV3_1Provider, + SpookySwapV2Provider, + SpookySwapV3Provider, + SquadSwapV2Provider, + SushiSwapV2Provider, + SushiSwapV3Provider, + SwapBlastProvider, + SwapsicleProvider, + ThrusterV2_1Provider, + ThrusterV2_3Provider, + ThrusterV3Provider, + TraderJoeProvider, + UbeSwapProvider, + UniswapV2Provider, + UniswapV3Provider, + VelodromeSlipstreamProvider, + VVSStandardProvider, + VVSFlawlessProvider, + WagmiProvider, + WigoswapProvider, + ZebraV2Provider, + ] + + const _pendings = [] + const _providers = [] + for (const p of allProviders) { + try { + const provider = new p(this.chainId, this.web3Client) + if ( + // If none passed, include all + !providers || + this._providerIsIncluded(provider.getType(), providers) + ) { + _pendings.push(provider.init(this.initBlockNumber)) + _providers?.push(provider) + } + } catch (_e: unknown) {} + } + + for (let i = 0; i < _pendings.length; i++) { + const provider = _providers[i]! + await _pendings[i]?.catch(() => { + console.warn(`Failed to initialize ${provider.getPoolProviderName()}`) + }) + if (provider.initialized) { + this.providers.push(provider) + + // gather unique instances of liquidity provider events abi + if (provider?.eventsAbi?.length) { + ;(provider.eventsAbi as any[]).forEach((abi) => { + const sig = toEventSignature(abi) + if ( + this.eventsAbi.every((v) => toEventSignature(v as any) !== sig) + ) { + this.eventsAbi.push(abi) + } + }) + } + // gather factory addresses + if ( + provider instanceof UniswapV2BaseProvider || + provider instanceof UniswapV3BaseProvider + ) { + const factory = + provider.factory[ + this.chainId as keyof typeof provider.factory + ]!.toLowerCase() + if (!this.factories.includes(factory)) { + this.factories.push(factory) + } + } + } + } + } + + /** + * Updates the pools data of all the liquidity providers until the given block number + * and returns true if there was a new pool deployed and false otherwise + * @param untilBlock - (optional) The block number to update to, if left undefined, + * pools data will be updated to latest block number + * @returns true if a new pool has been created during the update process, else false + */ + async updatePools(untilBlock?: bigint): Promise { + let fromBlock = -1n + const poolAddresses: string[] = [] + const addresses: string[] = [...this.factories] + if (typeof untilBlock !== 'bigint') { + untilBlock = await this.web3Client.getBlockNumber() + } + + // gather all provider pools addresses + this.providers.forEach((provider: any) => { + if ( + provider instanceof UniswapV2BaseProvider || + provider instanceof UniswapV3BaseProvider + ) { + const pools = provider.pools + pools.forEach((pool, address) => { + poolAddresses.push(address) + if (fromBlock === -1n) { + fromBlock = pool.blockNumber + } + if (pool.blockNumber < fromBlock) { + fromBlock = pool.blockNumber + } + }) + + // slipstream has swapFeeModule address to be collected as well + if (provider instanceof VelodromeSlipstreamBaseProvider) { + const swapFeeModule = + provider.swapFeeModule[ + this.chainId as keyof typeof provider.swapFeeModule + ]!.toLowerCase() + addresses.push(swapFeeModule) + } + } + }) + if (fromBlock === -1n) return false + if (fromBlock === untilBlock) return false + if (fromBlock > untilBlock) { + // throw [ + // 'pools data are cached at higher block height than the requested block height', + // 'if you wish to get pools data at your requested block height', + // 'consider calling fetchPoolsForToken() with "ignoreCache" option', + // 'so that pools data can fetched for lower block height than what they are currently cached at', + // `pools block height: ${fromBlock}`, + // `requested block height: ${untilBlock}`, + // ].join(', ') + return false; + } + if (!poolAddresses.length) return false + addresses.push(...poolAddresses) + + // get logs in slices of 5 blocks to follow paging instructions from standard evm rpc specs + let fromBlockSlice = fromBlock + const logsPromises = [] + const blockNumberSlices = [] + while (fromBlockSlice < untilBlock) { + let toBlock = untilBlock + 1n + if (fromBlockSlice + 5n < untilBlock) { + toBlock = fromBlockSlice + 5n + } + blockNumberSlices.push(toBlock) + logsPromises.push( + this.web3Client.getLogs({ + events: this.eventsAbi, + address: addresses as `0x${string}`[], + fromBlock: fromBlockSlice, + toBlock: toBlock - 1n, + }), + ) + fromBlockSlice += 5n + } + + // await logs and sort them from earliest block to latest + const logsResults = await Promise.allSettled(logsPromises) + const logs: Awaited< + ReturnType< + typeof this.web3Client.getLogs< + undefined, + ParseAbiItem[], + undefined, + bigint, + bigint + > + > + > = [] + for (let i = 0; i < logsResults.length; i++) { + const res = logsResults[i] + if (res && res.status === 'fulfilled') { + logs.push(...res.value) + if (typeof blockNumberSlices[i] === 'bigint') { + untilBlock = blockNumberSlices[i] + } + } else { + break // if any one of the logs request fails, break out of the loop to avoid missing logs + } + } + logs.sort((a, b) => { + const diff = a.blockNumber - b.blockNumber + if (diff === 0n) { + const txDiff = a.transactionIndex - b.transactionIndex + if (txDiff === 0) { + return a.logIndex - b.logIndex + } else { + return txDiff + } + } else { + return Number(diff) + } + }) + + // process each log for each provider + let isNewPoolCreated = false + logs.forEach((log) => { + this.providers.forEach((p) => { + if (p.processLog(log)) isNewPoolCreated = true + }) + }) + const results = await Promise.allSettled( + this.providers.map((p) => p.afterProcessLog(untilBlock!)), + ) + results.forEach((res, i) => { + if (res.status === 'fulfilled') { + const provider = this.providers[i] + if ( + provider instanceof UniswapV2BaseProvider || + provider instanceof UniswapV3BaseProvider + ) { + provider.pools.forEach((pool) => { + pool.blockNumber = untilBlock! + }) + } + } + }) + return isNewPoolCreated + } + + /** + * Resets this instance's liquidity providers cached pools data + */ + reset() { + this.providers.forEach((provider) => { + if ( + provider instanceof UniswapV2BaseProvider || + provider instanceof UniswapV3BaseProvider + ) { + provider.reset() + } + }) + } + + /** + * Get route and poolcode map for the given tokens and amount + * @param chainId - The network chain id + * @param fromToken - The from token + * @param toToken - The to token + * @param amountIn - The sell amount, of fromToken + * @param gasPrice - Gas price + * @param update - (optional) Whether or not pool should be updated before finding route, default is false + * @param options - (optional) options for fetching new pools data + * @param lps - (optional) List of liquidity providers, includes all if undefined + * @param poolFilter - (optional) A function to filter pools + * @param routeType - (optional) single (default) picks the best route with no breadth, multi + * picks the best route with breadth, set undefined for picking the better of the two + */ + async findBestRoute( + chainId: ChainId, + fromToken: Type, + toToken: Type, + amountIn: bigint, + gasPrice: bigint, + update = false, + options?: RainDataFetcherOptions, + lps?: LiquidityProviders[], + poolFilter?: PoolFilter, + routeType: 'single' | 'multi' = 'single', + ): Promise<{ + /** The route */ + route: MultiRoute + /** + * The PoolCode map, which is a map of all available pools + * with their details for the given token pair to route among + */ + pcMap: Map + }> { + const opts = { ...options } + if (typeof opts.blockNumber !== 'bigint') { + opts.blockNumber = await this.web3Client.getBlockNumber() + } + if (typeof opts.ignoreCache !== 'boolean') { + opts.ignoreCache = false + } + + if (update) await this.updatePools(opts.blockNumber) + await this.fetchPoolsForToken(fromToken, toToken, undefined, opts) + + const pcMap = this.getCurrentPoolCodeMap(fromToken, toToken) + const route = Router.findBestRoute( + pcMap, + chainId, + fromToken, + amountIn, + toToken, + Number(gasPrice), + lps, + poolFilter, + undefined, + routeType, + ) + return { pcMap: pcMap, route } + } + + static override onChain(chainId: ChainId): RainDataFetcher { + return new RainDataFetcher(chainId) + } + + override startDataFetching(_providers?: LiquidityProviders[]) { + this.providers.forEach((p) => p.startFetchPoolsData()) + this.stopDataFetching() + } + + override async fetchPoolsForToken( + currency0: Type, + currency1: Type, + excludePools?: Set, + options?: RainDataFetcherOptions, + ): Promise { + const opts = { ...options } + if (typeof opts.blockNumber !== 'bigint') { + opts.blockNumber = await this.web3Client.getBlockNumber() + } + if (typeof opts.ignoreCache !== 'boolean') { + opts.ignoreCache = false + } + await super.fetchPoolsForToken(currency0, currency1, excludePools, opts) + } +} diff --git a/packages/sushi/src/router/rain/UniswapV2Base.ts b/packages/sushi/src/router/rain/UniswapV2Base.ts new file mode 100644 index 0000000000..1a38d0d093 --- /dev/null +++ b/packages/sushi/src/router/rain/UniswapV2Base.ts @@ -0,0 +1,204 @@ +import { Log, parseAbiItem, parseEventLogs } from 'viem' +import { Token } from '../../currency/index.js' +import { ConstantProductRPool, RToken } from '../../tines/index.js' +import { + StaticPool, + UniswapV2BaseProvider as _UniswapV2BaseProvider, +} from '../liquidity-providers/UniswapV2Base.js' +import { ConstantProductPoolCode, type PoolCode } from '../pool-codes/index.js' +import { RainDataFetcherOptions } from './RainDataFetcher.js' + +// extends v2 static pool +export interface RainV2Pool extends StaticPool { + reserve0: bigint + reserve1: bigint + blockNumber: bigint +} + +export const UniV2EventsAbi = [ + parseAbiItem('event Sync(uint112 reserve0, uint112 reserve1)'), + parseAbiItem( + 'event PairCreated(address indexed token0, address indexed token1, address pair, uint)', + ), +] + +export abstract class UniswapV2BaseProvider extends _UniswapV2BaseProvider { + nullPools: Map = new Map() + pools: Map = new Map() + eventsAbi = UniV2EventsAbi + + override async getOnDemandPools( + t0: Token, + t1: Token, + excludePools?: Set, + options?: RainDataFetcherOptions, + ): Promise { + let pools = this.getStaticPools(t0, t1) + if (excludePools) + pools = (pools as RainV2Pool[]).filter( + (p) => !excludePools.has(p.address), + ) + + if (pools.length === 0) { + return + } + + this.poolsByTrade.set( + this.getTradeId(t0, t1), + pools.map((pool) => pool.address.toLowerCase() as `0x${string}`), + ) + + // filter out cached pools + // this ensures backward compatibility for original DataFetcher + if (typeof options?.ignoreCache === 'boolean' && !options.ignoreCache) { + pools = this.filterCachedPools(pools as StaticPool[]) + } + if (pools.length === 0) return + + const poolCodesToCreate = pools.map( + (pool) => + ({ + ...pool, + blockNumber: options?.blockNumber ?? 0n, + }) as RainV2Pool, + ) + if (!poolCodesToCreate.length) return + + const reserves = await this.getReserves( + poolCodesToCreate.map((v) => v.address), + options, + ) + this.setPool(poolCodesToCreate, reserves) + } + + override getCurrentPoolList(t0: Token, t1: Token): PoolCode[] { + const tradeId = this.getTradeId(t0, t1) + const poolsByTrade = this.poolsByTrade.get(tradeId) ?? [] + const onDemandPoolCodes = poolsByTrade + ? Array.from(this.pools) + .filter(([poolAddress]) => + poolsByTrade.includes(poolAddress as `0x${string}`), + ) + .map(([, pool]) => { + const rPool = new ConstantProductRPool( + pool.address, + pool.token0 as RToken, + pool.token1 as RToken, + 'fee' in pool ? pool.fee : this.fee, + pool.reserve0, + pool.reserve1, + ) + return new ConstantProductPoolCode( + rPool, + this.getType(), + this.getPoolProviderName(), + ) + }) + : [] + + return [...this.topPools.values(), onDemandPoolCodes].flat() + } + + override processLog(log: Log): boolean { + const result = this.handleFactoryEvents(log) + this.handlePoolEvents(log) + return result + } + + /** + * Handles factory events and updates the cache with the results + */ + handleFactoryEvents(log: Log): boolean { + const factory = + this.factory[this.chainId as keyof typeof this.factory]!.toLowerCase() + const logAddress = log.address.toLowerCase() + if (logAddress === factory) { + try { + const event = parseEventLogs({ + logs: [log], + abi: this.eventsAbi, + eventName: 'PairCreated', + })[0]! + return this.nullPools.delete(event.args[2].toLowerCase()) + } catch {} + } + return false + } + + /** + * Handles pool events and updates the pool cache with the results + */ + handlePoolEvents(log: Log) { + const logAddress = log.address.toLowerCase() + const pool = this.pools.get(logAddress as `0x${string}`) + if (pool) { + if (log.blockNumber! >= pool.blockNumber) { + try { + const event = parseEventLogs({ + logs: [log], + abi: this.eventsAbi, + eventName: 'Sync', + })[0]! + pool.blockNumber = log.blockNumber! + pool.reserve0 = event.args.reserve0 + pool.reserve1 = event.args.reserve1 + } catch {} + } + } + } + + /** + * Updates reserves of the given pool in the cache + */ + setPool(poolCodesToCreate: RainV2Pool[], reserves: any[]) { + poolCodesToCreate.forEach((pool, i) => { + const poolAddress = pool.address.toLowerCase() + const res0 = reserves?.[i]?.result?.[0] + const res1 = reserves?.[i]?.result?.[1] + + if (res0 !== undefined && res1 !== undefined) { + this.pools.set(poolAddress, { + ...pool, + reserve0: res0, + reserve1: res1, + }) + } else { + this.handleNullPool(poolAddress) + } + }) + } + + /** + * Caches non existent pools + */ + handleNullPool(poolAddress: string) { + const v = this.nullPools.get(poolAddress) + if (v) { + this.nullPools.set(poolAddress, v + 1) + } else { + this.nullPools.set(poolAddress, 1) + } + } + + /** + * Filters out already cached pools from the given list + */ + filterCachedPools(pools: StaticPool[]) { + return pools.filter((pool) => { + const poolAddress = pool.address.toLowerCase() + if (this.pools.has(poolAddress)) return false + const nullPool = this.nullPools.get(poolAddress) + if (typeof nullPool === 'number' && nullPool > 1) return false + return true + }) + } + + /** + * Resets the cache + */ + reset() { + this.pools.clear() + this.poolsByTrade.clear() + this.nullPools.clear() + } +} diff --git a/packages/sushi/src/router/rain/UniswapV3Base.ts b/packages/sushi/src/router/rain/UniswapV3Base.ts new file mode 100644 index 0000000000..1a08c08441 --- /dev/null +++ b/packages/sushi/src/router/rain/UniswapV3Base.ts @@ -0,0 +1,777 @@ +import { Address, Log, parseAbiItem, parseEventLogs } from 'viem' +import { erc20Abi, slot0Abi, tickLensAbi } from '../../abi/index.js' +import { Token } from '../../currency/index.js' +import { CLTick, RToken, UniV3Pool } from '../../tines/index.js' +import { + NUMBER_OF_SURROUNDING_TICKS, + PoolFilter, + StaticPoolUniV3, + UniswapV3BaseProvider as _UniswapV3BaseProvider, + V3Pool, + bitmapIndex, +} from '../liquidity-providers/UniswapV3Base.js' +import { type PoolCode, UniV3PoolCode } from '../pool-codes/index.js' +import { RainDataFetcherOptions } from './RainDataFetcher.js' + +// extends V3Pool from UniswapV3Base +export interface RainV3Pool extends V3Pool { + tickSpacing: number + ticks: Map + reserve0: bigint + reserve1: bigint + liquidity: bigint + blockNumber: bigint +} + +export const tickSpacingAbi = [ + { + inputs: [], + name: 'tickSpacing', + outputs: [{ internalType: 'int24', name: '', type: 'int24' }], + stateMutability: 'view', + type: 'function', + }, +] as const + +export const UniV3EventsAbi = [ + parseAbiItem( + 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)', + ), + parseAbiItem( + 'event Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)', + ), + parseAbiItem( + 'event Collect(address indexed owner, address recipient, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount0, uint128 amount1)', + ), + parseAbiItem( + 'event Burn(address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)', + ), + parseAbiItem( + 'event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1)', + ), + parseAbiItem( + 'event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1)', + ), + parseAbiItem( + 'event PoolCreated(address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool)', + ), +] + +export abstract class UniswapV3BaseProvider extends _UniswapV3BaseProvider { + pools: Map = new Map() + nullPools: Map = new Map() + eventsAbi = UniV3EventsAbi + newTicksQueue: [RainV3Pool, number[]][] = [] + + override getActiveTick = (tickCurrent: number, tickSpacing?: number) => + typeof tickCurrent === 'number' && typeof tickSpacing === 'number' + ? Math.floor(tickCurrent / tickSpacing) * tickSpacing + : undefined + + override async fetchPoolData( + t0: Token, + t1: Token, + excludePools?: Set | PoolFilter, + options?: RainDataFetcherOptions, + ): Promise { + let staticPools = this.getStaticPools(t0, t1) + if (excludePools) + staticPools = staticPools.filter((p) => !excludePools.has(p.address)) + + const tradeId = this.getTradeId(t0, t1) + if (!this.poolsByTrade.has(tradeId)) + this.poolsByTrade.set( + tradeId, + staticPools.map((pool) => pool.address.toLowerCase()), + ) + + // filter out cached pools + // this ensures backward compatibility for original DataFetcher + if (typeof options?.ignoreCache === 'boolean' && !options.ignoreCache) { + staticPools = this.filterCachedPools(staticPools) + } + if (staticPools.length === 0) return [] + + const slot0 = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: staticPools.map( + (pool) => + ({ + address: pool.address as Address, + chainId: this.chainId, + abi: slot0Abi, + functionName: 'slot0', + }) as const, + ), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + const existingPools: RainV3Pool[] = [] + staticPools.forEach((pool, i) => { + const poolAddress = pool.address.toLowerCase() + if (slot0 === undefined || !slot0[i]) { + this.handleNullPool(poolAddress) + return + } + const sqrtPriceX96 = slot0[i]!.result?.[0] + const tick = slot0[i]!.result?.[1] + if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number') { + this.handleNullPool(poolAddress) + return + } + const tickSpacing = this.TICK_SPACINGS[pool.fee]! + const activeTick = this.getActiveTick(tick, tickSpacing) + if (typeof activeTick !== 'number') { + this.handleNullPool(poolAddress) + return + } + existingPools.push({ + ...pool, + sqrtPriceX96, + activeTick, + tickSpacing, + ticks: new Map(), + reserve0: 0n, + reserve1: 0n, + liquidity: 0n, + blockNumber: options?.blockNumber ?? 0n, + tick, + }) + }) + + return existingPools + } + + override getIndexes(existingPools: RainV3Pool[]): [number[], number[]] { + const minIndexes = existingPools.map((pool) => + bitmapIndex( + pool.activeTick - NUMBER_OF_SURROUNDING_TICKS, + pool.tickSpacing, + ), + ) + const maxIndexes = existingPools.map((pool) => + bitmapIndex( + pool.activeTick + NUMBER_OF_SURROUNDING_TICKS, + pool.tickSpacing, + ), + ) + return [minIndexes, maxIndexes] + } + + override async fetchPoolsForToken( + t0: Token, + t1: Token, + excludePools?: Set | PoolFilter, + options?: RainDataFetcherOptions, + ): Promise { + const existingPools = await this.fetchPoolData( + t0, + t1, + excludePools, + options, + ) + if (existingPools.length === 0) return + + const [liquidity, reserves, ticks] = await Promise.all([ + this.getLiquidity(existingPools, options), + this.getReserves(existingPools, options), + this.getTicks(existingPools, options), + ]) + existingPools.forEach((pool, i) => { + if ( + liquidity === undefined || + reserves === undefined || + ticks === undefined + ) + return + if ( + liquidity[i] === undefined || + reserves[i] === undefined || + ticks[i] === undefined + ) + return + this.pools.set(pool.address.toLowerCase(), { + ...pool, + reserve0: reserves[i]![0], + reserve1: reserves[i]![1], + liquidity: liquidity[i]!, + ticks: ticks[i]!, + }) + }) + } + + override getCurrentPoolList(t0: Token, t1: Token): PoolCode[] { + const tradeId = this.getTradeId(t0, t1) + const poolsByTrade = this.poolsByTrade.get(tradeId) ?? [] + return Array.from(this.pools.values()) + .filter((pool) => poolsByTrade.includes(pool.address.toLowerCase())) + .map((pool) => { + const v3Pool = new UniV3Pool( + pool.address, + pool.token0 as RToken, + pool.token1 as RToken, + pool.fee / 1_000_000, + pool.reserve0, + pool.reserve1, + pool.activeTick, + pool.liquidity, + pool.sqrtPriceX96, + this.getMaxTickDiapason(pool.activeTick, pool), + undefined, + pool.tick, + ) + + return new UniV3PoolCode( + v3Pool, + this.getType(), + this.getPoolProviderName(), + ) + }) + } + + override processLog(log: Log): boolean { + const result = this.handleFactoryEvents(log) + this.handlePoolEvents(log) + return result + } + + override async afterProcessLog(untilBlock: bigint) { + const newTicksQueue = [...this.newTicksQueue.splice(0)] + if (newTicksQueue.length) { + const newTicks = await this.getTicksInner(newTicksQueue, { + blockNumber: untilBlock, + }) + if (newTicks) { + newTicksQueue.forEach(([pool], i) => { + newTicks?.[i]?.forEach((newTick, index) => { + pool.ticks.set(index, newTick) + }) + }) + } else { + // if unsuccessfull to get new ticks, put them back on queue for next try + this.newTicksQueue.push(...newTicksQueue) + } + } + } + + /** + * Fetches reserves of the given list of pools + */ + async getReserves( + existingPools: RainV3Pool[], + options?: RainDataFetcherOptions, + ): Promise<([bigint, bigint] | undefined)[]> { + const results = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: existingPools.flatMap( + (pool) => + [ + { + chainId: this.chainId, + address: pool.token0.wrapped.address as Address, + args: [pool.address as Address], + abi: erc20Abi, + functionName: 'balanceOf', + }, + { + chainId: this.chainId, + address: pool.token1.wrapped.address as Address, + args: [pool.address as Address], + abi: erc20Abi, + functionName: 'balanceOf', + }, + ] as const, + ), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return Array.from({ length: existingPools.length }, () => undefined) + }) + + const reserves = [] + for (let i = 0; i < results.length; i += 2) { + const res0 = results?.[i]?.result + const res1 = results?.[i + 1]?.result + if (typeof res0 === 'bigint' && typeof res1 === 'bigint') { + reserves.push([res0, res1] as [bigint, bigint]) + } else { + reserves.push(undefined) + } + } + return reserves + } + + /** + * Fetches liquidity of the given list of pools + */ + async getLiquidity( + existingPools: RainV3Pool[], + options?: RainDataFetcherOptions, + ): Promise<(bigint | undefined)[]> { + const results = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: existingPools.map( + (pool) => + ({ + chainId: this.chainId, + address: pool.address as Address, + abi: [ + { + inputs: [], + name: 'liquidity', + outputs: [ + { internalType: 'uint128', name: '', type: 'uint128' }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'liquidity', + }) as const, + ), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return Array.from({ length: existingPools.length }, () => undefined) + }) + + const liquidities = [] + for (let i = 0; i < results.length; i++) { + const liquidity = results?.[i]?.result + if (typeof liquidity === 'bigint') { + liquidities.push(liquidity) + } else { + liquidities.push(undefined) + } + } + return liquidities + } + + /** + * Fetches ticks capped at pool boundries of the given list of pools + */ + async getTicks( + existingPools: RainV3Pool[], + options?: RainDataFetcherOptions, + ): Promise[] | undefined> { + const [minIndexes, maxIndexes] = this.getIndexes(existingPools) + const wordList = existingPools.map((pool, i) => { + const minIndex = minIndexes[i]! + const maxIndex = maxIndexes[i]! + + return [ + pool, + Array.from({ length: maxIndex - minIndex + 1 }, (_, i) => minIndex + i), + ] as [RainV3Pool, number[]] + }) + return await this.getTicksInner(wordList, options) + } + + /** + * Fetches ticks of the given list of pools + */ + async getTicksInner( + existingPools: [RainV3Pool, number[]][], + options?: RainDataFetcherOptions, + ): Promise[] | undefined> { + const wordList = existingPools.flatMap(([pool, words], i) => { + return words.flatMap((j) => ({ + chainId: this.chainId, + address: this.tickLens[ + this.chainId as keyof typeof this.tickLens + ] as Address, + args: [pool.address, j] as const, + abi: tickLensAbi, + functionName: 'getPopulatedTicksInWord' as const, + index: [i, j], + })) + }) + + const tickResults = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + contracts: wordList, + blockNumber: options?.blockNumber, + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + if (!tickResults) return undefined + + const poolTicks: Map[] = [] + tickResults.forEach((t, i) => { + const index = wordList[i]!.index[0]! + const wordIndex = wordList[i]!.index[1]! + if (poolTicks[index] === undefined) poolTicks[index] = new Map() + poolTicks[index]!.set( + wordIndex, + (t?.result || []) + .map((tick) => ({ + index: tick.tick, + DLiquidity: tick.liquidityNet, + })) + .sort((a, b) => a.index - b.index), + ) + }) + return poolTicks + } + + /** + * Fetches tick spacing of the given list of pools + */ + async getTickSpacing( + pools: StaticPoolUniV3[], + options?: RainDataFetcherOptions, + ) { + return await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3 + ?.address as Address, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: pools.map( + (pool) => + ({ + address: pool.address as Address, + chainId: this.chainId, + abi: tickSpacingAbi, + functionName: 'tickSpacing', + }) as const, + ), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + } + + /** + * Calculates and returns the list of current ticks for the given pool + */ + getMaxTickDiapason(tick: number, pool: RainV3Pool): CLTick[] { + const currentTickIndex = bitmapIndex(tick, pool.tickSpacing) + if (!pool.ticks.has(currentTickIndex)) return [] + let minIndex + let maxIndex + for (minIndex = currentTickIndex; pool.ticks.has(minIndex); --minIndex); + for (maxIndex = currentTickIndex + 1; pool.ticks.has(maxIndex); ++maxIndex); + if (maxIndex - minIndex <= 1) return [] + + let poolTicks: CLTick[] = [] + for (let i = minIndex + 1; i < maxIndex; ++i) + poolTicks = poolTicks.concat(pool.ticks.get(i)!) + + const lowerUnknownTick = + (minIndex + 1) * pool.tickSpacing * 256 - pool.tickSpacing + console.assert( + poolTicks.length === 0 || lowerUnknownTick < poolTicks[0]!.index, + 'Error 236: unexpected min tick index', + ) + poolTicks.unshift({ + index: lowerUnknownTick, + DLiquidity: 0n, + }) + const upperUnknownTick = maxIndex * pool.tickSpacing * 256 + console.assert( + poolTicks[poolTicks.length - 1]!.index < upperUnknownTick, + 'Error 244: unexpected max tick index', + ) + poolTicks.push({ + index: upperUnknownTick, + DLiquidity: 0n, + }) + + return poolTicks + } + + /** + * Handles factory events and updates the cache with the results + */ + handleFactoryEvents(log: Log): boolean { + const factory = + this.factory[this.chainId as keyof typeof this.factory]!.toLowerCase() + const logAddress = log.address.toLowerCase() + if (logAddress === factory) { + try { + const event = parseEventLogs({ + logs: [log], + abi: this.eventsAbi, + eventName: 'PoolCreated', + })[0]! + return this.nullPools.delete(event.args.pool.toLowerCase()) + } catch {} + } + return false + } + + /** + * Handles pool events and updates the pool cache with the results + */ + handlePoolEvents(log: Log) { + const logAddress = log.address.toLowerCase() + const pool = this.pools.get(logAddress) + if (pool) { + try { + const event = parseEventLogs({ logs: [log], abi: this.eventsAbi })[0]! + switch (event.eventName) { + case 'Mint': { + const { amount, amount0, amount1 } = event.args + const { tickLower, tickUpper } = event.args + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + const tick = pool.activeTick + if (tickLower <= tick && tick < tickUpper) + pool.liquidity += amount + } + if (amount1 !== undefined && amount0 !== undefined) { + pool.reserve0 += amount0 + pool.reserve1 += amount1 + } + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + this.addTick(tickLower, amount, pool) + this.addTick(tickUpper, -amount, pool) + } + } + break + } + case 'Burn': { + const { amount } = event.args + const { tickLower, tickUpper } = event.args + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + const tick = pool.activeTick + if (tickLower <= tick && tick < tickUpper) + pool.liquidity -= amount + } + if ( + tickLower !== undefined && + tickUpper !== undefined && + amount !== undefined + ) { + this.addTick(tickLower, -amount, pool) + this.addTick(tickUpper, amount, pool) + } + } + break + } + case 'Collect': + case 'CollectProtocol': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + const { amount0, amount1 } = event.args + if (amount0 !== undefined && amount1 !== undefined) { + pool.reserve0 -= amount0 + pool.reserve1 -= amount1 + } + } + break + } + case 'Flash': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + const { paid0, paid1 } = event.args + if (paid0 !== undefined && paid1 !== undefined) { + pool.reserve0 += paid0 + pool.reserve1 += paid1 + } + } + break + } + case 'Swap': { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + const { amount0, amount1, sqrtPriceX96, liquidity, tick } = + event.args + if (amount0 !== undefined && amount1 !== undefined) { + pool.reserve0 += amount0 + pool.reserve1 += amount1 + } + if (sqrtPriceX96 !== undefined) pool.sqrtPriceX96 = sqrtPriceX96 + if (liquidity !== undefined) pool.liquidity = liquidity + if (tick !== undefined) { + pool.tick = tick + pool.activeTick = + Math.floor(tick / pool.tickSpacing) * pool.tickSpacing + const newTicks = this.onPoolTickChange(pool.activeTick, pool) + const queue = this.newTicksQueue.find( + (v) => v[0].address === pool.address, + ) + if (queue) { + for (const t of newTicks) { + if (!queue[1].includes(t)) queue[1].push(t) + } + } else { + this.newTicksQueue.push([pool, newTicks]) + } + } + } + break + } + default: { + this.otherEventCases(log, event, pool) + } + } + } catch {} + } + } + + // for child classes if they have other events to handle such as AlgebraV1Base + otherEventCases(_log: Log, _event: Log, _pool: RainV3Pool) {} + + /** + * Adds a new tick to the given pool's tick list + */ + addTick(tick: number, amount: bigint, pool: RainV3Pool) { + const tickWord = bitmapIndex(tick, pool.tickSpacing) + const ticks = pool.ticks.get(tickWord) + if (ticks !== undefined) { + if (ticks.length === 0 || tick < ticks[0]!.index) { + ticks.unshift({ index: tick, DLiquidity: amount }) + return + } + if (tick === ticks[0]!.index) { + ticks[0]!.DLiquidity = ticks[0]!.DLiquidity + amount + if (ticks[0]!.DLiquidity === 0n) ticks.splice(0, 1) + return + } + + let start = 0 + let end = ticks.length + while (end - start > 1) { + const middle = Math.floor((start + end) / 2) + const index = ticks[middle]!.index + if (index < tick) start = middle + else if (index > tick) end = middle + else { + ticks[middle]!.DLiquidity = ticks[middle]!.DLiquidity + amount + if (ticks[middle]!.DLiquidity === 0n) ticks.splice(middle, 1) + return + } + } + ticks.splice(start + 1, 0, { index: tick, DLiquidity: amount }) + } + } + + /** + * Gets triggered if a pool's current tick get changed after processing event logs, + * this calculates the new tciks that need to be fetched from onchain which then + * takes place when afterProcessLog() is called + */ + onPoolTickChange(tick: number, pool: RainV3Pool): number[] { + const currentTickWord = bitmapIndex(tick, pool.tickSpacing) + const minWord = bitmapIndex( + tick - NUMBER_OF_SURROUNDING_TICKS, + pool.tickSpacing, + ) + const maxWord = bitmapIndex( + tick + NUMBER_OF_SURROUNDING_TICKS, + pool.tickSpacing, + ) + + const direction = currentTickWord - minWord <= maxWord - currentTickWord + const wordNumber = maxWord - minWord + const newTicks: number[] = [] + for (let i = wordNumber; i >= 0; --i) { + const wordIndex = currentTickWord + this.getJump(i, direction) + const wordState = pool.ticks.get(wordIndex) + if (wordState === undefined) newTicks.push(wordIndex) + } + return newTicks + } + + // if positiveFirst == true returns 0, 1, -1, 2, -2, 3, -3, ... + // if positiveFirst == false returns 0, -1, 1, -2, 2, -3, 3, ... + getJump(index: number, positiveFirst: boolean): number { + let res + if (index % 2 === 0) res = -index / 2 + else res = (index + 1) / 2 + return positiveFirst ? res : -res + } + + /** + * Caches non existent pools + */ + handleNullPool(poolAddress: string) { + const v = this.nullPools.get(poolAddress) + if (v) { + this.nullPools.set(poolAddress, v + 1) + } else { + this.nullPools.set(poolAddress, 1) + } + } + + /** + * Filters out already cached pools from the given list + */ + filterCachedPools(pools: StaticPoolUniV3[]) { + return pools.filter((pool) => { + const poolAddress = pool.address.toLowerCase() + if (this.pools.has(poolAddress)) return false + const nullPool = this.nullPools.get(poolAddress) + if (typeof nullPool === 'number' && nullPool > 1) return false + return true + }) + } + + /** + * Resets the cache + */ + reset() { + this.pools.clear() + this.poolsByTrade.clear() + this.nullPools.clear() + } +} diff --git a/packages/sushi/src/router/rain/VelodromeSlipstreamBase.ts b/packages/sushi/src/router/rain/VelodromeSlipstreamBase.ts new file mode 100644 index 0000000000..147c16c357 --- /dev/null +++ b/packages/sushi/src/router/rain/VelodromeSlipstreamBase.ts @@ -0,0 +1,666 @@ +import { + Address, + Hex, + Log, + PublicClient, + encodeAbiParameters, + getAddress, + keccak256, + parseAbiItem, + parseAbiParameters, + parseEventLogs, +} from 'viem' +import { ChainId } from '../../chain/index.js' +import { Token } from '../../currency/index.js' +import { getCurrencyCombinations } from '../get-currency-combinations.js' +import { + PoolFilter, + StaticPoolUniV3, +} from '../liquidity-providers/UniswapV3Base.js' +import { RainDataFetcherOptions } from './RainDataFetcher.js' +import { + RainV3Pool, + UniV3EventsAbi, + UniswapV3BaseProvider, +} from './UniswapV3Base.js' + +export const ZERO_FEE_INDICATOR = 420 + +export enum FeeType { + Default = 0, + Dynamic = 1, + Zero = 2, +} + +export interface StaticSlipstreamPool extends StaticPoolUniV3 { + tickSpacing: number + feeType: FeeType +} + +export interface SlipstreamPool extends RainV3Pool { + feeType: FeeType +} + +const feeAbi = [ + { + inputs: [], + name: 'fee', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function', + }, +] as const + +const slot0Abi = [ + { + inputs: [], + name: 'slot0', + outputs: [ + { internalType: 'uint160', name: 'sqrtPriceX96', type: 'uint160' }, + { internalType: 'int24', name: 'tick', type: 'int24' }, + { internalType: 'uint16', name: 'observationIndex', type: 'uint16' }, + { + internalType: 'uint16', + name: 'observationCardinality', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'observationCardinalityNext', + type: 'uint16', + }, + { internalType: 'bool', name: 'unlocked', type: 'bool' }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const + +export const customFeeAbi = [ + { + inputs: [{ internalType: 'address', name: '_pool', type: 'address' }], + name: 'customFee', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function', + }, +] as const + +const SlipstreamEventsAbi = [ + ...UniV3EventsAbi.slice(0, -1), // univ3 shared events except PoolCreated + parseAbiItem( + 'event PoolCreated(address indexed token0, address indexed token1, int24 indexed tickSpacing, address pool)', + ), + parseAbiItem( + 'event TickSpacingEnabled(int24 indexed tickSpacing, uint24 indexed fee)', + ), + parseAbiItem('event CustomFeeSet(address indexed pool, uint24 indexed fee)'), + parseAbiItem( + 'event SwapFeeModuleChanged(address indexed oldFeeModule, address indexed newFeeModule)', + ), +] + +export abstract class VelodromeSlipstreamBaseProvider extends UniswapV3BaseProvider { + readonly BASE_FEE = 100 + DEFAULT_TICK_SPACINGS = [1, 50, 100, 200, 2000] as const + tickSpacings: number[] = [...this.DEFAULT_TICK_SPACINGS] + + shouldResetFees = false + feeSpacingMap: Record = {} // fee to tick spacing map + spacingFeeMap: Record = {} // tick spacing to fee map + + // poolImplementation and swapFeeModule addresses, fetched at init() from + // factory since they can change over time and are not contract constants + poolImplementation: Record = {} + swapFeeModule: Record = {} + + override eventsAbi = SlipstreamEventsAbi as any + + constructor( + chainId: ChainId, + web3Client: PublicClient, + factory: Record, + tickLens: Record, + isTest = false, + ) { + super( + chainId, + web3Client, + factory, + { [chainId]: `0x${'0'.repeat(64)}` }, // dummy, since slipstream has no initCodeHash + tickLens, + isTest, + ) + } + + override async init(blockNumber?: bigint) { + if (!this.initialized) { + if (!this.poolImplementation[this.chainId]) { + const poolImplementation = await this.client + .readContract({ + address: this.factory[this.chainId as keyof typeof this.factory]!, + blockNumber, + abi: [ + { + inputs: [], + name: 'poolImplementation', + outputs: [ + { internalType: 'address', name: '', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + ] as const, + functionName: 'poolImplementation', + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: failed to get poolImplementation address, message: ${ + e.message + }`, + ) + return undefined + }) + if (!poolImplementation) return + this.poolImplementation[this.chainId] = poolImplementation + } + + if (!this.swapFeeModule[this.chainId]) { + const swapFeeModule = await this.client + .readContract({ + address: this.factory[this.chainId as keyof typeof this.factory]!, + blockNumber, + abi: [ + { + inputs: [], + name: 'swapFeeModule', + outputs: [ + { internalType: 'address', name: '', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + ] as const, + functionName: 'swapFeeModule', + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: failed to get swapFeeModule address, message: ${ + e.message + }`, + ) + return undefined + }) + if (!swapFeeModule) return + this.swapFeeModule[this.chainId] = swapFeeModule + } + + if (!this.tickSpacings) { + const tickSpacings = await this.client + .readContract({ + address: this.factory[this.chainId as keyof typeof this.factory]!, + blockNumber, + abi: [ + { + inputs: [], + name: 'tickSpacings', + outputs: [ + { internalType: 'int24[]', name: '', type: 'int24[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'tickSpacings', + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: failed to get tickSpacings, message: ${ + e.message + }`, + ) + return undefined + }) + this.tickSpacings = (tickSpacings ?? + this.DEFAULT_TICK_SPACINGS) as number[] + } + + if (!Object.values(this.feeSpacingMap).length) { + const fees = await this.client + .multicall({ + multicallAddress: + this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber, + contracts: this.tickSpacings.map((spacing) => ({ + address: this.factory[this.chainId as keyof typeof this.factory]!, + chainId: this.chainId, + abi: [ + { + inputs: [{ internalType: 'int24', name: '', type: 'int24' }], + name: 'tickSpacingToFee', + outputs: [ + { internalType: 'uint24', name: '', type: 'uint24' }, + ], + stateMutability: 'view', + type: 'function', + }, + ] as const, + functionName: 'tickSpacingToFee', + args: [spacing], + })), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed to get tickSpacingToFee, message: ${ + e.message + }`, + ) + return undefined + }) + if (!fees) return + for (let i = 0; i < this.tickSpacings.length; i++) { + const fee = fees?.[i]?.result + const tickSpacing = this.tickSpacings[i] + if (typeof fee === 'number' && typeof tickSpacing === 'number') { + this.feeSpacingMap[fee] = tickSpacing + this.spacingFeeMap[tickSpacing] = fee + } + } + } + this.initialized = true + } + } + + override async fetchPoolData( + t0: Token, + t1: Token, + excludePools?: Set | PoolFilter, + options?: RainDataFetcherOptions, + ): Promise { + await this.init(options?.blockNumber) + + let staticPools = this.getStaticPools(t0, t1) + if (excludePools) + staticPools = staticPools.filter((p) => !excludePools.has(p.address)) + + const tradeId = this.getTradeId(t0, t1) + if (!this.poolsByTrade.has(tradeId)) + this.poolsByTrade.set( + tradeId, + staticPools.map((pool) => pool.address.toLowerCase()), + ) + + // filter out cached pools + // this ensures backward compatibility for original DataFetcher + if (typeof options?.ignoreCache === 'boolean' && !options.ignoreCache) { + staticPools = this.filterCachedPools( + staticPools, + ) as StaticSlipstreamPool[] + } + if (staticPools.length === 0) return [] + + const slot0 = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: staticPools.map((pool) => ({ + address: pool.address, + chainId: this.chainId, + abi: slot0Abi, + functionName: 'slot0', + })), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + const feeTypes = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: staticPools.map((pool) => ({ + address: this.swapFeeModule[this.chainId]!, + chainId: this.chainId, + abi: customFeeAbi, + functionName: 'customFee', + args: [pool.address], + })), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + staticPools.forEach((pool, i) => { + const result = feeTypes?.[i]?.result + if (typeof result === 'number') { + if (result === 0) pool.feeType = FeeType.Default + else if (result === ZERO_FEE_INDICATOR) pool.feeType = FeeType.Zero + else pool.feeType = FeeType.Dynamic + } + }) + + // get pool fees for dynamic fee type pools + const poolFees = await this.client + .multicall({ + multicallAddress: this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: options?.blockNumber, + contracts: staticPools + .filter((pool) => pool.feeType === FeeType.Dynamic) + .map( + (pool) => + ({ + address: pool.address, + chainId: this.chainId, + abi: feeAbi, + functionName: 'fee', + }) as const, + ), + }) + .catch((e) => { + console.warn( + `${this.getLogPrefix()} - INIT: multicall failed, message: ${ + e.message + }`, + ) + return undefined + }) + + const existingPools: SlipstreamPool[] = [] + staticPools.forEach((pool, i) => { + const poolAddress = pool.address.toLowerCase() + if (slot0 === undefined || !slot0[i]) { + this.handleNullPool(poolAddress) + return + } + const sqrtPriceX96 = slot0[i]!.result?.[0] // price + const tick = slot0[i]!.result?.[1] // tick + if (!sqrtPriceX96 || sqrtPriceX96 === 0n || typeof tick !== 'number') { + this.handleNullPool(poolAddress) + return + } + const activeTick = Math.floor(tick / pool.tickSpacing) * pool.tickSpacing + if (typeof activeTick !== 'number') { + this.handleNullPool(poolAddress) + return + } + const fee = (() => { + if (pool.feeType === FeeType.Zero) { + return 0 + } else if (pool.feeType === FeeType.Default) { + return this.spacingFeeMap[pool.tickSpacing]! + } else if (pool.feeType === FeeType.Dynamic) { + const _fee = poolFees?.shift()?.result + if (typeof _fee === 'number') return _fee + else return undefined + } else { + return this.spacingFeeMap[pool.tickSpacing]! + } + })() + if (typeof fee !== 'number') { + this.handleNullPool(poolAddress) + return + } + + existingPools.push({ + ...pool, + fee, + sqrtPriceX96, + activeTick, + ticks: new Map(), + reserve0: 0n, + reserve1: 0n, + liquidity: 0n, + blockNumber: options?.blockNumber ?? 0n, + feeType: pool.feeType, + tick, + }) + }) + + return existingPools + } + + override handleFactoryEvents(log: Log): boolean { + const logAddress = log.address.toLowerCase() + const factory = + this.factory[this.chainId as keyof typeof this.factory]!.toLowerCase() + const swapFeeModule = + this.swapFeeModule[ + this.chainId as keyof typeof this.swapFeeModule + ]!.toLowerCase() + if (logAddress === factory || logAddress === swapFeeModule) { + try { + const event = parseEventLogs({ + logs: [log], + abi: SlipstreamEventsAbi, + })[0]! + switch (event.eventName) { + case 'PoolCreated': { + return this.nullPools.delete(event.args.pool.toLowerCase()) + } + case 'TickSpacingEnabled': { + // new tick spacing enabled + if (!this.tickSpacings.includes(event.args.tickSpacing)) { + this.tickSpacings.push(event.args.tickSpacing) + } + this.feeSpacingMap[event.args.fee] = event.args.tickSpacing + break + } + case 'CustomFeeSet': { + // pool fee update + const pool = this.pools.get( + event.args.pool.toLowerCase(), + ) as SlipstreamPool + if (pool) { + if (log.blockNumber! >= pool.blockNumber) { + pool.blockNumber = log.blockNumber! + if (event.args.fee === ZERO_FEE_INDICATOR) { + pool.fee = 0 + pool.feeType = FeeType.Zero + } else if (event.args.fee !== 0) { + pool.fee = event.args.fee + pool.feeType = FeeType.Dynamic + } else { + pool.fee = this.spacingFeeMap[pool.tickSpacing]! + pool.feeType = FeeType.Default + } + } + } + break + } + case 'SwapFeeModuleChanged': { + // factory swapFeeModule address changed + if ( + this.swapFeeModule[this.chainId]?.toLowerCase() !== + event.args.newFeeModule.toLowerCase() + ) { + // we need to reset the cached pools fees as they might + // have wrong fees after swapFeeModule address is changed + // PS: this event is very rare + this.swapFeeModule[this.chainId] = event.args.newFeeModule + this.shouldResetFees = true + } + break + } + default: + } + } catch {} + } + return false + } + + override async afterProcessLog(untilBlock: bigint) { + let pools: SlipstreamPool[] = [] + let shouldResetFees = false + if (this.shouldResetFees) { + shouldResetFees = true + this.shouldResetFees = false + } + this.pools.forEach((pool) => { + if (shouldResetFees) { + pools.push(pool as SlipstreamPool) + } else { + if ((pool as SlipstreamPool).feeType === FeeType.Dynamic) { + pools.push(pool as SlipstreamPool) + } + } + }) + + let [_, poolFees] = await Promise.allSettled([ + // base after log process + super.afterProcessLog(untilBlock), + // get pool new fees + shouldResetFees + ? this.client.multicall({ + multicallAddress: + this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: untilBlock, + contracts: pools.map((pool) => ({ + address: this.swapFeeModule[this.chainId]!, + chainId: this.chainId, + abi: customFeeAbi, + functionName: 'customFee', + args: [pool.address], + })), + }) + : this.client.multicall({ + multicallAddress: + this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: untilBlock, + contracts: pools.map((pool) => ({ + address: pool.address, + chainId: this.chainId, + abi: feeAbi, + functionName: 'fee', + })), + }), + ]) + + // handle pool fees + if (poolFees.status === 'fulfilled') { + if (shouldResetFees) { + const newDynamicPools: SlipstreamPool[] = [] + pools.forEach((pool, i) => { + const result = (poolFees as any).value?.[i]?.result + if (typeof result === 'number') { + if (result === 0) pool.feeType = FeeType.Default + else if (result === ZERO_FEE_INDICATOR) pool.feeType = FeeType.Zero + else { + pool.feeType = FeeType.Dynamic + newDynamicPools.push(pool) + } + } + }) + pools = newDynamicPools + ;[poolFees] = await Promise.allSettled([ + this.client.multicall({ + multicallAddress: + this.client.chain?.contracts?.multicall3?.address!, + allowFailure: true, + blockNumber: untilBlock, + contracts: pools.map((pool) => ({ + address: pool.address, + chainId: this.chainId, + abi: feeAbi, + functionName: 'fee', + })), + }), + ]) + } + } + if (poolFees.status === 'fulfilled') { + pools.forEach((pool, i) => { + const fee = (poolFees as any).value?.[i]?.result + if (typeof fee === 'number') pool.fee = fee + }) + } else { + // if failed to update pool fees, we'll try again on next update + this.shouldResetFees = true + } + } + + override getStaticPools(t1: Token, t2: Token): StaticSlipstreamPool[] { + const allCombinations = getCurrencyCombinations(this.chainId, t1, t2) + const currencyCombinations: [Token, Token, number][] = [] + allCombinations.forEach(([currencyA, currencyB]) => { + if (currencyA && currencyB) { + const tokenA = currencyA.wrapped + const tokenB = currencyB.wrapped + if (tokenA.equals(tokenB)) return + const tokens = tokenA.sortsBefore(tokenB) + ? [tokenA, tokenB] + : [tokenB, tokenA] + currencyCombinations.push( + ...this.tickSpacings.map( + (t) => [...tokens, t] as [Token, Token, number], + ), + ) + } + }) + return currencyCombinations.map(([currencyA, currencyB, tickSpacing]) => ({ + address: this.getSlipstreamPoolAddress( + this.factory[this.chainId as keyof typeof this.factory]!, + currencyA.wrapped, + currencyB.wrapped, + tickSpacing, + ), + token0: currencyA, + token1: currencyB, + fee: this.BASE_FEE, + tickSpacing, + feeType: FeeType.Default, + })) + } + + // algebra doesnt have the fee/ticks setup the same way univ3 has + override async ensureFeeAndTicks(): Promise { + return true + } + + getSlipstreamPoolAddress( + factory: Address, + tokenA: Token, + tokenB: Token, + tickSpacing: number, + ): Address { + const [token0, token1] = tokenA.sortsBefore(tokenB) + ? [tokenA, tokenB] + : [tokenB, tokenA] + const constructorArgumentsEncoded = encodeAbiParameters( + parseAbiParameters('address, address, int24'), + [token0.address, token1.address, tickSpacing], + ) + const initCode = + `0x3d602d80600a3d3981f3363d3d373d3d3d363d73${this.poolImplementation[ + this.chainId as keyof typeof this.poolImplementation + ]!.replace('0x', '')}5af43d82803e903d91602b57fd5bf3` as Hex + const initCodeHash = keccak256(initCode) + + const create2Inputs = [ + '0xff', + factory, + // salt + keccak256(constructorArgumentsEncoded), + // init code hash + initCodeHash, + ] + const sanitizedInputs = `0x${create2Inputs + .map((i) => i.slice(2)) + .join('')}` as Hex + return getAddress(`0x${keccak256(sanitizedInputs).slice(-40)}`) + } +} diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index 4aca2ad35e..3ab93bac32 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -154,6 +154,8 @@ export class Router { gasPrice: number, providers?: LiquidityProviders[], // all providers if undefined poolFilter?: PoolFilter, + flows?: number | number[], + pickRoute?: 'single' | 'multi', ): MultiRoute { const networks: NetworkInfo[] = [ { @@ -195,6 +197,8 @@ export class Router { pools, networks, gasPrice, + flows, + pickRoute, ) return { diff --git a/packages/sushi/src/router/scripts/check.ts b/packages/sushi/src/router/scripts/check.ts index 607d0b563a..75c71a9995 100644 --- a/packages/sushi/src/router/scripts/check.ts +++ b/packages/sushi/src/router/scripts/check.ts @@ -151,7 +151,7 @@ function getProtocol(lp: LiquidityProviders, chainId: ChainId) { switch (lp) { case LiquidityProviders.SushiSwapV2: return `${prefix}SUSHISWAP` - case LiquidityProviders.QuickSwap: + case LiquidityProviders.QuickSwapV2: return `${prefix}QUICKSWAP` case LiquidityProviders.Trident: return `${prefix}TRIDENT` diff --git a/packages/sushi/src/router/static-pool-fetcher/Trident.ts b/packages/sushi/src/router/static-pool-fetcher/Trident.ts index ecd3038b7e..98b2471d95 100644 --- a/packages/sushi/src/router/static-pool-fetcher/Trident.ts +++ b/packages/sushi/src/router/static-pool-fetcher/Trident.ts @@ -11,6 +11,7 @@ import { TridentChainId, } from '../../config/index.js' import { Currency, Token } from '../../currency/index.js' +import { DataFetcherOptions } from '../data-fetcher.js' import { getCurrencyCombinations } from '../get-currency-combinations.js' export interface TridentStaticPool { @@ -27,10 +28,11 @@ export class TridentStaticPoolFetcher { chainId: ChainId, t1: Token, t2: Token, + options?: DataFetcherOptions, ): Promise<[TridentStaticPool[], TridentStaticPool[]]> { const pools = await Promise.all([ - this.getPools(client, chainId, t1, t2, 'CONSTANT_PRODUCT_POOL'), - this.getPools(client, chainId, t1, t2, 'STABLE_POOL'), + this.getPools(client, chainId, t1, t2, 'CONSTANT_PRODUCT_POOL', options), + this.getPools(client, chainId, t1, t2, 'STABLE_POOL', options), ]) return pools @@ -42,6 +44,7 @@ export class TridentStaticPoolFetcher { t1: Token, t2: Token, type: 'STABLE_POOL' | 'CONSTANT_PRODUCT_POOL', + options?: DataFetcherOptions, ) { const currencies = getCurrencyCombinations(chainId, t1, t2) @@ -62,6 +65,7 @@ export class TridentStaticPoolFetcher { const callStatePoolsCount = await client.multicall({ multicallAddress: client.chain?.contracts?.multicall3?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: _pairsUniqueAddr.map( (el) => ({ @@ -107,6 +111,7 @@ export class TridentStaticPoolFetcher { const callStatePools = await client.multicall({ multicallAddress: client.chain?.contracts?.multicall3?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: callStatePoolsCountProcessed.map( (args) => ({ @@ -137,6 +142,7 @@ export class TridentStaticPoolFetcher { const fees = await client.multicall({ multicallAddress: client.chain?.contracts?.multicall3?.address as Address, allowFailure: true, + blockNumber: options?.blockNumber, contracts: poolsAddresses.map( (address) => ({ @@ -147,6 +153,7 @@ export class TridentStaticPoolFetcher { }) as const, ), }) + const results: TridentStaticPool[] = [] pools.forEach((p, i) => { diff --git a/packages/sushi/src/router/timeout.test.ts b/packages/sushi/src/router/timeout.test.ts new file mode 100644 index 0000000000..611eb6d650 --- /dev/null +++ b/packages/sushi/src/router/timeout.test.ts @@ -0,0 +1,33 @@ +import { describe, it } from 'vitest' +import { promiseTimeout } from './timeout.js' + +const sleep = async (ms: number, msg = '') => { + let _timeoutReference + return new Promise((resolve) => { + _timeoutReference = setTimeout(() => resolve(msg), ms) + return _timeoutReference + }).finally(() => clearTimeout(_timeoutReference)) +} + +describe('Promise Timeout', async () => { + it('should timeout', async () => { + const mainPromise = sleep(1000) + await promiseTimeout(mainPromise, 500) + .then(() => { + throw 'expected to reject, but resolved' + }) + .catch(() => { + /**/ + }) + }) + it('should NOT timeout', async () => { + const mainPromise = sleep(1000) + await promiseTimeout(mainPromise, 1500) + .then(() => { + /**/ + }) + .catch(() => { + throw 'expected to resolve, but rejected' + }) + }) +}) diff --git a/packages/sushi/src/router/timeout.ts b/packages/sushi/src/router/timeout.ts new file mode 100644 index 0000000000..f05d41fd89 --- /dev/null +++ b/packages/sushi/src/router/timeout.ts @@ -0,0 +1,14 @@ +export async function promiseTimeout( + promise: Promise, + time: number, + exception?: any, +) { + let timer: any + return Promise.race([ + promise, + new Promise((_res, _rej) => { + timer = setTimeout(_rej, time, exception) + return timer + }), + ]).finally(() => clearTimeout(timer)) +} diff --git a/packages/sushi/src/serializer/index.ts b/packages/sushi/src/serializer/index.ts index 7da4aa67a3..cd7bda5da9 100644 --- a/packages/sushi/src/serializer/index.ts +++ b/packages/sushi/src/serializer/index.ts @@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs' import path from 'path' // import { fileURLToPath } from 'url' import serializer from 'serialijse' -import { ChainId } from 'sushi/chain' +import { ChainId } from '../chain/index.js' import { Native } from '../currency/index.js' import { BentoBridgePoolCode, diff --git a/packages/sushi/src/tines/MultiRouter.ts b/packages/sushi/src/tines/MultiRouter.ts index 7e7a756638..f059cd9cd9 100644 --- a/packages/sushi/src/tines/MultiRouter.ts +++ b/packages/sushi/src/tines/MultiRouter.ts @@ -88,6 +88,7 @@ export function findMultiRouteExactIn( baseTokenOrNetworks: RToken | NetworkInfo[], gasPrice?: number, flows?: number | number[], + pickRoute?: 'single' | 'multi', ): MultiRoute { try { pools = deduplicatePools(pools) @@ -112,7 +113,12 @@ export function findMultiRouteExactIn( if (bestFlowNumber === 1) return outSingle const outMulti = g.findBestRouteExactIn(from, to, amountIn, bestFlowNumber) - return getBetterRouteExactIn(outSingle, outMulti) + if (pickRoute) { + if (pickRoute === 'single') return outSingle + else return outMulti + } else { + return getBetterRouteExactIn(outSingle, outMulti) + } } catch (_e) { return NoWayMultiRoute(from, to) } diff --git a/packages/sushi/src/tines/RPool.ts b/packages/sushi/src/tines/RPool.ts index 815e91527d..1ea005d0ef 100644 --- a/packages/sushi/src/tines/RPool.ts +++ b/packages/sushi/src/tines/RPool.ts @@ -40,6 +40,8 @@ export abstract class RPool { // gasSpent: number = 0 readonly minLiquidity: number readonly swapGasCost: number + tick?: number | undefined + activeTick?: number | undefined constructor( address: Address, @@ -50,6 +52,8 @@ export abstract class RPool { reserve1: bigint, minLiquidity = TYPICAL_MINIMAL_LIQUIDITY, swapGasCost = TYPICAL_SWAP_GAS_COST, + tick?: number, + activeTick?: number | undefined, ) { this.address = address || '0x' this.token0 = token0 @@ -63,6 +67,8 @@ export abstract class RPool { this.swapGasCost = swapGasCost this.reserve0 = reserve0 this.reserve1 = reserve1 + this.tick = tick + this.activeTick = activeTick } updateReserves(res0: bigint, res1: bigint) { diff --git a/packages/sushi/src/tines/UniV3Pool.ts b/packages/sushi/src/tines/UniV3Pool.ts index 8b7298a551..8c29129990 100644 --- a/packages/sushi/src/tines/UniV3Pool.ts +++ b/packages/sushi/src/tines/UniV3Pool.ts @@ -92,11 +92,12 @@ export class UniV3Pool extends RPool { fee: number, reserve0: bigint, reserve1: bigint, - tick: number, + activeTick: number, liquidity: bigint, sqrtPriceX96: bigint, ticks: CLTick[], nearestTick?: number, + tick?: number, ) { super( address, @@ -109,6 +110,8 @@ export class UniV3Pool extends RPool { TYPICAL_SWAP_GAS_COST, ) this.ticks = ticks + this.tick = tick + this.activeTick = activeTick if (address !== undefined) { if (this.ticks.length === 0) { this.ticks.push({ index: CL_MIN_TICK, DLiquidity: ZERO }) @@ -121,7 +124,7 @@ export class UniV3Pool extends RPool { this.liquidity = liquidity this.sqrtPriceX96 = sqrtPriceX96 - this.nearestTick = nearestTick ?? this._findTickForPrice(tick) + this.nearestTick = nearestTick ?? this._findTickForPrice(activeTick) } else { // for deserialization this.liquidity = undefined as unknown as bigint diff --git a/packages/sushi/test/tines/snapshots/report b/packages/sushi/test/tines/snapshots/report index 306557668b..6b75ab34dc 100644 --- a/packages/sushi/test/tines/snapshots/report +++ b/packages/sushi/test/tines/snapshots/report @@ -3,362 +3,21 @@ 3:"bridge-3": 11953.94 -> 11953.94 (0%) avg:0% 4:"bridge-4": 5496.94 -> 5496.94 (0%) avg:0% 5:"bridge-5-1": 4260.964 -> 4260.964 (0%) avg:0% -2:"top20-1": 1.1195509365387262e+37 -> 1.1195509365387262e+37 (0%) avg:0% 6:"bridge-5-2": 5473.94 -> 5473.94 (0%) avg:0% 7:"bridge-5-3": 5501.94 -> 5501.94 (0%) avg:0% 8:"bridge-5-5": 5528.94 -> 5528.94 (0%) avg:0% 9:"bridge-5-10": 5528.94 -> 5528.94 (0%) avg:0% 10:"bridge-5-30": 5528.94 -> 5528.94 (0%) avg:0% 11:"bridge-5-100": 5528.94 -> 5528.94 (0%) avg:0% -3:"top20-2": 96249232830474440000 -> 96249232830474440000 (0%) avg:0% -4:"top20-3": 467011582838851800000 -> 467011582838851800000 (0%) avg:0% -5:"top20-4": 14263706377454.916 -> 14263706377454.916 (0%) avg:0% 12:"bridge-5-300": 5528.94 -> 5528.94 (0%) avg:0% -6:"top20-5": 111208992328025 -> 111208992328025 (0%) avg:0% -7:"top20-6": 184056193599 -> 184056193599 (0%) avg:0% 13:"bridge-5-1000": 5528.94 -> 5528.94 (0%) avg:0% -8:"top20-7": 1.949010266471403e+21 -> 1.949010266471403e+21 (0%) avg:0% 14:"bridge-6": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 15:"bridge-7-1": 567.9947198349995 -> 567.9947198349995 (0%) avg:0% 16:"bridge-7-2": 567.9947198349995 -> 567.9947198349995 (0%) avg:0% 17:"bridge-7-3": 569.9929597799993 -> 569.9929597799993 (0%) avg:0% -9:"top20-8": 5147698251 -> 5147698251 (0%) avg:0% 18:"bridge-7-5": 577.9911997249991 -> 577.9911997249991 (0%) avg:0% 19:"bridge-7-10": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 20:"bridge-7-30": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% -10:"top20-9": 2.3146866045567974e+29 -> 2.3146866045567974e+29 (0%) avg:0% -11:"top20-10": 2.000939725061475e+25 -> 2.000939725061475e+25 (0%) avg:0% 21:"bridge-7-100": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% -12:"top20-11": 0 -> 0 (0%) avg:0% 22:"bridge-7-300": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% -13:"top20-12": 5.998729978399937e+23 -> 5.998729978399937e+23 (0%) avg:0% -14:"top20-13": 14.999999999999975 -> 14.999999999999975 (0%) avg:0% -15:"top20-14": 242561332730 -> 242561332730 (0%) avg:0% -16:"top20-15": 20057219983855420 -> 20057219983855420 (0%) avg:0% -17:"top20-16": 1371193183.507006 -> 1371193183.507006 (0%) avg:0% -18:"top20-17": 618784869519468900000 -> 618784869519468900000 (0%) avg:0% -19:"top20-18": 13965130914 -> 13965130914 (0%) avg:0% 23:"bridge-7-1000": 578.9911997249991 -> 578.9911997249991 (0%) avg:0% -20:"top20-19": 1719221840266011.2 -> 1719221840266011.2 (0%) avg:0% -21:"top20-20": 1.1539072915253164e+27 -> 1.1539072915253164e+27 (0%) avg:0% -22:"top20-21": 1.4857010533172297e+22 -> 1.4857010533172297e+22 (0%) avg:0% -23:"top20-22": 13216695381.96823 -> 13216695381.96823 (0%) avg:0% -24:"top20-23": 71.99999999995467 -> 71.99999999995467 (0%) avg:0% -25:"top20-24": 4.257526126994545e+23 -> 4.257526126994545e+23 (0%) avg:0% -26:"top20-25": 9.20707200216008e+22 -> 9.20707200216008e+22 (0%) avg:0% -27:"top20-26": 119377775 -> 119377775 (0%) avg:0% -28:"top20-27": 4.5396775085904846e+33 -> 4.5396775085904846e+33 (0%) avg:0% -29:"top20-28": 224764614280864 -> 224764614280864 (0%) avg:0% -30:"top20-29": 137910092016871140 -> 137910092016871140 (0%) avg:0% -31:"top20-30": 38414127759.999916 -> 38414127759.999916 (0%) avg:0% -32:"top20-31": 3.9150404497784796e+29 -> 3.9150404497784796e+29 (0%) avg:0% -33:"top20-32": 44939721212060795000 -> 44939721212060795000 (0%) avg:0% -34:"top20-33": 1.4260244914513205e+22 -> 1.4260244914513205e+22 (0%) avg:0% -35:"top20-34": 1.5495747386928312e+21 -> 1.5495747386928312e+21 (0%) avg:0% -36:"top20-35": 943239170088233300000 -> 943239170088233300000 (0%) avg:0% -37:"top20-36": 6121749117436.458 -> 6121749117436.458 (0%) avg:0% -38:"top20-37": 696747 -> 696747 (0%) avg:0% -39:"top20-38": 0 -> 0 (0%) avg:0% -40:"top20-39": 2.3426635283232224e+24 -> 2.3426635283232224e+24 (0%) avg:0% -41:"top20-40": 48254932363.26666 -> 48254932363.26666 (0%) avg:0% -42:"top20-41": 37860138974211.35 -> 37860138974211.35 (0%) avg:0% -43:"top20-42": 6.848076980412381e+22 -> 6.848076980412381e+22 (0%) avg:0% -44:"top20-43": 4320914881 -> 4320914881 (0%) avg:0% -45:"top20-44": 30713427089 -> 30713427089 (0%) avg:0% -46:"top20-45": 198661729955810 -> 198661729955810 (0%) avg:0% -47:"top20-46": 4003462547412852.5 -> 4003462547412852.5 (0%) avg:0% -48:"top20-47": 121585 -> 121585 (0%) avg:0% -49:"top20-48": 0 -> 0 (0%) avg:0% -50:"top20-49": 5.999999999999976 -> 5.999999999999976 (0%) avg:0% -51:"top20-50": 968129348392.8033 -> 968129348392.8033 (0%) avg:0% -52:"top20-51": 17468164450890598000 -> 17468164450890598000 (0%) avg:0% -53:"top20-52": 3370 -> 3370 (0%) avg:0% -54:"top20-53": 2.8669052288613494e+26 -> 2.8669052288613494e+26 (0%) avg:0% -55:"top20-54": 212397690771150670000 -> 212397690771150670000 (0%) avg:0% -56:"top20-55": 114722123950.99864 -> 114722123950.99864 (0%) avg:0% -57:"top20-56": 6237611807.9999895 -> 6237611807.9999895 (0%) avg:0% -58:"top20-57": 173 -> 173 (0%) avg:0% -59:"top20-58": 8.653786678134718e+34 -> 8.653786678134718e+34 (0%) avg:0% -60:"top20-59": 584843.9943957697 -> 584843.9943957697 (0%) avg:0% -61:"top20-60": 83746.99999922093 -> 83746.99999922093 (0%) avg:0% -62:"top20-61": 1.2108029911483686e+28 -> 1.2108029911483686e+28 (0%) avg:0% -63:"top20-62": 1.1321762736810075e+23 -> 1.1321762736810075e+23 (0%) avg:0% -64:"top20-63": 18624850720 -> 18624850720 (0%) avg:0% -65:"top20-64": 6558802213825504000 -> 6558802213825504000 (0%) avg:0% -66:"top20-65": 3006323408104.839 -> 3006323408104.839 (0%) avg:0% -67:"top20-66": 7.25699759360167e+33 -> 7.25699759360167e+33 (0%) avg:0% -68:"top20-67": 26997497976784.977 -> 26997497976784.977 (0%) avg:0% -69:"top20-68": 2.271898658800524e+29 -> 2.271898658800524e+29 (0%) avg:0% -70:"top20-69": 3320690.9992622463 -> 3320690.9992622463 (0%) avg:0% -71:"top20-70": 12137990973481046000 -> 12137990973481046000 (0%) avg:0% -72:"top20-71": 4.2988353121158716e+26 -> 4.2988353121158716e+26 (0%) avg:0% -73:"top20-72": 6.3575495792381146e+28 -> 6.3575495792381146e+28 (0%) avg:0% -74:"top20-73": 1.2313497939167126e+26 -> 1.2313497939167126e+26 (0%) avg:0% -75:"top20-74": 27707599790097 -> 27707599790097 (0%) avg:0% -76:"top20-75": 7124308 -> 7124308 (0%) avg:0% -77:"top20-76": 0 -> 0 (0%) avg:0% -78:"top20-77": 117608543724585440000 -> 117608543724585440000 (0%) avg:0% -79:"top20-78": 274576852204457 -> 274576852204457 (0%) avg:0% -80:"top20-79": 4.1679251723404575e+23 -> 4.1679251723404575e+23 (0%) avg:0% -81:"top20-80": 1.169123327125618e+23 -> 1.169123327125618e+23 (0%) avg:0% -82:"top20-81": 1.256638691159724e+26 -> 1.256638691159724e+26 (0%) avg:0% -83:"top20-82": 0 -> 0 (0%) avg:0% -84:"top20-83": 2.0149283251435153e+32 -> 2.0149283251435153e+32 (0%) avg:0% -85:"top20-84": 6.510078466693012e+35 -> 6.510078466693012e+35 (0%) avg:0% -86:"top20-85": 0 -> 0 (0%) avg:0% -87:"top20-86": 541712645104171 -> 541712645104171 (0%) avg:0% -88:"top20-87": 2935458414464351700 -> 2935458414464351700 (0%) avg:0% -89:"top20-88": 1672225 -> 1672225 (0%) avg:0% -90:"top20-89": 0 -> 0 (0%) avg:0% -91:"top20-90": 0 -> 0 (0%) avg:0% -92:"top20-91": 98143784 -> 98143784 (0%) avg:0% -93:"top20-92": 8692029076033.435 -> 8692029076033.435 (0%) avg:0% -94:"top20-93": 51562257056054440 -> 51562257056054440 (0%) avg:0% -95:"top20-94": 25641964396823.965 -> 25641964396823.965 (0%) avg:0% -96:"top20-95": 526418678128563400 -> 526418678128563400 (0%) avg:0% -97:"top20-96": 42011945995000000 -> 42011945995000000 (0%) avg:0% -98:"top20-97": 0 -> 0 (0%) avg:0% -99:"top20-98": 578210769514157600 -> 578210769514157600 (0%) avg:0% -100:"top20-99": 23757288573225 -> 23757288573225 (0%) avg:0% -101:"top20-100": 3519054200.963973 -> 3519054200.963973 (0%) avg:0% -102:"top20-101": 1.2366902841804613e+26 -> 1.2366902841804613e+26 (0%) avg:0% -103:"top20-102": 3.0616038596056797e+32 -> 3.0616038596056797e+32 (0%) avg:0% -104:"top20-103": 398198791124206 -> 398198791124206 (0%) avg:0% -105:"top20-104": 3434281999000000 -> 3434281999000000 (0%) avg:0% -106:"top20-105": 436386366610963040000 -> 436386366610963040000 (0%) avg:0% -107:"top20-106": 7814 -> 7814 (0%) avg:0% -108:"top20-107": 4.387432445585929e+34 -> 4.387432445585929e+34 (0%) avg:0% -109:"top20-108": 0 -> 0 (0%) avg:0% -110:"top20-109": 0 -> 0 (0%) avg:0% -111:"top20-110": 180771390372608.16 -> 180771390372608.16 (0%) avg:0% -112:"top20-111": 1.53356324718735e+23 -> 1.53356324718735e+23 (0%) avg:0% -113:"top20-112": 0 -> 0 (0%) avg:0% -114:"top20-113": 441807728976948040000 -> 441807728976948040000 (0%) avg:0% -115:"top20-114": 5.872905678780656e+30 -> 5.872905678780656e+30 (0%) avg:0% -116:"top20-115": 1.9999999999999998 -> 1.9999999999999998 (0%) avg:0% -117:"top20-116": 0 -> 0 (0%) avg:0% -118:"top20-117": 103625.91934739704 -> 103625.91934739704 (0%) avg:0% -119:"top20-118": 3994 -> 3994 (0%) avg:0% -120:"top20-119": 5481554822 -> 5481554822 (0%) avg:0% -121:"top20-120": 2148662632935361000 -> 2148662632935361000 (0%) avg:0% -122:"top20-121": 780768139203693200000 -> 780768139203693200000 (0%) avg:0% -123:"top20-122": 0 -> 0 (0%) avg:0% -124:"top20-123": 74390557839848180 -> 74390557839848180 (0%) avg:0% -125:"top20-124": 5.2767009412144705e+23 -> 5.2767009412144705e+23 (0%) avg:0% -126:"top20-125": 12999322599.999998 -> 12999322599.999998 (0%) avg:0% -127:"top20-126": 1.166563599584172e+25 -> 1.166563599584172e+25 (0%) avg:0% -128:"top20-127": 0 -> 0 (0%) avg:0% -129:"top20-128": 2.381239814048817e+29 -> 2.381239814048817e+29 (0%) avg:0% -130:"top20-129": 1.773617547666896e+21 -> 1.773617547666896e+21 (0%) avg:0% -131:"top20-130": 1043374941775 -> 1043374941775 (0%) avg:0% -132:"top20-131": 3 -> 3 (0%) avg:0% -133:"top20-132": 3523544256 -> 3523544256 (0%) avg:0% -134:"top20-133": 30660569440069612 -> 30660569440069612 (0%) avg:0% -135:"top20-134": 0 -> 0 (0%) avg:0% -136:"top20-135": 46215289309 -> 46215289309 (0%) avg:0% -137:"top20-136": 157666012290841060 -> 157666012290841060 (0%) avg:0% -138:"top20-137": 0 -> 0 (0%) avg:0% -139:"top20-138": 94486154517 -> 94486154517 (0%) avg:0% -140:"top20-139": 5381047.578903644 -> 5381047.578903644 (0%) avg:0% -141:"top20-140": 2904868891031402 -> 2904868891031402 (0%) avg:0% -142:"top20-141": 349815735970433660000 -> 349815735970433660000 (0%) avg:0% -143:"top20-142": 1.61321284630438e+29 -> 1.61321284630438e+29 (0%) avg:0% -144:"top20-143": 0 -> 0 (0%) avg:0% -145:"top20-144": 1.8715935050611244e+27 -> 1.8715935050611244e+27 (0%) avg:0% -146:"top20-145": 2329.999987331977 -> 2329.999987331977 (0%) avg:0% -147:"top20-146": 1.5754421469670991e+28 -> 1.5754421469670991e+28 (0%) avg:0% -148:"top20-147": 2.6838048385825768e+32 -> 2.6838048385825768e+32 (0%) avg:0% -149:"top20-148": 2.7141809250137436e+32 -> 2.7141809250137436e+32 (0%) avg:0% -150:"top20-149": 17399664148369718 -> 17399664148369718 (0%) avg:0% -151:"top20-150": 0 -> 0 (0%) avg:0% -152:"top20-151": 481 -> 481 (0%) avg:0% -153:"top20-152": 0 -> 0 (0%) avg:0% -154:"top20-153": 1.3468577317796694e+32 -> 1.3468577317796694e+32 (0%) avg:0% -155:"top20-154": 7978807883992.964 -> 7978807883992.964 (0%) avg:0% -156:"top20-155": 75460.9999999988 -> 75460.9999999988 (0%) avg:0% -157:"top20-156": 1433531033857000200 -> 1433531033857000200 (0%) avg:0% -158:"top20-157": 5729885219 -> 5729885219 (0%) avg:0% -159:"top20-158": 3.5295876698920206e+21 -> 3.5295876698920206e+21 (0%) avg:0% -160:"top20-159": 2752089826200724500 -> 2752089826200724500 (0%) avg:0% -161:"top20-160": 1.3721043284746797e+27 -> 1.3721043284746797e+27 (0%) avg:0% -162:"top20-161": 2628873 -> 2628873 (0%) avg:0% -163:"top20-162": 0 -> 0 (0%) avg:0% -164:"top20-163": 7.139942836800165e+35 -> 7.139942836800165e+35 (0%) avg:0% -165:"top20-164": 588671138.9993676 -> 588671138.9993676 (0%) avg:0% -166:"top20-165": 141491517.99997458 -> 141491517.99997458 (0%) avg:0% -167:"top20-166": 9.906334905865037e+36 -> 9.906334905865037e+36 (0%) avg:0% -168:"top20-167": 6.127970056928261e+23 -> 6.127970056928261e+23 (0%) avg:0% -169:"top20-168": 0 -> 0 (0%) avg:0% -170:"top20-169": 5.563914872862701e+28 -> 5.563914872862701e+28 (0%) avg:0% -171:"top20-170": 60.99999999999998 -> 60.99999999999998 (0%) avg:0% -172:"top20-171": 4.798308643628861e+25 -> 4.798308643628861e+25 (0%) avg:0% -173:"top20-172": 1.367545112055793e+32 -> 1.367545112055793e+32 (0%) avg:0% -174:"top20-173": 0 -> 0 (0%) avg:0% -175:"top20-174": 4.993017087793419e+24 -> 4.993017087793419e+24 (0%) avg:0% -176:"top20-175": 441351853599 -> 441351853599 (0%) avg:0% -177:"top20-176": 534 -> 534 (0%) avg:0% -178:"top20-177": 485417607049678900 -> 485417607049678900 (0%) avg:0% -179:"top20-178": 0 -> 0 (0%) avg:0% -180:"top20-179": 0 -> 0 (0%) avg:0% -181:"top20-180": 1.2621789345587139e+22 -> 1.2621789345587139e+22 (0%) avg:0% -182:"top20-181": 215019508513714540000 -> 215019508513714540000 (0%) avg:0% -183:"top20-182": 1.3446105728596857e+28 -> 1.3446105728596857e+28 (0%) avg:0% -184:"top20-183": 218271833509345280 -> 218271833509345280 (0%) avg:0% -185:"top20-184": 1.3560596494961327e+36 -> 1.3560596494961327e+36 (0%) avg:0% -186:"top20-185": 2.9275096959904162e+26 -> 2.9275096959904162e+26 (0%) avg:0% -187:"top20-186": 62225098320.952 -> 62225098320.952 (0%) avg:0% -188:"top20-187": 402767 -> 402767 (0%) avg:0% -189:"top20-188": 1545581776329305 -> 1545581776329305 (0%) avg:0% -190:"top20-189": 12592573197286450000 -> 12592573197286450000 (0%) avg:0% -191:"top20-190": 4110203427990146 -> 4110203427990146 (0%) avg:0% -192:"top20-191": 30858888.999999996 -> 30858888.999999996 (0%) avg:0% -193:"top20-192": 1315512 -> 1315512 (0%) avg:0% -194:"top20-193": 0 -> 0 (0%) avg:0% -195:"top20-194": 35645518265 -> 35645518265 (0%) avg:0% -196:"top20-195": 187628800443894.75 -> 187628800443894.75 (0%) avg:0% -197:"top20-196": 61348 -> 61348 (0%) avg:0% -198:"top20-197": 195599663704564 -> 195599663704564 (0%) avg:0% -199:"top20-198": 7.150706782902594e+25 -> 7.150706782902594e+25 (0%) avg:0% -200:"top20-199": 5.948111798638225e+27 -> 5.948111798638225e+27 (0%) avg:0% -201:"m100-0": 6.771484296681975e+23 -> 6.771484296681975e+23 (0%) avg:0% -202:"m100-1": 9.840311847767955e+26 -> 9.840311847767955e+26 (0%) avg:0% -203:"m100-2": 4129386959 -> 4129386959 (0%) avg:0% -204:"m100-3": 401699286402680300000 -> 401699286402680300000 (0%) avg:0% -205:"m100-4": 0 -> 0 (0%) avg:0% -206:"m100-5": 5.527533399902125e+23 -> 5.527533399902125e+23 (0%) avg:0% -207:"m100-6": 11370204433554 -> 11370204433554 (0%) avg:0% -208:"m100-7": 134.99999999999997 -> 134.99999999999997 (0%) avg:0% -209:"m100-8": 1.4799956370270965e+30 -> 1.4799956370270965e+30 (0%) avg:0% -210:"m100-9": 9.24662083836204e+21 -> 9.24662083836204e+21 (0%) avg:0% -211:"st-0-1": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -212:"st-0-2": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -213:"st-0-4": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -214:"st-0-10": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -215:"st-0-20": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -216:"st-0-40": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -217:"st-0-100": 33.99999999999998 -> 33.99999999999998 (0%) avg:0% -218:"st-1-1": 0 -> 0 (0%) avg:0% -219:"st-1-2": 0 -> 0 (0%) avg:0% -220:"st-1-4": 0 -> 0 (0%) avg:0% -221:"st-1-10": 0 -> 0 (0%) avg:0% -222:"st-1-20": 0 -> 0 (0%) avg:0% -223:"st-1-40": 0 -> 0 (0%) avg:0% -224:"st-1-100": 0 -> 0 (0%) avg:0% -225:"st-2-1": 6258246 -> 6258246 (0%) avg:0% -226:"st-2-2": 6258246 -> 6258246 (0%) avg:0% -227:"st-2-4": 6258246 -> 6258246 (0%) avg:0% -228:"st-2-10": 6258246 -> 6258246 (0%) avg:0% -229:"st-2-20": 6258246 -> 6258246 (0%) avg:0% -230:"st-2-40": 6258246 -> 6258246 (0%) avg:0% -231:"st-2-100": 6258246 -> 6258246 (0%) avg:0% -232:"st-3-1": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -233:"st-3-2": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -234:"st-3-4": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -235:"st-3-10": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -236:"st-3-20": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -237:"st-3-40": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -238:"st-3-100": 654213972821424900000 -> 654213972821424900000 (0%) avg:0% -239:"st-4-1": 0 -> 0 (0%) avg:0% -240:"st-4-2": 0 -> 0 (0%) avg:0% -241:"st-4-4": 0 -> 0 (0%) avg:0% -242:"st-4-10": 0 -> 0 (0%) avg:0% -243:"st-4-20": 0 -> 0 (0%) avg:0% -244:"st-4-40": 0 -> 0 (0%) avg:0% -245:"st-4-100": 0 -> 0 (0%) avg:0% -246:"single20-0": 3.110433173731008e+31 -> 3.110433173731008e+31 (0%) avg:0% -247:"single20-1": 4.918763490555518e+26 -> 4.918763490555518e+26 (0%) avg:0% -248:"single20-2": 3067374209460307 -> 3067374209460307 (0%) avg:0% -249:"single20-3": 127.99999999999996 -> 127.99999999999996 (0%) avg:0% -250:"single20-4": 30781798338.99999 -> 30781798338.99999 (0%) avg:0% -251:"single20-5": 510007647749 -> 510007647749 (0%) avg:0% -252:"single20-6": 12228714.999978304 -> 12228714.999978304 (0%) avg:0% -253:"single20-7": 30137.939997182115 -> 30137.939997182115 (0%) avg:0% -254:"single20-8": 68027738516254000000 -> 68027738516254000000 (0%) avg:0% -255:"single20-9": 0 -> 0 (0%) avg:0% -256:"single20-10": 2.4010151620123693e+26 -> 2.4010151620123693e+26 (0%) avg:0% -257:"single20-12": 1.2058573329386557e+21 -> 1.2058573329386557e+21 (0%) avg:0% -258:"single20-13": 3.8499082136677565e+29 -> 3.8499082136677565e+29 (0%) avg:0% -259:"single20-14": 1.739289559046476e+32 -> 1.739289559046476e+32 (0%) avg:0% -260:"single20-15": 26.99999995404102 -> 26.99999995404102 (0%) avg:0% -261:"single20-16": 5928814 -> 5928814 (0%) avg:0% -262:"single20-17": 171116433126.98795 -> 171116433126.98795 (0%) avg:0% -263:"single20-18": 17182663994373956 -> 17182663994373956 (0%) avg:0% -264:"single20-19": 5.455075077751915e+25 -> 5.455075077751915e+25 (0%) avg:0% -265:"single20-20": 360857285427093500000 -> 360857285427093500000 (0%) avg:0% -266:"single20-21": 2.304646401405295e+22 -> 2.304646401405295e+22 (0%) avg:0% -267:"single20-22": 0 -> 0 (0%) avg:0% -268:"single20-23": 2.2994347806532058e+36 -> 2.2994347806532058e+36 (0%) avg:0% -269:"single20-24": 7.447097880265051e+21 -> 7.447097880265051e+21 (0%) avg:0% -270:"single20-25": 133922523688561480000 -> 133922523688561480000 (0%) avg:0% -271:"single20-26": 5026553 -> 5026553 (0%) avg:0% -272:"single20-27": 47.999999999999964 -> 47.999999999999964 (0%) avg:0% -273:"single20-28": 1.9205043560883324e+24 -> 1.9205043560883324e+24 (0%) avg:0% -274:"single20-29": 3.0630038173782246e+29 -> 3.0630038173782246e+29 (0%) avg:0% -275:"single20-30": 4.792771135234192e+28 -> 4.792771135234192e+28 (0%) avg:0% -276:"single20-31": 186094651774764900000 -> 186094651774764900000 (0%) avg:0% -277:"single20-32": 1394820921664611600 -> 1394820921664611600 (0%) avg:0% -278:"single20-33": 335911113542380100 -> 335911113542380100 (0%) avg:0% -279:"single20-34": 0 -> 0 (0%) avg:0% -280:"single20-35": 8712.999999999955 -> 8712.999999999955 (0%) avg:0% -281:"single20-36": 478334445511687700000 -> 478334445511687700000 (0%) avg:0% -282:"single20-37": 29922687677716180000 -> 29922687677716180000 (0%) avg:0% -283:"single20-38": 7027962904639 -> 7027962904639 (0%) avg:0% -284:"single20-39": 54349026305008 -> 54349026305008 (0%) avg:0% -285:"single20-40": 1.048115189966003e+30 -> 1.048115189966003e+30 (0%) avg:0% -286:"single20-41": 0 -> 0 (0%) avg:0% -287:"single20-42": 88269162089.67043 -> 88269162089.67043 (0%) avg:0% -288:"single20-43": 1.1062465843952062e+26 -> 1.1062465843952062e+26 (0%) avg:0% -289:"single20-44": 1.1706032304343827e+29 -> 1.1706032304343827e+29 (0%) avg:0% -290:"single20-45": 3.8665402822771385e+30 -> 3.8665402822771385e+30 (0%) avg:0% -291:"single20-46": 5006500.999999981 -> 5006500.999999981 (0%) avg:0% -292:"single20-47": 1.3400049787611494e+21 -> 1.3400049787611494e+21 (0%) avg:0% -293:"single20-48": 3.355999525511012e+29 -> 3.355999525511012e+29 (0%) avg:0% -294:"single20-49": 752555750223170400 -> 752555750223170400 (0%) avg:0% -295:"single20-50": 3116677.9999996107 -> 3116677.9999996107 (0%) avg:0% -296:"single20-51": 26920158412794640 -> 26920158412794640 (0%) avg:0% -297:"single20-52": 203746532105.99997 -> 203746532105.99997 (0%) avg:0% -298:"single20-53": 1179122601233816 -> 1179122601233816 (0%) avg:0% -299:"single20-54": 213910825414942200 -> 213910825414942200 (0%) avg:0% -300:"single20-55": 0 -> 0 (0%) avg:0% -301:"single20-56": 210.9999999874765 -> 210.9999999874765 (0%) avg:0% -302:"single20-57": 5.999999987470895 -> 5.999999987470895 (0%) avg:0% -303:"single20-58": 8934960728455735 -> 8934960728455735 (0%) avg:0% -304:"single20-59": 548961453342463 -> 548961453342463 (0%) avg:0% -305:"single20-61": 10270254270231846 -> 10270254270231846 (0%) avg:0% -306:"single20-62": 1957972021 -> 1957972021 (0%) avg:0% -307:"single20-63": 2.780081385181302e+30 -> 2.780081385181302e+30 (0%) avg:0% -308:"single20-64": 46862570178490150 -> 46862570178490150 (0%) avg:0% -309:"single20-65": 93880 -> 93880 (0%) avg:0% -310:"single20-66": 104563807639877650000 -> 104563807639877650000 (0%) avg:0% -311:"single20-67": 762618499000000 -> 762618499000000 (0%) avg:0% -312:"single20-68": 152455414826877200000 -> 152455414826877200000 (0%) avg:0% -313:"single20-69": 4587453 -> 4587453 (0%) avg:0% -314:"single20-70": 2.999999999999988 -> 2.999999999999988 (0%) avg:0% -315:"single20-71": 3.1885969249920197e+25 -> 3.1885969249920197e+25 (0%) avg:0% -316:"single20-72": 0 -> 0 (0%) avg:0% -317:"single20-73": 323670280231 -> 323670280231 (0%) avg:0% -318:"single20-74": 1106163 -> 1106163 (0%) avg:0% -319:"single20-75": 205243486119 -> 205243486119 (0%) avg:0% -320:"single20-76": 9747 -> 9747 (0%) avg:0% -321:"single20-77": 846579839 -> 846579839 (0%) avg:0% -322:"single20-78": 2.4699054876781903e+36 -> 2.4699054876781903e+36 (0%) avg:0% -323:"single20-79": 4.246671249563139e+28 -> 4.246671249563139e+28 (0%) avg:0% -324:"single20-81": 1845.5775247637528 -> 1845.5775247637528 (0%) avg:0% -325:"single20-82": 3159304 -> 3159304 (0%) avg:0% -326:"single20-83": 1968634860443 -> 1968634860443 (0%) avg:0% -327:"single20-84": 1777226861761304 -> 1777226861761304 (0%) avg:0% -328:"single20-85": 0 -> 0 (0%) avg:0% -329:"single20-86": 58719.99999999999 -> 58719.99999999999 (0%) avg:0% -330:"single20-87": 17710930 -> 17710930 (0%) avg:0% -331:"single20-88": 0 -> 0 (0%) avg:0% -332:"single20-89": 0 -> 0 (0%) avg:0% -333:"single20-90": 1244477320958906 -> 1244477320958906 (0%) avg:0% -334:"single20-91": 410123511138301.8 -> 410123511138301.8 (0%) avg:0% -335:"single20-92": 839628132306643 -> 839628132306643 (0%) avg:0% -336:"single20-93": 479724950549 -> 479724950549 (0%) avg:0% -337:"single20-94": 8942951159051322 -> 8942951159051322 (0%) avg:0% -338:"single20-95": 2.980951054274543e+21 -> 2.980951054274543e+21 (0%) avg:0% -339:"single20-96": 0 -> 0 (0%) avg:0% -340:"single20-97": 8.021659281577077e+31 -> 8.021659281577077e+31 (0%) avg:0% -341:"single20-98": 1701170936126.7368 -> 1701170936126.7368 (0%) avg:0% -342:"single20-99": 433219 -> 433219 (0%) avg:0% diff --git a/packages/sushi/test/vitest.config.ts b/packages/sushi/test/vitest.config.ts index 2a9216887c..f6174d3176 100644 --- a/packages/sushi/test/vitest.config.ts +++ b/packages/sushi/test/vitest.config.ts @@ -26,6 +26,7 @@ export default defineConfig({ include: ['src/**/*.test.ts', 'test/**/*.test.ts'], setupFiles: [join(__dirname, './setupFiles.ts')], globalSetup: [join(__dirname, './globalSetup.ts')], - testTimeout: 10_000, + testTimeout: 600_000, + hookTimeout: 70_000, }, }) diff --git a/packages/sushi/tsconfig.esm.json b/packages/sushi/tsconfig.esm.json new file mode 100644 index 0000000000..30264ccf40 --- /dev/null +++ b/packages/sushi/tsconfig.esm.json @@ -0,0 +1,26 @@ +{ + "extends": ["@tsconfig/strictest/tsconfig"], + "include": ["src"], + "exclude": [ + "node_modules", + "dist", + ".turbo", + "src/**/*.test.ts", + "src/**/*.test-d.ts", + "src/**/*.bench.ts" + ], + "compilerOptions": { + "target": "es2022", + "module": "ES2022", + "lib": ["ES2022", "DOM", "ES6"], + "outDir": "./dist/esm", + "rootDir": "./src", + "declaration": false, + "declarationMap": false, + "sourceMap": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "moduleResolution": "bundler" + } + } + \ No newline at end of file diff --git a/packages/sushi/tsconfig.json b/packages/sushi/tsconfig.json index fb39f028eb..317aaf9e94 100644 --- a/packages/sushi/tsconfig.json +++ b/packages/sushi/tsconfig.json @@ -10,10 +10,11 @@ "src/**/*.bench.ts" ], "compilerOptions": { - "outDir": "./dist", + "outDir": "./dist/cjs", "rootDir": "./src", "declaration": true, "declarationMap": true, + "declarationDir": "./dist/types", "sourceMap": true, "skipLibCheck": true, "resolveJsonModule": true diff --git a/packages/wagmi/package.json b/packages/wagmi/package.json index e954231424..c46fc24db0 100644 --- a/packages/wagmi/package.json +++ b/packages/wagmi/package.json @@ -65,7 +65,7 @@ "@uniswap/v3-periphery": "1.4.1", "next-themes": "0.2.1", "sushi": "workspace:*", - "zod": "3.21.4" + "zod": "3.22.0" }, "devDependencies": { "@sentry/nextjs": "7.101.1", @@ -80,7 +80,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "typescript": "5.2.2", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20" }, "peerDependencies": { @@ -89,7 +89,7 @@ "next": "14.1.0", "react": "18.2.0", "react-dom": "18.2.0", - "viem": "2.8.14", + "viem": "2.21.35", "wagmi": "2.5.20" }, "peerDependenciesMeta": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eafb65cc1a..7fac592223 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,7 +64,7 @@ importers: version: link:../../packages/extractor '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) cors: specifier: 2.8.5 version: 2.8.5 @@ -78,14 +78,14 @@ importers: specifier: workspace:* version: link:../../packages/sushi viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@5.29.2)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.5.20(@tanstack/react-query@5.29.2)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@tsconfig/esm': specifier: 1.0.4 @@ -125,7 +125,7 @@ importers: version: link:../../packages/extractor '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) cors: specifier: 2.8.5 version: 2.8.5 @@ -139,14 +139,14 @@ importers: specifier: workspace:* version: link:../../packages/sushi viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@5.29.2)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.5.20(@tanstack/react-query@5.29.2)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@tsconfig/esm': specifier: 1.0.4 @@ -229,7 +229,7 @@ importers: version: 3.0.9 '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) drizzle-orm: specifier: ^0.29.5 version: 0.29.5(@neondatabase/serverless@0.9.0)(postgres@3.4.4)(react@18.2.0) @@ -240,11 +240,11 @@ importers: specifier: workspace:* version: link:../../packages/sushi viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@sushiswap/jest-config': specifier: workspace:* @@ -333,7 +333,7 @@ importers: version: 0.82.3(@babel/core@7.24.4)(@types/node@20.10.0)(graphql-tag@2.12.6)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/graphql': specifier: 0.94.2 - version: 0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(@types/node@20.10.0)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(@types/node@20.10.0)(graphql@16.6.0)(tslib@2.8.0) '@next/eslint-plugin-next': specifier: 14.1.0 version: 14.1.0 @@ -439,7 +439,7 @@ importers: version: 0.82.3(@babel/core@7.24.4)(@types/node@20.10.0)(graphql-tag@2.12.6)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/graphql': specifier: 0.94.2 - version: 0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(@types/node@20.10.0)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(@types/node@20.10.0)(graphql@16.6.0)(tslib@2.8.0) '@next/eslint-plugin-next': specifier: 14.1.0 version: 14.1.0 @@ -583,10 +583,10 @@ importers: version: 0.4.1 '@wagmi/connectors': specifier: ^4.1.14 - version: 4.1.19(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 4.1.19(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) cors: specifier: 2.8.5 version: 2.8.5 @@ -666,14 +666,14 @@ importers: specifier: 1.3.1 version: 1.3.1 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(@upstash/redis@1.22.1)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(@upstash/redis@1.22.1)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@0xsquid/squid-types': specifier: ^0.1.59 @@ -1117,7 +1117,7 @@ importers: version: 2.0.2 '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) jest: specifier: 29.7.0 version: 29.7.0(@types/node@20.10.0) @@ -1150,37 +1150,37 @@ importers: version: 3.0.0(@babel/core@7.24.4)(@envelop/core@4.0.0)(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/delegate@10.0.4)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@10.0.5)(@swc/core@1.4.2)(@types/node@20.12.7)(graphql-tag@2.12.6)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/cache-localforage': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/cross-helpers': specifier: 0.4.0 version: 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/graphql': specifier: 0.94.2 - version: 0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(@types/node@20.12.7)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(@types/node@20.12.7)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/http': specifier: 0.94.4 - version: 0.94.4(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/runtime@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.4(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/runtime@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/merger-stitching': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/runtime': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/store': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-filter-schema': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-prefix': specifier: 0.94.2 - version: 0.94.2(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.2(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-type-merging': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': specifier: 0.94.1 - version: 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/merge': specifier: 9.0.0 version: 9.0.0(graphql@16.6.0) @@ -1204,7 +1204,7 @@ importers: version: link:../../config/wagmi '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) '@whatwg-node/fetch': specifier: 0.8.4 version: 0.8.4 @@ -1233,11 +1233,11 @@ importers: specifier: ^4.7.1 version: 4.7.1 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@sushiswap/jest-config': specifier: workspace:* @@ -1317,8 +1317,8 @@ importers: specifier: 5.2.2 version: 5.2.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) packages/client: dependencies: @@ -1344,11 +1344,11 @@ importers: specifier: latest version: 2.6.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@sushiswap/jest-config': specifier: workspace:* @@ -1489,13 +1489,13 @@ importers: version: 1.0.1 abitype: specifier: 0.9.8 - version: 0.9.8(typescript@5.2.2)(zod@3.21.4) + version: 0.9.8(typescript@5.2.2)(zod@3.22.0) sushi: specifier: workspace:* version: link:../sushi viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) devDependencies: '@sushiswap/jest-config': specifier: workspace:* @@ -1535,19 +1535,19 @@ importers: version: 3.0.0(@babel/core@7.24.4)(@envelop/core@4.0.0)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@10.0.4)(@graphql-tools/merge@9.0.3)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@10.0.5)(@types/node@20.10.0)(graphql-tag@2.12.6)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/transform-filter-schema': specifier: 0.96.6 - version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-prefix': specifier: 0.96.6 - version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-prune': specifier: 0.96.6 - version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-rename': specifier: 0.96.7 - version: 0.96.7(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + version: 0.96.7(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/transform-type-merging': specifier: 0.96.6 - version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.6.2) + version: 0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/merge': specifier: 9.0.3 version: 9.0.3(graphql@16.6.0) @@ -1575,7 +1575,7 @@ importers: version: 20.10.0 '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) graphql: specifier: 16.6.0 version: 16.6.0 @@ -1668,8 +1668,8 @@ importers: specifier: 4.0.0 version: 4.0.0 zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 devDependencies: '@sentry/nextjs': specifier: 7.101.1 @@ -1717,11 +1717,11 @@ importers: specifier: 5.2.2 version: 5.2.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) packages/steer-sdk: dependencies: @@ -1741,11 +1741,11 @@ importers: specifier: latest version: 2.6.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@5.29.2)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + version: 2.5.20(@tanstack/react-query@5.29.2)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) optionalDependencies: next: specifier: 14.1.0 @@ -1765,7 +1765,7 @@ importers: version: 20.10.0 '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) eslint: specifier: 8.43.0 version: 8.43.0 @@ -1856,7 +1856,7 @@ importers: version: 3.0.1 '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.4.2)(@types/node@20.12.7)(typescript@5.2.2) @@ -1864,14 +1864,14 @@ importers: specifier: 5.2.2 version: 5.2.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) vitest: specifier: 0.34.6 version: 0.34.6 zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 packages/ui: dependencies: @@ -2082,7 +2082,7 @@ importers: version: 5.2.2 wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@5.29.2)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + version: 2.5.20(@tanstack/react-query@5.29.2)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) packages/wagmi: dependencies: @@ -2141,8 +2141,8 @@ importers: specifier: workspace:* version: link:../sushi zod: - specifier: 3.21.4 - version: 3.21.4 + specifier: 3.22.0 + version: 3.22.0 optionalDependencies: next: specifier: 14.1.0 @@ -2168,7 +2168,7 @@ importers: version: 18.2.6 '@wagmi/core': specifier: 2.6.17 - version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) eslint-config-sushi: specifier: workspace:* version: link:../../config/eslint @@ -2182,11 +2182,11 @@ importers: specifier: 5.2.2 version: 5.2.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) wagmi: specifier: 2.5.20 - version: 2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + version: 2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) protocols/route-processor: devDependencies: @@ -2311,8 +2311,8 @@ importers: specifier: 5.2.2 version: 5.2.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) protocols/tines-sandbox: devDependencies: @@ -2452,8 +2452,8 @@ importers: specifier: 5.2.2 version: 5.2.2 viem: - specifier: 2.8.14 - version: 2.8.14(typescript@5.2.2)(zod@3.21.4) + specifier: 2.21.35 + version: 2.21.35(typescript@5.2.2)(zod@3.22.0) packages: @@ -2499,6 +2499,9 @@ packages: /@adraffy/ens-normalize@1.10.0: resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==} + /@adraffy/ens-normalize@1.11.0: + resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -7929,7 +7932,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 graphql: 16.6.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.4(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.5(graphql@16.6.0) @@ -7948,7 +7951,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 graphql: 16.6.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.4(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.5(graphql@16.6.0) @@ -7966,7 +7969,7 @@ packages: graphql: 16.6.0 dependencies: '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.5.0) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.4(graphql@16.6.0) graphql: 16.6.0 tslib: 2.5.0 @@ -7983,7 +7986,7 @@ packages: graphql: 16.6.0 dependencies: '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.5.0) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.4(graphql@16.6.0) graphql: 16.6.0 tslib: 2.5.0 @@ -8468,14 +8471,14 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) graphql: 16.6.0 localforage: 1.10.0 tslib: 2.6.2 dev: false - /@graphql-mesh/cache-localforage@0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/cache-localforage@0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-0cix/UXVVw+EzDAI1mfrPMHNJ5lwKHqmp9DcyzB1XIffu6qZVHWvG9wEqn/yTd0BCAV8HoTcNuPaREh0YX3lAg==} engines: {node: '>=16.0.0'} peerDependencies: @@ -8484,11 +8487,11 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) graphql: 16.6.0 localforage: 1.10.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false /@graphql-mesh/cli@0.82.3(@babel/core@7.24.4)(@types/node@20.10.0)(graphql-tag@2.12.6)(graphql@16.6.0)(react-native@0.73.7): @@ -8562,7 +8565,7 @@ packages: '@graphql-mesh/http': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/runtime@0.93.2)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.6.2) '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) ajv: 8.12.0 @@ -8614,10 +8617,10 @@ packages: '@graphql-mesh/config': 0.93.1(@babel/core@7.24.4)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/runtime@0.93.2)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/http': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/runtime@0.93.2)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) ajv: 8.12.0 change-case: 4.1.2 @@ -8672,7 +8675,7 @@ packages: '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-tools/code-file-loader': 7.3.23(@babel/core@7.24.4)(graphql@16.6.0) '@graphql-tools/graphql-file-loader': 7.5.17(graphql@16.6.0) @@ -8797,10 +8800,10 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.6.0)(tslib@2.5.0) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/url-loader': 7.17.18(@types/node@20.10.0)(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) @@ -8826,10 +8829,10 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.6.0)(tslib@2.5.0) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/url-loader': 7.17.18(@types/node@20.12.7)(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) @@ -8843,7 +8846,7 @@ packages: - utf-8-validate dev: false - /@graphql-mesh/graphql@0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(@types/node@20.12.7)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/graphql@0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(@types/node@20.12.7)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-uKPaHpnZqxU0pGa79xlfrJB85vbZ5rTfhdBK+HtYAp+1MCL4xB9Rjomyu2VG+KDvfdtu2sj9Bqql+5NGztZFMQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -8856,24 +8859,24 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/url-loader': 8.0.0(@types/node@20.12.7)(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 lodash.get: 4.4.2 - tslib: 2.6.2 + tslib: 2.8.0 transitivePeerDependencies: - '@types/node' - bufferutil - utf-8-validate dev: false - /@graphql-mesh/graphql@0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(@types/node@20.10.0)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/graphql@0.94.2(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(@types/node@20.10.0)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-uKPaHpnZqxU0pGa79xlfrJB85vbZ5rTfhdBK+HtYAp+1MCL4xB9Rjomyu2VG+KDvfdtu2sj9Bqql+5NGztZFMQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -8886,17 +8889,17 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/url-loader': 8.0.0(@types/node@20.10.0)(graphql@16.6.0) '@graphql-tools/utils': 10.1.3(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 lodash.get: 4.4.2 - tslib: 2.6.2 + tslib: 2.8.0 transitivePeerDependencies: - '@types/node' - bufferutil @@ -8938,7 +8941,7 @@ packages: dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) fets: 0.1.5 graphql: 16.6.0 @@ -8946,7 +8949,7 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/http@0.94.4(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/runtime@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/http@0.94.4(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/runtime@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-eUye4S9tnp+BijW1ol7bD8TUyM7ptRqgxAhBej79pVlx/fs98z1IUxIgTb39HzNBBZaPaLdNtWv5Yqd/PImXEw==} engines: {node: '>=16.0.0'} peerDependencies: @@ -8958,13 +8961,13 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/runtime': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/runtime': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@whatwg-node/server': 0.9.33 graphql: 16.6.0 graphql-yoga: 4.0.5(graphql@16.6.0) - tslib: 2.6.2 + tslib: 2.8.0 dev: false /@graphql-mesh/merger-bare@0.16.4(graphql@16.6.0)(react-native@0.73.7): @@ -8994,7 +8997,7 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-tools/schema': 9.0.19(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) @@ -9035,7 +9038,7 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/schema': 9.0.19(graphql@16.6.0) @@ -9046,7 +9049,7 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/merger-stitching@0.94.1(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/merger-stitching@0.94.1(@graphql-mesh/store@0.94.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-s9yPkX9mJG4Ceyl0kyMdwX/nmD+mxHU/SXW8xIo1+YkFOOogJbwEgiF2QZaxIsBJgsE1uB8vAc6FmUg6wNLgKg==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9057,16 +9060,16 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/schema': 10.0.0(graphql@16.6.0) '@graphql-tools/stitch': 9.1.0(graphql@16.6.0) '@graphql-tools/stitching-directives': 3.0.0(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false /@graphql-mesh/runtime@0.46.2(graphql@16.6.0)(react-native@0.73.7): @@ -9108,7 +9111,7 @@ packages: '@envelop/extended-validation': 2.0.6(@envelop/core@3.0.6)(graphql@16.6.0) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-tools/batch-delegate': 8.4.27(graphql@16.6.0) '@graphql-tools/batch-execute': 8.5.22(graphql@16.6.0) @@ -9120,7 +9123,33 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/runtime@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/runtime@0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): + resolution: {integrity: sha512-8z9ag3jZLmkzawMzF6+i/+P1nQai+HmSZzNeJJen6fRkwprSM1Z7B4lfYBYhdiCbK11HHubDfw4LYwRuBcISMQ==} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.3.4 + '@graphql-mesh/types': ^0.93.1 + '@graphql-mesh/utils': ^0.93.1 + '@graphql-tools/utils': ^9.2.1 + graphql: 16.6.0 + tslib: ^2.4.0 + dependencies: + '@envelop/core': 3.0.6 + '@envelop/extended-validation': 2.0.6(@envelop/core@3.0.6)(graphql@16.6.0) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) + '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-tools/batch-delegate': 8.4.27(graphql@16.6.0) + '@graphql-tools/batch-execute': 8.5.22(graphql@16.6.0) + '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) + '@graphql-tools/utils': 9.2.1(graphql@16.6.0) + '@graphql-tools/wrap': 9.4.2(graphql@16.6.0) + '@whatwg-node/fetch': 0.8.4 + graphql: 16.6.0 + tslib: 2.8.0 + dev: false + + /@graphql-mesh/runtime@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-C2f2XmdKD1j7SU/btRFGupJHFBkVJ25WyhHCOw6k31dbbK/o8zuwsD1bPTW5JIzs4zpGmAdEoNcs7G/axe5XJw==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9134,9 +9163,9 @@ packages: '@envelop/core': 4.0.0 '@envelop/extended-validation': 3.0.3(@envelop/core@4.0.0)(graphql@16.6.0) '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/batch-delegate': 9.0.0(graphql@16.6.0) '@graphql-tools/batch-execute': 9.0.1(graphql@16.6.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) @@ -9144,7 +9173,7 @@ packages: '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) '@whatwg-node/fetch': 0.9.9 graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false /@graphql-mesh/store@0.9.3(graphql@16.6.0)(react-native@0.73.7): @@ -9176,14 +9205,33 @@ packages: dependencies: '@graphql-inspector/core': 3.3.0(graphql@16.6.0) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) graphql: 16.6.0 tslib: 2.6.2 dev: false - /@graphql-mesh/store@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/store@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): + resolution: {integrity: sha512-OEljVuaZn2htU1rt4Yll/aJmynw3/Kvhd6eE8V0/del0u9iuLJqiKkzFJl8HUSMh0IkO10OnficJnTM0tCmxRw==} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.3.4 + '@graphql-mesh/types': ^0.93.1 + '@graphql-mesh/utils': ^0.93.1 + '@graphql-tools/utils': ^9.2.1 + graphql: 16.6.0 + tslib: ^2.4.0 + dependencies: + '@graphql-inspector/core': 3.3.0(graphql@16.6.0) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-tools/utils': 9.2.1(graphql@16.6.0) + graphql: 16.6.0 + tslib: 2.8.0 + dev: false + + /@graphql-mesh/store@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-EbHLSPdlRqq0VYjdKXhKCAGdpP0n9qFPduugdGrd35Vk4UaBo4VdBhXQ1vkenAI3VK1VXWjCB+aaC2ikva/2yQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9196,14 +9244,14 @@ packages: dependencies: '@graphql-inspector/core': 5.0.0(graphql@16.6.0) '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/store@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/store@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-EbHLSPdlRqq0VYjdKXhKCAGdpP0n9qFPduugdGrd35Vk4UaBo4VdBhXQ1vkenAI3VK1VXWjCB+aaC2ikva/2yQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9216,11 +9264,11 @@ packages: dependencies: '@graphql-inspector/core': 5.0.0(graphql@16.6.0) '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/types': 0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/utils': 10.1.3(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: true /@graphql-mesh/string-interpolation@0.4.1(graphql@16.6.0): @@ -9260,7 +9308,20 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/string-interpolation@0.5.1(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/string-interpolation@0.4.4(graphql@16.6.0)(tslib@2.8.0): + resolution: {integrity: sha512-IotswBYZRaPswOebcr2wuOFuzD3dHIJxVEkPiiQubqjUIR8HhQI22XHJv0WNiQZ65z8NR9+GYWwEDIc2JRCNfQ==} + peerDependencies: + graphql: 16.6.0 + tslib: ^2.4.0 + dependencies: + dayjs: 1.11.7 + graphql: 16.6.0 + json-pointer: 0.6.2 + lodash.get: 4.4.2 + tslib: 2.8.0 + dev: false + + /@graphql-mesh/string-interpolation@0.5.1(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-xrShpJ4silpWekpeVntDNt6NY6RxEMMbZ1CenIkLsl/QN3mMjxWa3rQX0qrByBeyDn7SorSN3lrClCCsPvmWZw==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9271,9 +9332,9 @@ packages: graphql: 16.6.0 json-pointer: 0.6.2 lodash.get: 4.4.2 - tslib: 2.6.2 + tslib: 2.8.0 - /@graphql-mesh/transform-filter-schema@0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-filter-schema@0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-833mj7JsSJbP3797Ls+fS6SXzf13ZKe92ghOn+3b6CMSHpP7k3jacVjhvoMdmw7IdYo6OC0+XjbQzF/A6YE/cA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9283,17 +9344,17 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 minimatch: 9.0.3 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/transform-filter-schema@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-filter-schema@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-l6P0FYmS4f3Sq0rCnLWcSQi6QawyAcXFtEs61+aDLZU/EUp9NmjLYKjO4pWjxvOEbguBWx+ZcKRH3jNGaavokQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9303,17 +9364,17 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 minimatch: 9.0.3 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/transform-prefix@0.94.2(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-prefix@0.94.2(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-1G9mscftMPIAnN3yZfOLka1lUQ38pXIzdxjg77SmkCt85BE0Asjsbn8hitdQGiCMd5urVvj/WmxGDx+iJt8y8g==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9323,17 +9384,17 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 graphql-scalars: 1.23.0(graphql@16.6.0) - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/transform-prefix@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-prefix@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-950SfyNr2VIC4viujk/nedAehBKjv5FowRlZs/6fWZiktN6/6KELMZcZcbk6VI2fi3yB5evl4X43tJRRY3Zl+A==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9343,17 +9404,17 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 graphql-scalars: 1.23.0(graphql@16.6.0) - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/transform-prune@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-prune@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-brKG+MVd2gsGbYitV1TtpMOShXKrZsbM2jI/2YHz1wrnMDEx2gQLT1/XYi/rKbKLizJjKAPUwiAbOJKzpdf3UA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9362,13 +9423,13 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/transform-rename@0.96.7(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-rename@0.96.7(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-v1oUlx6HXIqwhPnGGLQ/MgoHYF1yQVUCVB154nNghYlQtOCkMhktK+45QXAdVho398icyRyVAY+N1sl6oFynPA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9378,14 +9439,14 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-tools/wrap': 10.0.0(graphql@16.6.0) graphql: 16.6.0 graphql-scalars: 1.23.0(graphql@16.6.0) - tslib: 2.6.2 + tslib: 2.8.0 dev: false /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.5.0): @@ -9396,8 +9457,8 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/stitching-directives': 2.3.34(graphql@16.6.0) graphql: 16.6.0 @@ -9412,15 +9473,15 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/stitching-directives': 2.3.34(graphql@16.6.0) graphql: 16.6.0 tslib: 2.5.0 dev: false - /@graphql-mesh/transform-type-merging@0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-type-merging@0.94.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-VO/28veFKTAY1Ngd+jUxb6wo6XDManhpc+eQ6bL8OpsEU6viJkL/2Hxi7SoC37bXA9/5zAkPaMAP+tdQ26O6GQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9429,15 +9490,15 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/stitching-directives': 3.0.0(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/transform-type-merging@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/transform-type-merging@0.96.6(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-vbY3HDAdNjgbNVHC4fBqovZbWSZ7HWDyIvC3/ujbdzA5eGkWy15zCC87cbb6vblatgA6BkY+WnopTHyUTrTaWQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9446,12 +9507,12 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/stitching-directives': 3.0.0(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false /@graphql-mesh/types@0.89.2(graphql@16.6.0)(react-native@0.73.7): @@ -9471,7 +9532,7 @@ packages: - react-native-windows dev: true - /@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-113DuJzmR7aj2EMnLPu33ktCe5k7+Mk0BxFfmQViUH+mkr6i4JMsWvPKs9dTODSYuSuwvAZ90Vw2l3QyMrbFVA==} peerDependencies: '@graphql-mesh/store': ^0.93.1 @@ -9479,16 +9540,16 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/batch-delegate': 8.4.27(graphql@16.6.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-typed-document-node/core': 3.2.0(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-113DuJzmR7aj2EMnLPu33ktCe5k7+Mk0BxFfmQViUH+mkr6i4JMsWvPKs9dTODSYuSuwvAZ90Vw2l3QyMrbFVA==} peerDependencies: '@graphql-mesh/store': ^0.93.1 @@ -9496,16 +9557,16 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/batch-delegate': 8.4.27(graphql@16.6.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) '@graphql-typed-document-node/core': 3.2.0(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/types@0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/types@0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-Dir0ETwXhNK0Du5CHQ51xnBu/t5PhcTBbQVniPq/zgM02FJZRvbRHqlg2/Q1g3X3M9dIjs787XLhEarG4imL2g==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9514,13 +9575,13 @@ packages: graphql: 16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/store': 0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-mesh/utils@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/batch-delegate': 9.0.1(graphql@16.6.0) '@graphql-tools/delegate': 10.0.4(graphql@16.6.0) '@graphql-tools/utils': 10.1.3(graphql@16.6.0) '@graphql-typed-document-node/core': 3.2.0(graphql@16.6.0) graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: true /@graphql-mesh/utils@0.43.3(graphql@16.6.0)(react-native@0.73.7): @@ -9556,7 +9617,7 @@ packages: dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) dset: 3.1.2 @@ -9568,7 +9629,30 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/utils@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/utils@0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): + resolution: {integrity: sha512-U+VytfSoqPofH/pmYZHFY10SkIFtHKrvE7Isxv1d0DiweVjdH3Qtojw13DWFpu/EKtgJY5bqoVnlcsZJYlKQoA==} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.3.4 + '@graphql-mesh/types': ^0.93.2 + '@graphql-tools/utils': ^9.2.1 + graphql: 16.6.0 + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) + '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) + '@graphql-tools/delegate': 9.0.35(graphql@16.6.0) + '@graphql-tools/utils': 9.2.1(graphql@16.6.0) + dset: 3.1.2 + graphql: 16.6.0 + js-yaml: 4.1.0 + lodash.get: 4.4.2 + lodash.topath: 4.5.2 + tiny-lru: 8.0.2 + tslib: 2.8.0 + dev: false + + /@graphql-mesh/utils@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-K5cGtD+zmYcikoprovANM0B1MDAHE3tadSM7fDoEbfy//vBCXYfLAVjzgAMVxeS0M7KEH1vVqtHHZJKCvSjAoQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9579,8 +9663,8 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@9.2.1)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 9.2.1(graphql@16.6.0) dset: 3.1.2 @@ -9589,10 +9673,10 @@ packages: lodash.get: 4.4.2 lodash.topath: 4.5.2 tiny-lru: 11.0.1 - tslib: 2.6.2 + tslib: 2.8.0 dev: false - /@graphql-mesh/utils@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2): + /@graphql-mesh/utils@0.94.1(@graphql-mesh/cross-helpers@0.4.0)(@graphql-mesh/types@0.94.6)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0): resolution: {integrity: sha512-K5cGtD+zmYcikoprovANM0B1MDAHE3tadSM7fDoEbfy//vBCXYfLAVjzgAMVxeS0M7KEH1vVqtHHZJKCvSjAoQ==} engines: {node: '>=16.0.0'} peerDependencies: @@ -9603,8 +9687,8 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.0(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(react-native@0.73.7) - '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.6.2) - '@graphql-mesh/types': 0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.1(graphql@16.6.0)(tslib@2.8.0) + '@graphql-mesh/types': 0.94.6(@graphql-mesh/store@0.94.1)(@graphql-tools/utils@10.1.3)(graphql@16.6.0)(tslib@2.8.0) '@graphql-tools/delegate': 10.0.2(graphql@16.6.0) '@graphql-tools/utils': 10.1.3(graphql@16.6.0) dset: 3.1.2 @@ -9613,7 +9697,7 @@ packages: lodash.get: 4.4.2 lodash.topath: 4.5.2 tiny-lru: 11.0.1 - tslib: 2.6.2 + tslib: 2.8.0 dev: true /@graphql-tools/batch-delegate@8.4.13(graphql@16.6.0): @@ -10457,7 +10541,7 @@ packages: cross-inspect: 1.0.0 dset: 3.1.3 graphql: 16.6.0 - tslib: 2.6.2 + tslib: 2.8.0 dev: true /@graphql-tools/utils@8.13.1(graphql@16.6.0): @@ -10685,6 +10769,7 @@ packages: /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead dependencies: '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.4(supports-color@8.1.1) @@ -10703,6 +10788,7 @@ packages: /@humanwhocodes/object-schema@2.0.3: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead dev: false /@ioredis/commands@1.2.0: @@ -11667,6 +11753,12 @@ packages: dependencies: '@noble/hashes': 1.3.2 + /@noble/curves@1.6.0: + resolution: {integrity: sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==} + engines: {node: ^14.21.3 || >=16} + dependencies: + '@noble/hashes': 1.5.0 + /@noble/hashes@1.2.0: resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} @@ -11678,6 +11770,10 @@ packages: resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} + /@noble/hashes@1.5.0: + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -14979,15 +15075,14 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 rollup: 3.29.4 - dev: false /@rushstack/eslint-patch@1.3.3: resolution: {integrity: sha512-0xd7qez0AQ+MbHatZTlI1gu5vkG8r7MYRUJAHPAHJBmGLs16zpkrpAVLvjQKQOqaXPDUBwOiJzNc00znHSCVBw==} - /@safe-global/safe-apps-provider@0.18.1(typescript@5.2.2)(zod@3.21.4): + /@safe-global/safe-apps-provider@0.18.1(typescript@5.2.2)(zod@3.22.0): resolution: {integrity: sha512-V4a05A3EgJcriqtDoJklDz1BOinWhC6P0hjUSxshA4KOZM7rGPCTto/usXs09zr1vvL28evl/NldSTv97j2bmg==} dependencies: - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) events: 3.3.0 transitivePeerDependencies: - bufferutil @@ -14996,11 +15091,11 @@ packages: - utf-8-validate - zod - /@safe-global/safe-apps-sdk@8.1.0(typescript@5.2.2)(zod@3.21.4): + /@safe-global/safe-apps-sdk@8.1.0(typescript@5.2.2)(zod@3.22.0): resolution: {integrity: sha512-XJbEPuaVc7b9n23MqlF6c+ToYIS3f7P2Sel8f3cSBQ9WORE4xrSuvhMpK9fDSFqJ7by/brc+rmJR/5HViRr0/w==} dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.9.0 - viem: 1.21.4(typescript@5.2.2)(zod@3.21.4) + viem: 1.21.4(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - bufferutil - encoding @@ -15018,6 +15113,9 @@ packages: /@scure/base@1.1.3: resolution: {integrity: sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==} + /@scure/base@1.1.9: + resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} + /@scure/bip32@1.1.5: resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} dependencies: @@ -15039,6 +15137,13 @@ packages: '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 + /@scure/bip32@1.5.0: + resolution: {integrity: sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==} + dependencies: + '@noble/curves': 1.6.0 + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.9 + /@scure/bip39@1.1.1: resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} dependencies: @@ -15051,6 +15156,12 @@ packages: '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 + /@scure/bip39@1.4.0: + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} + dependencies: + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.9 + /@sentry-internal/feedback@7.101.1: resolution: {integrity: sha512-fOKDMVvLX+FuJHJszKBvRg1m7+fd4hchqRnZ9DDfitT6P5Ppl0gbEt/LStqu8Wq5M0tna+hpdwHlVEt7gZVKzw==} engines: {node: '>=12'} @@ -16889,7 +17000,7 @@ packages: vite: ^3.0.0 || ^4.0.0 dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.2.2)(vite@4.3.9) - '@rollup/pluginutils': 5.0.4(rollup@2.78.0) + '@rollup/pluginutils': 5.0.4(rollup@3.29.4) '@storybook/builder-vite': 7.4.6(typescript@5.2.2)(vite@4.3.9) '@storybook/react': 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2) '@vitejs/plugin-react': 3.1.0(vite@4.3.9) @@ -19049,7 +19160,7 @@ packages: pretty-format: 29.7.0 dev: true - /@wagmi/connectors@4.1.19(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /@wagmi/connectors@4.1.19(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-7OmdvepGCmzjGlY+pT7SgItgDd+eo7J2q50PywtnZ8xIdIEJUiwDm37izwQH0S7ZH8EL/9XkmOuz9hV5ORwn8Q==} peerDependencies: '@wagmi/core': 2.6.10 @@ -19061,13 +19172,13 @@ packages: dependencies: '@coinbase/wallet-sdk': 3.9.1 '@metamask/sdk': 0.14.3(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4) - '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.21.4) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.22.0) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) '@walletconnect/ethereum-provider': 2.11.2(@types/react@18.2.14)(@upstash/redis@1.22.1)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19093,7 +19204,7 @@ packages: - zod dev: false - /@wagmi/connectors@4.1.26(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /@wagmi/connectors@4.1.26(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-0bANLzi4gZcszPnCj3l7+DPztCG+L+W1Zm/a02YmEh2MaQC/blBsbAdb2JALdW66HJJE8m4cNZjPJPTsS2/MQQ==} peerDependencies: '@wagmi/core': 2.6.17 @@ -19105,13 +19216,13 @@ packages: dependencies: '@coinbase/wallet-sdk': 3.9.1 '@metamask/sdk': 0.14.3(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4) - '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.21.4) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.22.0) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) '@walletconnect/ethereum-provider': 2.11.2(@types/react@18.2.14)(@upstash/redis@1.22.1)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19137,7 +19248,7 @@ packages: - zod dev: false - /@wagmi/connectors@4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14): + /@wagmi/connectors@4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35): resolution: {integrity: sha512-0bANLzi4gZcszPnCj3l7+DPztCG+L+W1Zm/a02YmEh2MaQC/blBsbAdb2JALdW66HJJE8m4cNZjPJPTsS2/MQQ==} peerDependencies: '@wagmi/core': 2.6.17 @@ -19149,13 +19260,13 @@ packages: dependencies: '@coinbase/wallet-sdk': 3.9.1 '@metamask/sdk': 0.14.3(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4) - '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.21.4) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.22.0) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) '@walletconnect/ethereum-provider': 2.11.2(@types/react@18.2.14)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19181,7 +19292,7 @@ packages: - zod dev: true - /@wagmi/connectors@4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /@wagmi/connectors@4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-0bANLzi4gZcszPnCj3l7+DPztCG+L+W1Zm/a02YmEh2MaQC/blBsbAdb2JALdW66HJJE8m4cNZjPJPTsS2/MQQ==} peerDependencies: '@wagmi/core': 2.6.17 @@ -19193,13 +19304,13 @@ packages: dependencies: '@coinbase/wallet-sdk': 3.9.1 '@metamask/sdk': 0.14.3(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4) - '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.21.4) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.22.0) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) '@walletconnect/ethereum-provider': 2.11.2(@types/react@18.2.14)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19225,7 +19336,7 @@ packages: - zod dev: true - /@wagmi/connectors@4.1.26(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14): + /@wagmi/connectors@4.1.26(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35): resolution: {integrity: sha512-0bANLzi4gZcszPnCj3l7+DPztCG+L+W1Zm/a02YmEh2MaQC/blBsbAdb2JALdW66HJJE8m4cNZjPJPTsS2/MQQ==} peerDependencies: '@wagmi/core': 2.6.17 @@ -19237,13 +19348,13 @@ packages: dependencies: '@coinbase/wallet-sdk': 3.9.1 '@metamask/sdk': 0.14.3(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0) - '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.21.4) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.22.0) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) '@walletconnect/ethereum-provider': 2.11.2(@types/react@18.2.14)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19269,7 +19380,7 @@ packages: - zod dev: false - /@wagmi/connectors@4.1.26(@wagmi/core@2.6.17)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /@wagmi/connectors@4.1.26(@wagmi/core@2.6.17)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-0bANLzi4gZcszPnCj3l7+DPztCG+L+W1Zm/a02YmEh2MaQC/blBsbAdb2JALdW66HJJE8m4cNZjPJPTsS2/MQQ==} peerDependencies: '@wagmi/core': 2.6.17 @@ -19281,13 +19392,13 @@ packages: dependencies: '@coinbase/wallet-sdk': 3.9.1 '@metamask/sdk': 0.14.3(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0) - '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.21.4) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.2.2)(zod@3.22.0) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.2.2)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) '@walletconnect/ethereum-provider': 2.11.2(@types/react@18.2.14)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19313,7 +19424,7 @@ packages: - zod dev: false - /@wagmi/core@2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14): + /@wagmi/core@2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35): resolution: {integrity: sha512-Ghr7PlD5HO1YJrsaC52j/csgaigBAiTR7cFiwrY7WdwvWLsR5na4Dv6KfHTU3d3al0CKDLanQdRS5nB4mX1M+g==} peerDependencies: '@tanstack/query-core': '>=5.0.0' @@ -19326,9 +19437,9 @@ packages: optional: true dependencies: eventemitter3: 5.0.1 - mipd: 0.0.5(typescript@5.2.2)(zod@3.21.4) + mipd: 0.0.5(typescript@5.2.2)(zod@3.22.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) zustand: 4.4.1(@types/react@18.2.14)(react@18.2.0) transitivePeerDependencies: - '@types/react' @@ -19338,7 +19449,7 @@ packages: - utf-8-validate - zod - /@wagmi/core@2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /@wagmi/core@2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-Ghr7PlD5HO1YJrsaC52j/csgaigBAiTR7cFiwrY7WdwvWLsR5na4Dv6KfHTU3d3al0CKDLanQdRS5nB4mX1M+g==} peerDependencies: '@tanstack/query-core': '>=5.0.0' @@ -19351,9 +19462,9 @@ packages: optional: true dependencies: eventemitter3: 5.0.1 - mipd: 0.0.5(typescript@5.2.2)(zod@3.21.4) + mipd: 0.0.5(typescript@5.2.2)(zod@3.22.0) typescript: 5.2.2 - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) zustand: 4.4.1(@types/react@18.2.14)(react@18.2.0) transitivePeerDependencies: - '@types/react' @@ -20041,7 +20152,7 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: false - /abitype@0.9.8(typescript@5.2.2)(zod@3.21.4): + /abitype@0.9.8(typescript@5.2.2)(zod@3.22.0): resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==} peerDependencies: typescript: 5.2.2 @@ -20053,10 +20164,10 @@ packages: optional: true dependencies: typescript: 5.2.2 - zod: 3.21.4 + zod: 3.22.0 - /abitype@1.0.0(typescript@5.2.2)(zod@3.21.4): - resolution: {integrity: sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==} + /abitype@1.0.6(typescript@5.2.2)(zod@3.22.0): + resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} peerDependencies: typescript: 5.2.2 zod: ^3 >=3.22.0 @@ -20067,7 +20178,7 @@ packages: optional: true dependencies: typescript: 5.2.2 - zod: 3.21.4 + zod: 3.22.0 /abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -26338,6 +26449,7 @@ packages: /eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) @@ -27351,8 +27463,8 @@ packages: json-schema-to-ts: 2.9.2 openapi-types: 12.1.3 tslib: 2.6.2 - zod: 3.21.4 - zod-to-json-schema: 3.21.4(zod@3.21.4) + zod: 3.22.0 + zod-to-json-schema: 3.21.4(zod@3.22.0) dev: false /figures@2.0.0: @@ -28238,6 +28350,7 @@ packages: /glob@7.1.7: resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + deprecated: Glob versions prior to v9 are no longer supported dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -30102,6 +30215,13 @@ packages: dependencies: ws: 8.13.0 + /isows@1.0.6(ws@8.18.0): + resolution: {integrity: sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.18.0 + /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} @@ -31236,7 +31356,7 @@ packages: dependencies: copy-anything: 2.0.6 parse-node-version: 1.0.1 - tslib: 2.6.2 + tslib: 2.8.0 optionalDependencies: errno: 0.1.8 graceful-fs: 4.2.11 @@ -32185,6 +32305,11 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + /meriyah@4.4.2: + resolution: {integrity: sha512-fENZIbs4tscI3IGRGtPrCoW4H4oGzVQrQCVCGRv+92kFXKkvxr52ZNR684ICvDC/UBWg9ioGc2X6pMnWOtRYwA==} + engines: {node: '>=10.4.0'} + dev: false + /merkle-patricia-tree@2.3.2: resolution: {integrity: sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==} dependencies: @@ -32957,7 +33082,7 @@ packages: minipass: 3.3.6 yallist: 4.0.0 - /mipd@0.0.5(typescript@5.2.2)(zod@3.21.4): + /mipd@0.0.5(typescript@5.2.2)(zod@3.22.0): resolution: {integrity: sha512-gbKA784D2WKb5H/GtqEv+Ofd1S9Zj+Z/PGDIl1u1QAbswkxD28BQ5bSXQxkeBzPBABg1iDSbiwGG1XqlOxRspA==} peerDependencies: typescript: 5.2.2 @@ -32966,7 +33091,7 @@ packages: optional: true dependencies: typescript: 5.2.2 - viem: 1.21.4(typescript@5.2.2)(zod@3.21.4) + viem: 1.21.4(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -39294,6 +39419,9 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + /tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} + /tsort@0.0.1: resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} @@ -40438,7 +40566,7 @@ packages: unist-util-stringify-position: 3.0.3 vfile-message: 3.1.4 - /viem@1.21.4(typescript@5.2.2)(zod@3.21.4): + /viem@1.21.4(typescript@5.2.2)(zod@3.22.0): resolution: {integrity: sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==} peerDependencies: typescript: 5.2.2 @@ -40451,7 +40579,7 @@ packages: '@noble/hashes': 1.3.2 '@scure/bip32': 1.3.2 '@scure/bip39': 1.2.1 - abitype: 0.9.8(typescript@5.2.2)(zod@3.21.4) + abitype: 0.9.8(typescript@5.2.2)(zod@3.22.0) isows: 1.0.3(ws@8.13.0) typescript: 5.2.2 ws: 8.13.0 @@ -40460,23 +40588,24 @@ packages: - utf-8-validate - zod - /viem@2.8.14(typescript@5.2.2)(zod@3.21.4): - resolution: {integrity: sha512-K5u9OoyPQ7W8VPa6xY2m7oazuhemp0xuK9Ur8AkaXHtcusism9keTXDDaCw6WWFK3YR9HSojHJOtuVQqvRz0ug==} + /viem@2.21.35(typescript@5.2.2)(zod@3.22.0): + resolution: {integrity: sha512-f3EFc5JILeA9veuNymUN8HG/nKP9ykC0NCgwFrZWuxcCc822GaP0IEnkRBsHGqmjwbz//FxJFmvtx7TBcdVs0A==} peerDependencies: typescript: 5.2.2 peerDependenciesMeta: typescript: optional: true dependencies: - '@adraffy/ens-normalize': 1.10.0 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@scure/bip32': 1.3.2 - '@scure/bip39': 1.2.1 - abitype: 1.0.0(typescript@5.2.2)(zod@3.21.4) - isows: 1.0.3(ws@8.13.0) + '@adraffy/ens-normalize': 1.11.0 + '@noble/curves': 1.6.0 + '@noble/hashes': 1.5.0 + '@scure/bip32': 1.5.0 + '@scure/bip39': 1.4.0 + abitype: 1.0.6(typescript@5.2.2)(zod@3.22.0) + isows: 1.0.6(ws@8.18.0) typescript: 5.2.2 - ws: 8.13.0 + webauthn-p256: 0.0.10 + ws: 8.18.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -40619,7 +40748,7 @@ packages: xml-name-validator: 4.0.0 dev: false - /wagmi@2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(@upstash/redis@1.22.1)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /wagmi@2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(@upstash/redis@1.22.1)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-K/9qk6+t/+NKFdbQyB7LtFgl3UXnGjvgyzAyfMQ+dF56uTSJipQwc94CSlN8kdQXTIOvhUSK2P7WJrdTEd15AA==} peerDependencies: '@tanstack/react-query': '>=5.0.0' @@ -40631,12 +40760,12 @@ packages: optional: true dependencies: '@tanstack/react-query': 4.28.0(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0) - '@wagmi/connectors': 4.1.26(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@wagmi/connectors': 4.1.26(@types/react@18.2.14)(@upstash/redis@1.22.1)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(rollup@3.29.4)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) react: 18.2.0 typescript: 5.2.2 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -40663,7 +40792,7 @@ packages: - zod dev: false - /wagmi@2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /wagmi@2.5.20(@tanstack/react-query@4.28.0)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-K/9qk6+t/+NKFdbQyB7LtFgl3UXnGjvgyzAyfMQ+dF56uTSJipQwc94CSlN8kdQXTIOvhUSK2P7WJrdTEd15AA==} peerDependencies: '@tanstack/react-query': '>=5.0.0' @@ -40675,12 +40804,12 @@ packages: optional: true dependencies: '@tanstack/react-query': 4.28.0(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0) - '@wagmi/connectors': 4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@wagmi/connectors': 4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) react: 18.2.0 typescript: 5.2.2 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -40707,7 +40836,7 @@ packages: - zod dev: true - /wagmi@2.5.20(@tanstack/react-query@5.29.2)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14): + /wagmi@2.5.20(@tanstack/react-query@5.29.2)(@types/react@18.2.14)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35): resolution: {integrity: sha512-K/9qk6+t/+NKFdbQyB7LtFgl3UXnGjvgyzAyfMQ+dF56uTSJipQwc94CSlN8kdQXTIOvhUSK2P7WJrdTEd15AA==} peerDependencies: '@tanstack/react-query': '>=5.0.0' @@ -40719,12 +40848,12 @@ packages: optional: true dependencies: '@tanstack/react-query': 5.29.2(react@18.2.0) - '@wagmi/connectors': 4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + '@wagmi/connectors': 4.1.26(@types/react@18.2.14)(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) react: 18.2.0 typescript: 5.2.2 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -40751,7 +40880,7 @@ packages: - zod dev: true - /wagmi@2.5.20(@tanstack/react-query@5.29.2)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14): + /wagmi@2.5.20(@tanstack/react-query@5.29.2)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35): resolution: {integrity: sha512-K/9qk6+t/+NKFdbQyB7LtFgl3UXnGjvgyzAyfMQ+dF56uTSJipQwc94CSlN8kdQXTIOvhUSK2P7WJrdTEd15AA==} peerDependencies: '@tanstack/react-query': '>=5.0.0' @@ -40763,12 +40892,12 @@ packages: optional: true dependencies: '@tanstack/react-query': 5.29.2(react@18.2.0) - '@wagmi/connectors': 4.1.26(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14) + '@wagmi/connectors': 4.1.26(@wagmi/core@2.6.17)(react-dom@18.2.0)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35) react: 18.2.0 typescript: 5.2.2 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -40795,7 +40924,7 @@ packages: - zod dev: false - /wagmi@2.5.20(@tanstack/react-query@5.29.2)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4): + /wagmi@2.5.20(@tanstack/react-query@5.29.2)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0): resolution: {integrity: sha512-K/9qk6+t/+NKFdbQyB7LtFgl3UXnGjvgyzAyfMQ+dF56uTSJipQwc94CSlN8kdQXTIOvhUSK2P7WJrdTEd15AA==} peerDependencies: '@tanstack/react-query': '>=5.0.0' @@ -40807,12 +40936,12 @@ packages: optional: true dependencies: '@tanstack/react-query': 5.29.2(react@18.2.0) - '@wagmi/connectors': 4.1.26(@wagmi/core@2.6.17)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) - '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) + '@wagmi/connectors': 4.1.26(@wagmi/core@2.6.17)(react-native@0.73.7)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) + '@wagmi/core': 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.21.35)(zod@3.22.0) react: 18.2.0 typescript: 5.2.2 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.8.14(typescript@5.2.2)(zod@3.21.4) + viem: 2.21.35(typescript@5.2.2)(zod@3.22.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -41300,6 +41429,7 @@ packages: /web3-provider-engine@14.2.1: resolution: {integrity: sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==} + deprecated: 'This package has been deprecated, see the README for details: https://github.com/MetaMask/web3-provider-engine' dependencies: async: 2.6.4 backoff: 2.5.0 @@ -41496,6 +41626,12 @@ packages: - utf-8-validate optional: true + /webauthn-p256@0.0.10: + resolution: {integrity: sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==} + dependencies: + '@noble/curves': 1.6.0 + '@noble/hashes': 1.5.0 + /webcrypto-core@1.7.7: resolution: {integrity: sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==} dependencies: @@ -41927,6 +42063,18 @@ packages: utf-8-validate: optional: true + /ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + /ws@8.5.0: resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} @@ -42281,16 +42429,20 @@ packages: requiresBuild: true optional: true - /zod-to-json-schema@3.21.4(zod@3.21.4): + /zod-to-json-schema@3.21.4(zod@3.22.0): resolution: {integrity: sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw==} peerDependencies: zod: ^3.21.4 dependencies: - zod: 3.21.4 + zod: 3.22.0 dev: false /zod@3.21.4: resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} + dev: false + + /zod@3.22.0: + resolution: {integrity: sha512-y5KZY/ssf5n7hCGDGGtcJO/EBJEm5Pa+QQvFBeyMOtnFYOSflalxIFFvdaYevPhePcmcKC4aTbFkCcXN7D0O8Q==} /zrender@5.4.4: resolution: {integrity: sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==} diff --git a/protocols/route-processor/.env.example b/protocols/route-processor/.env.example index ce1584298c..816fd63db8 100644 --- a/protocols/route-processor/.env.example +++ b/protocols/route-processor/.env.example @@ -7,4 +7,4 @@ MNEMONIC="test test test test test test test test test test test junk" REPORT_GAS=false TENDERLY_PROJECT= TENDERLY_USERNAME= -PRIVATE_KEY= \ No newline at end of file +PRIVATE_KEY= diff --git a/protocols/route-processor/contracts/Approve.sol b/protocols/route-processor/contracts/Approve.sol index b9b86c064c..099a4028e4 100644 --- a/protocols/route-processor/contracts/Approve.sol +++ b/protocols/route-processor/contracts/Approve.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; diff --git a/protocols/route-processor/contracts/InputStream.sol b/protocols/route-processor/contracts/InputStream.sol index b1056c28ae..e9c82bc1be 100644 --- a/protocols/route-processor/contracts/InputStream.sol +++ b/protocols/route-processor/contracts/InputStream.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; /** @notice Simple read stream */ library InputStream { diff --git a/protocols/route-processor/contracts/RouteProcessor.sol b/protocols/route-processor/contracts/RouteProcessor.sol index c45ea67343..8178019ba9 100644 --- a/protocols/route-processor/contracts/RouteProcessor.sol +++ b/protocols/route-processor/contracts/RouteProcessor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; import '../interfaces/IUniswapV2Pair.sol'; import '../interfaces/IBentoBoxMinimal.sol'; diff --git a/protocols/route-processor/contracts/RouteProcessor3.sol b/protocols/route-processor/contracts/RouteProcessor3.sol index 2f03cc198f..08cd9a06d0 100644 --- a/protocols/route-processor/contracts/RouteProcessor3.sol +++ b/protocols/route-processor/contracts/RouteProcessor3.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; import '../interfaces/IUniswapV2Pair.sol'; import '../interfaces/IUniswapV3Pool.sol'; diff --git a/protocols/route-processor/contracts/RouteProcessor3_1.sol b/protocols/route-processor/contracts/RouteProcessor3_1.sol index 6eecbf02ff..53d4faad22 100644 --- a/protocols/route-processor/contracts/RouteProcessor3_1.sol +++ b/protocols/route-processor/contracts/RouteProcessor3_1.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; import '../interfaces/IUniswapV2Pair.sol'; import '../interfaces/IUniswapV3Pool.sol'; diff --git a/protocols/route-processor/contracts/RouteProcessor3_2.sol b/protocols/route-processor/contracts/RouteProcessor3_2.sol index 14bb5e7514..65fe9a04fa 100644 --- a/protocols/route-processor/contracts/RouteProcessor3_2.sol +++ b/protocols/route-processor/contracts/RouteProcessor3_2.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; import '../interfaces/IUniswapV2Pair.sol'; import '../interfaces/IUniswapV3Pool.sol'; diff --git a/protocols/route-processor/contracts/RouteProcessor4.sol b/protocols/route-processor/contracts/RouteProcessor4.sol index f9436e48c3..955e4c6a33 100644 --- a/protocols/route-processor/contracts/RouteProcessor4.sol +++ b/protocols/route-processor/contracts/RouteProcessor4.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.10; +pragma solidity =0.8.25; import '../interfaces/IUniswapV2Pair.sol'; import '../interfaces/IUniswapV3Pool.sol'; diff --git a/protocols/route-processor/hardhat.config.cts b/protocols/route-processor/hardhat.config.cts index a0309d1a72..56d52c96b9 100644 --- a/protocols/route-processor/hardhat.config.cts +++ b/protocols/route-processor/hardhat.config.cts @@ -86,7 +86,7 @@ const config: HardhatUserConfig = { solidity: { compilers: [ { - version: '0.8.10', + version: '0.8.25', settings: { optimizer: { enabled: true, diff --git a/protocols/route-processor/interfaces/ITridentCLPool.sol b/protocols/route-processor/interfaces/ITridentCLPool.sol index 0859307ef1..bcf090c393 100644 --- a/protocols/route-processor/interfaces/ITridentCLPool.sol +++ b/protocols/route-processor/interfaces/ITridentCLPool.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.10; +pragma solidity =0.8.25; interface ITridentCLPool { function token0() external returns (address); diff --git a/protocols/route-processor/interfaces/IUniswapV3Pool.sol b/protocols/route-processor/interfaces/IUniswapV3Pool.sol index b0a729aca8..18d03b1125 100644 --- a/protocols/route-processor/interfaces/IUniswapV3Pool.sol +++ b/protocols/route-processor/interfaces/IUniswapV3Pool.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.10; +pragma solidity =0.8.25; interface IUniswapV3Pool { function token0() external returns (address); diff --git a/protocols/route-processor/interfaces/IWETH.sol b/protocols/route-processor/interfaces/IWETH.sol index 713b55c89e..da15bb8ffd 100644 --- a/protocols/route-processor/interfaces/IWETH.sol +++ b/protocols/route-processor/interfaces/IWETH.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.10; +pragma solidity =0.8.25; interface IWETH { function deposit() external payable; diff --git a/protocols/route-processor/package.json b/protocols/route-processor/package.json index 285f896cec..8b6bdad8f3 100644 --- a/protocols/route-processor/package.json +++ b/protocols/route-processor/package.json @@ -68,6 +68,6 @@ "ts-generator": "0.1.1", "ts-node": "10.9.1", "typescript": "5.2.2", - "viem": "2.8.14" + "viem": "2.21.35" } } diff --git a/protocols/route-processor/test/DataFetcher.test.ts b/protocols/route-processor/test/DataFetcher.test.ts index 750bb633f5..db5418880e 100644 --- a/protocols/route-processor/test/DataFetcher.test.ts +++ b/protocols/route-processor/test/DataFetcher.test.ts @@ -1,6 +1,23 @@ -import { ChainId, chainName } from 'sushi/chain' -import { FRAX, SUSHI, Token, Type, USDC, USDT, WNATIVE } from 'sushi/currency' -import { DataFetcher } from 'sushi/router' +import assert from 'assert' +import { ChainId, TESTNET_CHAIN_IDS, chainName } from 'sushi/chain' +import { + DAI, + FRAX, + SUSHI, + Token, + Type, + USDB, + USDC, + USDT, + WNATIVE, +} from 'sushi/currency' +import { + DataFetcher, + LiquidityProviders, + Router, + UniV3LiquidityProviders, +} from 'sushi/router' +import { UniswapV3BaseProvider } from '../../../packages/sushi/src/router/liquidity-providers/UniswapV3Base.js' async function testDF( _chainName: string, @@ -9,49 +26,109 @@ async function testDF( t1: Type | undefined, name0: string, name1: string, -) { - if (!t0 || !t1) return +): Promise> { + const dexPools: Record = {} + + if (!t0 || !t1) return dexPools + const start = performance.now() - await dataFetcher.fetchPoolsForToken(t0, t1) + await dataFetcher.fetchPoolsForToken(t0, t1, undefined) const pools = dataFetcher.getCurrentPoolCodeMap(t0, t1) const time = Math.round(performance.now() - start) console.log( ` found pools(${name0}-${name1}): ${pools.size} time=${time}ms`, ) dataFetcher.providers.forEach((p) => { + const dexName = p.getType() const poolCodes = p.getCurrentPoolList(t0 as Token, t1 as Token) if (poolCodes.length) console.log( ` ${p.getPoolProviderName()} pools: ${poolCodes.length}`, ) + // ignore non uni protocol based dexes + if ( + dexName !== LiquidityProviders.Trident && + dexName !== LiquidityProviders.CurveSwap && + dexName !== LiquidityProviders.NativeWrap + ) + dexPools[dexName] = poolCodes.length }) + return dexPools +} + +// checks if all available dexes on a chain have found a pool or not and returns the missing dexes names +function reportMissingDexes(reports: Record[]): { + hasMissingDex: boolean + missingDexNames: string[] +} { + const dexNames = reports.map((v) => Object.keys(v)).find((v) => v.length > 0) + if (!dexNames) return { hasMissingDex: true, missingDexNames: [] } + + const missingDexNames = [] + for (const name of dexNames) { + let poolsCount = 0 + for (const element of reports) poolsCount += element[name] ?? 0 + if (poolsCount === 0) missingDexNames.push(name) + } + + if (missingDexNames.length) return { hasMissingDex: true, missingDexNames } + else return { hasMissingDex: false, missingDexNames } +} + +// tries to find a route for a token pair from current fetched pools +function findRoute( + dataFetcher: DataFetcher, + fromToken: Type, + toToken: Type, + chainId: ChainId, + liquidityProviders?: LiquidityProviders[], +): boolean { + try { + // find the best route map + const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken) + const route = Router.findBestRoute( + pcMap, + chainId, + fromToken, + BigInt(`1${'0'.repeat(fromToken.decimals)}`), + toToken, + 30e9, + liquidityProviders, + ) + // call rp4 route data encoder to build route data + Router.routeProcessor4Params( + pcMap, + route, + fromToken, + toToken, + `0x${'1'.repeat(40)}`, + `0x${'2'.repeat(40)}`, + ) + return route.status !== 'NoWay' + } catch { + // no route found + return false + } } -const chainIds = [ - ChainId.ARBITRUM_NOVA, - ChainId.ARBITRUM, - ChainId.AVALANCHE, - ChainId.BOBA, +// exclude testnets and unsupported chains (chains with no dex/pool) +const excludedChains = [ + ...TESTNET_CHAIN_IDS, + ChainId.HECO, + ChainId.PALM, ChainId.BOBA_AVAX, - ChainId.BOBA_BNB, - ChainId.BSC, - ChainId.BTTC, - ChainId.CELO, - ChainId.ETHEREUM, - ChainId.FANTOM, - ChainId.FUSE, - ChainId.GNOSIS, - ChainId.HARMONY, - ChainId.KAVA, - ChainId.METIS, - ChainId.MOONBEAM, - ChainId.MOONRIVER, - ChainId.OPTIMISM, - ChainId.POLYGON, + ChainId.ZKSYNC_ERA, ] +const chainIds = Object.values(ChainId).filter((v) => { + if (excludedChains.every((e) => v !== e) && process?.env?.CHAIN) { + return v === ChainId[process.env.CHAIN as keyof typeof ChainId] + } + return false +}) + async function runTest() { - describe('DataFetcher Pools/Time check', async () => { + describe.only('DataFetcher Pools/Time check', async () => { chainIds.forEach((chainId) => { //if (chainId !== ChainId.OPTIMISM) return const chName = chainName[chainId] @@ -61,34 +138,395 @@ async function runTest() { it(`${chName}(${chainId})`, async () => { dataFetcher.startDataFetching() console.log(chName) - await testDF( - chName, - dataFetcher, - WNATIVE[chainId], - USDC[chainId as keyof typeof USDC], - 'WNATIVE', - 'USDC', - ) - await testDF( - chName, - dataFetcher, - SUSHI[chainId as keyof typeof SUSHI], - FRAX[chainId as keyof typeof FRAX], - 'SUSHI', - 'FRAX', + const allFoundPools = [] + const foundRouteReports = [] + + // a pool with this pair is available in most dexes and chains, but some may not have this, so + // for those, other pairs are tried if there happened to be a missing dex from previous results + allFoundPools.push( + await testDF( + chName, + dataFetcher, + WNATIVE[chainId], + USDC[chainId as keyof typeof USDC], + 'WNATIVE', + 'USDC', + ), ) - await testDF( - chName, - dataFetcher, - SUSHI[chainId as keyof typeof SUSHI], - USDT[chainId as keyof typeof USDT], - 'SUSHI', - 'USDT', + + // check that route is found and rp4 encoder encoded a route data correctly + // this is repeated for each pair throughout the test + foundRouteReports.push( + findRoute( + dataFetcher, + WNATIVE[chainId], + USDC[chainId as keyof typeof USDC], + chainId, + ), ) + await sleep(60_000) + + // only for quickswapv3 + if (chainId === ChainId.POLYGON) { + const foundRoute = findRoute( + dataFetcher, + WNATIVE[chainId], + USDC[chainId as keyof typeof USDC], + chainId, + [LiquidityProviders.QuickSwapV3], + ) + assert.ok(foundRoute) + foundRouteReports.push(foundRoute) + } + + // only for pancakev3 with 0.2.5% fee pool pair + if (chainId === ChainId.BSC) { + allFoundPools.push( + await testDF( + chName, + dataFetcher, + WNATIVE[chainId], + USDT[chainId as keyof typeof USDT], + 'WNATIVE', + 'USDT', + ), + ) + const pcMap = dataFetcher.getCurrentPoolCodeMap( + WNATIVE[chainId], + USDT[chainId as keyof typeof USDT], + ) + assert.ok(!!pcMap.get('0x1401ff943D08a7E098328C1d3a9d388923B115D2')) + foundRouteReports.push( + findRoute( + dataFetcher, + WNATIVE[chainId], + USDT[chainId as keyof typeof USDT], + chainId, + [LiquidityProviders.PancakeSwapV3], + ), + ) + await sleep(60_000) + } + + // only for kimv4 on base + if (chainId === ChainId.BASE) { + const token = new Token({ + chainId: ChainId.BASE, + address: '0x5dC25aA049837B696d1dc0F966aC8DF1491f819B', + decimals: 18, + symbol: 'KIM', + }) + allFoundPools.push( + await testDF( + chName, + dataFetcher, + token, + WNATIVE[chainId as keyof typeof WNATIVE], + 'KIM', + 'WETH', + ), + ) + + foundRouteReports.push( + findRoute( + dataFetcher, + token, + WNATIVE[chainId as keyof typeof WNATIVE], + chainId, + [LiquidityProviders.KimV4], + ), + ) + await sleep(60_000) + } + + // only for horizon on linea + if (chainId === ChainId.LINEA) { + const token = new Token({ + chainId: ChainId.LINEA, + address: '0x7d43AABC515C356145049227CeE54B608342c0ad', + decimals: 18, + symbol: 'BUSD', + }) + allFoundPools.push( + await testDF( + chName, + dataFetcher, + token, + WNATIVE[chainId as keyof typeof WNATIVE], + 'BUSD', + 'WETH', + ), + ) + + foundRouteReports.push( + findRoute( + dataFetcher, + token, + WNATIVE[chainId as keyof typeof WNATIVE], + chainId, + [LiquidityProviders.Horizon], + ), + ) + await sleep(60_000) + } + + // only for Dfyn and JetSwap on fantom chain + if ( + chainId === ChainId.FANTOM && + reportMissingDexes(allFoundPools).hasMissingDex + ) { + allFoundPools.push( + await testDF( + chName, + dataFetcher, + WNATIVE[chainId], + DAI[chainId as keyof typeof DAI], + 'WNATIVE', + 'DAI', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + WNATIVE[chainId], + DAI[chainId as keyof typeof DAI], + chainId, + ), + ) + await sleep(60_000) + } + + // only for Blast chain + if ( + chainId === ChainId.BLAST && + reportMissingDexes(allFoundPools).hasMissingDex + ) { + allFoundPools.push( + await testDF( + chName, + dataFetcher, + WNATIVE[chainId], + USDB[chainId as keyof typeof USDB], + 'WNATIVE', + 'USDB', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + WNATIVE[chainId], + USDB[chainId as keyof typeof USDB], + chainId, + ), + ) + await sleep(60_000) + } + + // only for Blast chain + if ( + chainId === ChainId.BLAST && + reportMissingDexes(allFoundPools).hasMissingDex + ) { + const token0 = new Token({ + chainId: ChainId.BLAST, + address: '0x18755D2ceC785aB87680Edb8e117615E4B005430', + decimals: 18, + symbol: 'fwRING', + }) + const token1 = new Token({ + chainId: ChainId.BLAST, + address: '0x66714DB8F3397c767d0A602458B5b4E3C0FE7dd1', + decimals: 18, + symbol: 'fwWETH', + }) + allFoundPools.push( + await testDF( + chName, + dataFetcher, + token0, + token1, + 'fwRING', + 'fwWETH', + ), + ) + foundRouteReports.push( + findRoute(dataFetcher, token0, token1, chainId), + ) + await sleep(60_000) + } + + // only for Moonbeam chain + if ( + chainId === ChainId.MOONBEAM && + reportMissingDexes(allFoundPools).hasMissingDex + ) { + const token = new Token({ + chainId: ChainId.MOONBEAM, + address: '0xA649325Aa7C5093d12D6F98EB4378deAe68CE23F', + decimals: 18, + symbol: 'BUSD', + }) + allFoundPools.push( + await testDF( + chName, + dataFetcher, + token, + USDC[chainId as keyof typeof USDC], + 'USDC', + 'BUSD', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + token, + USDC[chainId as keyof typeof USDC], + chainId, + ), + ) + await sleep(60_000) + } + + // only for Elk dex on Moonriver since it only has 1 pool deployed which is with following pair + if ( + chainId === ChainId.MOONRIVER && + reportMissingDexes(allFoundPools).hasMissingDex + ) { + const token = new Token({ + chainId: ChainId.MOONRIVER, + address: '0xE1C110E1B1b4A1deD0cAf3E42BfBdbB7b5d7cE1C', + decimals: 18, + symbol: 'ELK', + }) + allFoundPools.push( + await testDF( + chName, + dataFetcher, + DAI[chainId as keyof typeof DAI], + token, + 'DAI', + 'ELK', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + DAI[chainId as keyof typeof DAI], + token, + chainId, + ), + ) + await sleep(60_000) + } + + // shared pairs for all chains and dexes + if (reportMissingDexes(allFoundPools).hasMissingDex) { + allFoundPools.push( + await testDF( + chName, + dataFetcher, + WNATIVE[chainId], + USDT[chainId as keyof typeof USDT], + 'WNATIVE', + 'USDT', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + WNATIVE[chainId], + USDT[chainId as keyof typeof USDT], + chainId, + ), + ) + await sleep(60_000) + } + + if (reportMissingDexes(allFoundPools).hasMissingDex) { + allFoundPools.push( + await testDF( + chName, + dataFetcher, + SUSHI[chainId as keyof typeof SUSHI], + FRAX[chainId as keyof typeof FRAX], + 'SUSHI', + 'FRAX', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + SUSHI[chainId as keyof typeof SUSHI], + FRAX[chainId as keyof typeof FRAX], + chainId, + ), + ) + await sleep(60_000) + } + + if (reportMissingDexes(allFoundPools).hasMissingDex) { + allFoundPools.push( + await testDF( + chName, + dataFetcher, + SUSHI[chainId as keyof typeof SUSHI], + USDT[chainId as keyof typeof USDT], + 'SUSHI', + 'USDT', + ), + ) + foundRouteReports.push( + findRoute( + dataFetcher, + SUSHI[chainId as keyof typeof SUSHI], + USDT[chainId as keyof typeof USDT], + chainId, + ), + ) + await sleep(60_000) + } + dataFetcher.stopDataFetching() + + // univ3 based dexes should all have correct fees/ticks + const invalidDexes = [] + for (const dex of dataFetcher.providers) { + const dexName = dex.getType() + // if the current provider is univ3 type, ensure its fees and ticks + if (UniV3LiquidityProviders.some((v) => v === dexName)) { + const res = await (dex as UniswapV3BaseProvider).ensureFeeAndTicks() + if (!res) invalidDexes.push(dexName) + } + } + assert.ok( + invalidDexes.length === 0, + `invalid fees/ticks at ${chName} for: ${invalidDexes.join(', ')}`, + ) + + // should have found route + assert.ok( + foundRouteReports.some((v) => v), + 'did not find any valid route', + ) + + // should not have any missing dex + const { hasMissingDex, missingDexNames } = + reportMissingDexes(allFoundPools) + if (hasMissingDex) { + if (!missingDexNames.length) + assert.fail(`found no pools for all available dexes on ${chName}`) + else + assert.fail( + `found no pools on ${chName} for: ${missingDexNames.join(', ')}`, + ) + } }) }) }) } +async function sleep(ms: number, msg = '') { + return new Promise((resolve) => setTimeout(() => resolve(msg), ms)) +} + runTest() diff --git a/protocols/tines-sandbox/contracts/ERC20Mock.sol b/protocols/tines-sandbox/contracts/ERC20Mock.sol index dd437fa4bc..2f1042affb 100644 --- a/protocols/tines-sandbox/contracts/ERC20Mock.sol +++ b/protocols/tines-sandbox/contracts/ERC20Mock.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity =0.8.25; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract ERC20Mock is ERC20 { diff --git a/protocols/tines-sandbox/contracts/TestRouter.sol b/protocols/tines-sandbox/contracts/TestRouter.sol index 2c5289bb4a..4cbd4521bc 100644 --- a/protocols/tines-sandbox/contracts/TestRouter.sol +++ b/protocols/tines-sandbox/contracts/TestRouter.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense -pragma solidity 0.8.10; +pragma solidity =0.8.25; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/protocols/tines-sandbox/hardhat.config.cts b/protocols/tines-sandbox/hardhat.config.cts index 889a2a0079..eda51c55ef 100644 --- a/protocols/tines-sandbox/hardhat.config.cts +++ b/protocols/tines-sandbox/hardhat.config.cts @@ -27,7 +27,7 @@ const config: HardhatUserConfig = { solidity: { compilers: [ { - version: '0.8.10', + version: '0.8.25', settings: { optimizer: { enabled: true, diff --git a/protocols/tines-sandbox/package.json b/protocols/tines-sandbox/package.json index 06b8dc0f01..24ace56f6a 100644 --- a/protocols/tines-sandbox/package.json +++ b/protocols/tines-sandbox/package.json @@ -76,6 +76,6 @@ "ts-node": "10.9.1", "tsup": "7.2.0", "typescript": "5.2.2", - "viem": "2.8.14" + "viem": "2.21.35" } }