Skip to content

CCIP SDK Browser Compatibility Workaround #131

@evgenii-bond

Description

@evgenii-bond

Problem

When using @chainlink/ccip-sdk@0.95.0 in a browser-based application with Vite, the SDK causes build failures because it bundles all blockchain dependencies (Solana, Sui, Aptos, TON) even when only EVM functionality is needed.

Error Messages

ERROR: No matching export in "@coral-xyz/anchor/dist/browser/index.js" for import "eventDiscriminator"
ERROR: No matching export for "BorshAccountsCoder"
ERROR: No matching export for "AnchorProvider"

Root Cause

The main entry point (@chainlink/ccip-sdk) imports all chain implementations in dist/index.js, which includes:

  • @coral-xyz/anchor (Solana) - Not browser-compatible
  • @mysten/sui (Sui)
  • @aptos-labs/ts-sdk (Aptos)
  • @ton/core (TON)

These dependencies are required in package.json even though most applications only use EVM chains.

Workaround Implementation

We've implemented a multi-layered workaround until the SDK provides proper modular exports:

1. Vite Plugin to Stub Non-EVM Modules

In vite.config.ts, we created a plugin that intercepts imports from non-EVM chains and replaces them with empty stubs:

function ccipSdkStubPlugin(): Plugin {
  const stubCode = `
    // Mock class that can be instantiated
    class MockClass {
      constructor(...args) {}
    }
    
    // Mock function that returns a mock
    const mockFunction = (...args) => ({});
    
    // @coral-xyz/anchor exports - all as MockClass
    export const AnchorProvider = MockClass;
    export const BorshCoder = MockClass;
    export const BorshAccountsCoder = MockClass;
    // ... all other exports
    export default {};
  `;

  const shouldStub = (id: string): boolean => {
    const normalizedId = id.replace(/\\/g, '/');
    return (
      normalizedId.includes('@chainlink/ccip-sdk/dist/solana') ||
      normalizedId.includes('@chainlink/ccip-sdk/dist/sui') ||
      normalizedId.includes('@chainlink/ccip-sdk/dist/aptos') ||
      normalizedId.includes('@chainlink/ccip-sdk/dist/ton') ||
      normalizedId.includes('@coral-xyz/anchor')
    );
  };

  return {
    name: 'ccip-sdk-stub',
    enforce: 'pre',
    resolveId(id, importer) {
      if (shouldStub(id)) {
        return '\0ccip-sdk-stub';
      }
      if (importer && shouldStub(importer)) {
        return '\0ccip-sdk-stub';
      }
      return null;
    },
    load(id) {
      if (id === '\0ccip-sdk-stub') {
        return stubCode;
      }
      return null;
    },
  };
}

2. ESBuild Configuration

Added esbuild options to handle optimization phase:

optimizeDeps: {
  exclude: [
    '@chainlink/ccip-sdk/dist/solana',
    '@chainlink/ccip-sdk/dist/sui',
    '@chainlink/ccip-sdk/dist/aptos',
    '@chainlink/ccip-sdk/dist/ton',
    '@coral-xyz/anchor',
  ],
  esbuildOptions: {
    plugins: [
      {
        name: 'ignore-non-evm-chains',
        setup(build) {
          build.onResolve({ filter: /@coral-xyz\/anchor/ }, () => ({
            path: 'data:text/javascript,export default {};',
            external: false,
          }));
          build.onResolve({ 
            filter: /@chainlink\/ccip-sdk\/dist\/(solana|sui|aptos|ton)/ 
          }, () => ({
            path: 'data:text/javascript,export default {};',
            external: false,
          }));
        },
      },
    ],
  },
}

Future Improvements

This is a temporary workaround. Ideally, the SDK should:

  1. Make non-EVM dependencies optional in package.json:

    {
      "optionalDependencies": {
        "@coral-xyz/anchor": "^0.29.0",
        "@mysten/sui": "^1.45.2",
        "@aptos-labs/ts-sdk": "^5.2.1",
        "@ton/core": "0.63.0"
      }
    }
  2. Provide separate entry points per chain:

    {
      "exports": {
        "./evm": "./dist/evm.js",
        "./solana": "./dist/solana.js",
        "./sui": "./dist/sui.js"
      }
    }
  3. Use conditional/dynamic imports for non-EVM chains

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions