Using the Yield.xyz Widget

The Yield.xyz Widget is the fastest way to integrate on-chain yield flows into any app — no backend, no custom logic. Built on top of the Yield.xyz API, the Widget supports staking, restaking, vaults, and more — all from a single drop-in interface

Yield.xyz Widget is mainly built as a React component and can be easily added in your application by importing it. There is also an option to use fully bundled widget component which can be added in any javascript library. If your application is already using React, using it as a React component will reduce bundle size of your application. If not, there is option for fully bundled component.

Installation

To install Yield.xyz Widget:

npm install @stakekit/widget

yarn add @stakekit/widget

pnpm add @stakekit/widget

Usage

To use Yield.xyz Widget, first you'll need API key from Yield.xyz.

React component usage

After you get the API key, you can import styles and widget component:

  import "@stakekit/widget/package/css";
  import { SKApp, darkTheme } from "@stakekit/widget";

  const App = () => {
    return (
      <SKApp
        apiKey="your-api-key"
        theme={darkTheme}
      />
    )
  }

Bundled component usage

  import "@stakekit/widget/bundle/css";
  import { renderSKWidget, lightTheme } from "@stakekit/widget/bundle";

  renderSKWidget({
    container: document.getElementById("sk_widget_container")!,
    apiKey: 'your-api-key',
    theme: lightTheme
  });

After this is done, you can start using the widget.

Params

To open the widget on a specific yield opportunity you need to pass the parameter yieldId as a prop to the component. Below is are examples that will open the widget on theethereum-eth-lido-staking. All possible yieldIds can be retrieved from the v2/yields endpoint

React component

  import "@stakekit/widget/package/css";
  import { SKApp, darkTheme } from "@stakekit/widget";

  const App = () => {
    return (
      <SKApp
        apiKey="your-api-key"
        theme={darkTheme}
				yieldId="ethereum-eth-lido-staking"
      />
    )
  }

Bundled component

  import "@stakekit/widget/bundle/css";
  import { renderSKWidget, lightTheme } from "@stakekit/widget/bundle";

  renderSKWidget({
    container: document.getElementById("sk_widget_container")!,
    apiKey: 'your-api-key',
    theme: lightTheme,
    yieldId="ethereum-eth-lido-staking"
  });

Style customization

You can customize look of widget by overriding darkTheme or lightTheme, or providing your own theme and passing it to Yield.xyz. If theme is not provided, widget will use default lightTheme.

import "@stakekit/widget/package/css";
import { SKApp } from "@stakekit/widget";

const App = () => {
  return (
    <SKApp
      apiKey="your-api-key"
      theme={{
        lightMode: {
          font: { body: '"IBM Plex Mono", monospace' },
          color: {
            primaryButtonBackground: "#8323fd",
            primaryButtonActiveOutline: "#8323fd",
            primaryButtonOutline: "#8323fd",
          },
          borderRadius: { primaryButton: "0", widgetBorderRadius: "10px" },
        },
      }}
    />
  );
};
import "@stakekit/widget/package/css";
import { SKApp, darkTheme } from "@stakekit/widget";

const App = () => {
  return (
    <SKApp
      apiKey="your-api-key"
      theme={{
        ...darkTheme,
        borderRadius: { ...darkTheme.borderRadius, widgetBorderRadius: "10px" },
      }}
    />
  );
};

You can also provide both themes, and widget will respect preference if a user has requested light or dark color themes

import "@stakekit/widget/package/css";
import { SKApp, darkTheme, lightTheme } from "@stakekit/widget";

const App = () => {
  return (
    <SKApp
      apiKey="your-api-key"
      theme={{
        lightMode: lightTheme,
        darkMode: darkTheme,
      }}
    />
  );
};

Theme properties:

{
  color: {
      white: string;
      black: string;
      transparent: string;
      primary: string;
      accent: string;
      disabled: string;
      text: string;
      textMuted: string;
      textDanger: string;
      background: string;
      backgroundMuted: string;
      tokenSelectBackground: string;
      tokenSelectHoverBackground: string;
      tokenSelect: string;
      skeletonLoaderBase: string;
      skeletonLoaderHighlight: string;
      tabBorder: string;
      stakeSectionBackground: string;
      dropdownBackground: string;
      selectValidatorMultiSelectedBackground: string;
      selectValidatorMultiDefaultBackground: string;
      warningBoxBackground: string;
      positionsSectionBackgroundColor: string;
      positionsSectionBorderColor: string;
      positionsSectionDividerColor: string;
      positionsClaimRewardsBackground: string;
      positionsActionRequiredBackground: string;
      positionsPendingBackground: string;
      modalOverlayBackground: string;
      modalBodyBackground: string;
      tooltipBackground: string;
      primaryButtonColor: string;
      primaryButtonBackground: string;
      primaryButtonOutline: string;
      primaryButtonHoverColor: string;
      primaryButtonHoverBackground: string;
      primaryButtonHoverOutline: string;
      primaryButtonActiveColor: string;
      primaryButtonActiveBackground: string;
      primaryButtonActiveOutline: string;
      secondaryButtonColor: string;
      secondaryButtonBackground: string;
      secondaryButtonOutline: string;
      secondaryButtonHoverColor: string;
      secondaryButtonHoverBackground: string;
      secondaryButtonHoverOutline: string;
      secondaryButtonActiveColor: string;
      secondaryButtonActiveBackground: string;
      secondaryButtonActiveOutline: string;
      smallButtonColor: string;
      smallButtonBackground: string;
      smallButtonOutline: string;
      smallButtonHoverColor: string;
      smallButtonHoverBackground: string;
      smallButtonHoverOutline: string;
      smallButtonActiveColor: string;
      smallButtonActiveBackground: string;
      smallButtonActiveOutline: string;
      smallLightButtonColor: string;
      smallLightButtonBackground: string;
      smallLightButtonOutline: string;
      smallLightButtonHoverColor: string;
      smallLightButtonHoverBackground: string;
      smallLightButtonHoverOutline: string;
      smallLightButtonActiveColor: string;
      smallLightButtonActiveBackground: string;
      smallLightButtonActiveOutline: string;
      disabledButtonColor: string;
      disabledButtonBackground: string;
      disabledButtonOutline: string;
      disabledButtonHoverColor: string;
      disabledButtonHoverBackground: string;
      disabledButtonHoverOutline: string;
      disabledButtonActiveColor: string;
      disabledButtonActiveBackground: string;
      disabledButtonActiveOutline: string;
  } & {
      connectKit: {
            accentColor: string;
            accentColorForeground: string;
            actionButtonBorder: string;
            actionButtonBorderMobile: string;
            actionButtonSecondaryBackground: string;
            closeButton: string;
            closeButtonBackground: string;
            connectButtonBackground: string;
            connectButtonBackgroundError: string;
            connectButtonInnerBackground: string;
            connectButtonText: string;
            connectButtonTextError: string;
            connectionIndicator: string;
            downloadBottomCardBackground: string;
            downloadTopCardBackground: string;
            error: string;
            generalBorder: string;
            generalBorderDim: string;
            menuItemBackground: string;
            modalBackdrop: string;
            modalBackground: string;
            modalBorder: string;
            modalText: string;
            modalTextDim: string;
            modalTextSecondary: string;
            profileAction: string;
            profileActionHover: string;
            profileForeground: string;
            selectedOptionBorder: string;
            standby: string;
        };
  };
  fontSize: {
      xs: string;
      sm: string;
      md: string;
      lg: string;
      lgx: string;
      xl: string;
      "2xl": string;
      "3xl": string;
      "4xl": string;
      "5xl": string;
      "6xl": string;
  };
  letterSpacing: {
      tighter: string;
      tight: string;
      normal: string;
      wide: string;
      wider: string;
      widest: string;
  };
  lineHeight: {
      none: string;
      shorter: string;
      short: string;
      base: string;
      tall: string;
      taller: string;
      xs: string;
      sm: string;
      md: string;
      lg: string;
      xl: string;
      "2xl": string;
      "3xl": string;
      "4xl": string;
      "5xl": string;
      "6xl": string;
  };
  fontWeight: {
      normal: string;
      medium: string;
      semibold: string;
      bold: string;
      extrabold: string;
      modalHeading: string;
      tokenSelect: string;
      primaryButton: string;
      secondaryButton: string;
  };
  borderRadius: {
      baseContract: {
          none: string;
          sm: string;
          base: string;
          md: string;
          lg: string;
          xl: string;
          "2xl": string;
          "3xl": string;
          full: string;
          half: string;
          widgetBorderRadius: string;
          primaryButton: string;
          secondaryButton: string;
          smallButton: string;
      };
      connectKit: {
            actionButton: string;
            connectButton: string;
            menuButton: string;
            modal: string;
            modalMobile: string;
        };
  };
  space: {
      full: string;
      unset: string;
      auto: string;
      "0": string;
      "1": string;
      "2": string;
      "3": string;
      "4": string;
      "5": string;
      "6": string;
      "7": string;
      "8": string;
      "9": string;
      "10": string;
      "12": string;
      "14": string;
      "16": string;
      "20": string;
      "24": string;
      "28": string;
      "32": string;
      "36": string;
      "40": string;
      "44": string;
      "48": string;
      px: string;
      buttonMinHeight: string;
  };
  heading: {
      h1: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
      h2: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
      h3: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
      h4: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
  };
  text: {
      small: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
      large: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
      medium: {
          mobile: {
              fontSize: string;
          };
          tablet: {
              fontSize: string;
          };
      };
  };
  zIndices: {
      hide: string;
      auto: string;
      simple: string;
      base: string;
      docked: string;
      dropdown: string;
      sticky: string;
      banner: string;
      overlay: string;
      modal: string;
      skipLink: string;
  };
  font: {
      body: string;
  };
}

Custom provider

Optionally, you can pass externalProviders property to the widget which will be used to connect to the wallet.

type SKExternalProviders = {
  currentChain?: number;
  currentAddress: string;
  initToken?: `${TokenDto["network"]}-${TokenDto["address"]}`;
  supportedChainIds?: number[];
  type: "generic";
  provider: EVMWallet;
};

type EVMWallet = {
  signMessage: (message: string) => Promise<string>;
  switchChain: (chainId: string) => Promise<void>;
  getTransactionReceipt?(txHash: string): Promise<{
      transactionHash?: string;
  }>;
  sendTransaction(tx: EVMTx): Promise<string>;
};

export declare enum TxType {
    Legacy = "0x1",
    EIP1559 = "0x2"
}

export type EVMTx = {
    data: Hex;
    from: Hex;
    to: Hex;
    value: Hex | undefined;
    nonce: Hex;
    gas: Hex;
    chainId: Hex;
    type: Hex;
} & ({
    type: TxType.EIP1559;
    maxFeePerGas: Hex | undefined;
    maxPriorityFeePerGas: Hex | undefined;
} | {
    type: TxType.Legacy;
});

Tracking

Yield.xyz component provides tracking prop for analytics to track user actions and page views

import "@stakekit/widget/package/css";
import { SKApp, darkTheme, lightTheme } from "@stakekit/widget";

const App = () => {
  return (
    <SKApp
      apiKey="your-api-key"
      theme={{ darkMode: darkTheme }}
      tracking={{
        trackEvent: (event, props) => {
          console.log(event, props);
        },
        trackPageView: (event, props) => {
          console.log(event, props);
        },
      }}
    />
  );
};

 

Some Examples

React Native wallets usage

To use StakeKit with your wallets managed provider, you can use utility hook to get prepared props and pass them to WebView component from react-native-webview. Using widget with injected provider skips connection step.

First, install package:

npm install @stakekit/use-inject-provider

or

yarn add @stakekit/use-inject-provider

or

pnpm add @stakekit/use-inject-provider

After that, pass wallets managed EIP-1193 provider and web-views ref to useInjectProvider, and you'll receive injectedJavaScript and onMessage props that you need to pass to WebView component.

Example:

import React, { useRef } from 'react';
import { StyleSheet } from 'react-native';
import WebView from 'react-native-webview';
import { useInjectProvider } from '@stakekit/use-inject-provider';

// Some EIP1193Provider thats managed by wallet
class Provider {
  async request(args) {
    switch (args.method) {
      case 'eth_accounts':
      case 'eth_requestAccounts': {
        // get accounts from your wallet
        // ...
        return ['0xe455036e2f3a26df7014b7dbf6cedbbf81433478']
      }

      case 'eth_chainId': {
        // get current chain id
        return  '1';
      }

      case "eth_sendTransaction": {
        // send transaction and return transaction hash
        // ...
        return "some_transaction_hash";
      }

      default:
        throw new Error('unhandled method');
    }
  }
}

const provider = new Provider();

export const WebViewStake = () => {
  const webViewRef = useRef<WebView>(null);

  const { injectedJavaScript, onMessage } = useInjectProvider({
    webViewRef,
    provider,
  });

  return (
    <WebView
      ref={webViewRef}
      source={{ uri: `${WIDGET_URL}/?api_key=${YOUR_API_KEY}` }}
      onMessage={onMessage}
      injectedJavaScript={injectedJavaScript}
      style={styles.container}
      cacheEnabled={false}
    />
  );
};

const styles = StyleSheet.create({
  container: { flex: 1 },
});