React components enabling seamless interaction with ApeChain.
✨ Bridge, 💱 Swap, and 🛒 Buy portals can be used independently, or as an all-in-one portal.
💻 Developer? Check out the contributing guidelines to get involved!
If users require support with transactions they have already sent, all components have visible links for users to obtain support through the same means. Furthermore:
- To get help with Bridge or Swap transactions, please use see decent.xyz support for ApePortal.
- To get help with fiat Onramp transactions:
- If you have already submitted a transaction: Please reach out directly to the provider you transacted through (Moonpay, Stripe, Transak) for any transaction-related issues.
- If you encounter functional issues and cannot complete the transaction flow: If you are unable to proceed with the onramp process or face any functional issues, please contact Halliday at support at halliday dot xyz
Ape Portal is designed for use in a web3 application with a wagmi provider.
The easiest way to get started creating a web3 app is with RainbowKit, which provides a script to quickly set up a NextJS + web3 app.
- Copy our
.npmrc
file to your repo to ensure@yuga-labs
scoped packages are read from GitHub's package registry rather thannpm
:
curl -sSL -o .npmrc https://raw.githubusercontent.com/yuga-labs/ape-portal-public/2bd5d6c85cbb8dfc276c054ddeb0f55a1df459aa/.npmrc
-
Accessing the GitHub npm registry requires a GitHub account. Ensure you have a GitHub personal access token
GITHUB_TOKEN
in your environment, authorized withread:package
permissions. For more information, see GitHub documentation on personal access tokens. -
Install the ApeChain Portal using
npm
,yarn
, orpnpm
:
npm i --save @yuga-labs/ape-portal-public
yarn add @yuga-labs/ape-portal-public
pnpm i @yuga-labs/ape-portal-public
- React
^18
- Wagmi and Viem
viem@^2.21.32
contains theapeChain
network- Import
ApeChain
as a provider chain viagetDefaultConfig
orcreateConfig
. - Bridge functionality requires a multi-chain setup with at least 2 chains, including dedicated RPC providers in production (more info below).
Example:
import { http, createConfig } from '@wagmi/core';
import { arbitrum, base, mainnet, apeChain } from 'viem/chains';
export const config = createConfig({
chains: [
apeChain,
{
...mainnet,
rpcUrls: {
default: {
http: ['https://eth-mainnet.g.alchemy.com/v2/<YOUR-ALCHEMY-KEY>'],
},
},
},
arbitrum,
base,
],
transports: {
[apeChain.id]: http(),
[mainnet.id]: http(),
[arbitrum.id]: http(),
[base.id]: http(),
},
});
- Import the
ape-portal
stylesheet in your root app/layout:
// _app.tsx
import "@yuga-labs/ape-portal-public/dist/assets/style.css";
import type { AppProps } from "next/app";
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
export default MyApp;
It is strongly recommended to explicitly specify RPC URL providers for production. At the time of writing, the default Ethereum mainnet RPC provider (cloudflare-eth.com
) has sporadic caching issues with ETH balance amounts, causing gas estimation errors.
The ApeProvider
is used to pass configuration options and callbacks to ApeChain portals. All top level UI components (Bridge, Swap, Buy) and the all-in-one ApePortal require an ApeProvider.
import { useConnectModal } from '@rainbow-me/rainbowkit';
import { ApeConfig, ApeProvider, ApePortal } from "@yuga-labs/ape-portal-public";
const Home = () => {
const { openConnectModal = () => {} } = useConnectModal();
const apeConfig: ApeConfig = { openConnectModal };
return (
<ApeProvider config={apeConfig}>
<ApePortal />
</ApeProvider>
);
};
Bridge means to move tokens from one chain to another, for example from Ethereum mainnet to ApeChain mainnet.
Swap means to change from one token to another on the same chain.
These definitions are reflected in the use and features of ApePortal.
The Onramp component allows purchase of ApeChain $APE with fiat funding sources.
Usage of the Onramp component requires prior approval from Yuga Labs.
If you're not approved, the ApePortal ONRAMP tab or Buy component will fail due to CORS errors.
To request permission, email support at yugalabs dot io with the subject line: Ape Portal: Onramp Request
. This email is only for dev support to become a partner and host the Onramp. General user support for Bridge, Swap or Onramp transactions is handled elsewhere.
Include <ApePortal>
as a component in your React files to display the Bridge, Swap, and Buy portals in a tabbed interface. <ApePortal>
includes branding elements like the logo and gradient border.
- ApeProvider is still required higher in the component tree.
- Optional props are available:
initialTab={PortalType...}
: Set the initial tab.onTransactionSuccess
andonTransactionError
: Callbacks for transaction success/failure.tokenConfig
: Customize token defaults (discussed below).
import React from 'react';
import { ApePortal } from '@yuga-labs/ape-portal-public';
function App() {
return <ApePortal />;
}
export default App;
Alternatively, use Bridge, Swap, or Buy components individually:
import React from 'react';
import { Bridge, Buy, Swap } from '@yuga-labs/ape-portal-public';
function App() {
return (
<>
<Bridge />
<Swap />
<Buy />
</>
);
}
export default App;
Both the source and destination tokens can be independently set to a custom default token by passing the token
information (DefaultTokenInfo
) to the TokenConfig
object to the Portal or the individual Bridge component.
NOTE: The Swap component does not support all custom token defaults and is ApeChain only.
The tokens can be set with or without an amount. When an amount is set the input field for that token will be pre-filled and the calculation for the other token will be updated automatically. This amount should be a string representation of the amount (i.e. "0.1" for 0.1 tokens). Do not use wei amounts.
Note: Only 1 token can have an amount set. The token the amount is targeting is denoted by the type
property in
the DefaultTokenAmount
object.
If either token is on a chain that is not supported by the current Wagmi provider, then the respective token will remain unchanged.
Lastly, we expose both DefaultTokenInfo
and DefaultTokenAmount
to ensure values conformed to the config.
Example of setting both a source and destination token:
<ApePortal
tokenConfig={{
defaultSourceToken: {
chainId: 1,
address: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
},
defaultDestinationToken: {
chainId: 137,
address: '0x0000000000000000000000000000000000000000',
},
}}
/>
Example of setting a source token with an amount (0.125 tokens):
<ApePortal
tokenConfig={{
defaultSourceToken: {
chainId: 1,
address: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
},
defaultTokenAmount: {
type: InputType.Source,
amount: '0.125',
},
}}
/>
Example of using the TokenConfig
object with the Bridge component:
<Bridge
tokenConfig={{
defaultSourceToken: {
chainId: 1,
address: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
},
}}
/>
To facilitate onboarding users to your app or service, it may be desirable to only allow bridge/swap to a specific chain/token. Use the TokenConfig
boolean lockDestinationToken
for this purpose.
If lockDestinationToken
is true, users will only be allowed to bridge or swap to the default destination token/chain, which is currently ApeCoin. This default can be overridden by setting the defaultDestinationToken
in the TokenConfig
object.
NOTE: The Swap component destination token must be on ApeChain. So any overrides must comply.
<ApePortal
tokenConfig={{
lockDestinationToken: true,
}}
/>
When the portal is used with the all-in-one ApePortal
component, the tabs can be configured to show or hide specific tabs and select an initial tab. This is done by passing an array to the tabConfig
property to the ApePortal
component.
This array accepts 2-3 elements. These elements can be one of the following:
InitialPortalType
PortalType
The array will only accept 1 InitialPortalType
element at a time, and 1 or 2 PortalType
elements. If you decide not to set an initial tab, the array can consist of 3 PortalType
s.
The InitialPortalType
element will determine the initial tab that is shown when the portal is opened. The PortalType
elements will determine the tabs that are shown in the portal.
Lastly, the order of the elements in the array will determine the order of the tabs in the portal.
Example of showing only the Bridge and Swap tabs with the Bridge tab as the initial tab:
<ApePortal tabConfig={[InitialPortalType.Bridge, PortalType.Swap]} />
Example of all three tabs shown without setting an initial tab:
<ApePortal
tabConfig={[PortalType.Bridge, PortalType.Swap, PortalType.Onramp]}
/>
The portal hash router is a feature that allows ApePortal to be navigated using the URL hash. This is useful for sharing a link to a specific tab of ApePortal.
Please note this is not compatible with NextJS 14+ and will require extra code in the NextJS host app - see Hash router NextJS incompatibility below.
To enable the hash router, set the useHashRouter
property in the ApeConfig
object to true
. It is disabled by default.
The router works by look for hash fragments in the URL, and parsing them to determine the tab of the portal. The following hash fragments are supported:
#bridge
#swap
#onramp
These can be used by adding the hash to the URL, for example: https://yourapp.com/#swap
.
const apeConfig: ApeConfig = {
openConnectModal,
useHashRouter: true,
};
The #swap
hash also supports an optional chain and token address parameter, to force the <Swap>
widget or ApePortal swab tab to initialize to that chain and token pair.
NOTE: This feature only currently supports ApeChain.
The expected URL format is #swap/chainId/contractAddress
.
Example URL:
- Chain ID 33139, Ape-Usd contract:
/your-ape-portal/#swap/33139/0xA2235d059F80e176D931Ef76b6C51953Eb3fBEf4
The NextJS 14+ router does not trigger window.hashchange
events (ref). For Ape Portal hash router to work in this environment, please add the following code to manually trigger window.hashchange
events:
import { useParams } from 'next/navigation';
export default function Portal() {
const params = useParams();
useEffect(() => {
// NextJS 14+ router compatibility fix: Allow ApePortal to detect hash changes
window.dispatchEvent(new HashChangeEvent('hashchange'));
}, [params]);
return <ApePortal />;
}
In some cases, it may be desirable to bridge, swap or onramp funds to a wallet other than the connected wallet.
To use this feature, pass a valid wallet address to ApeConfig
property destinationAddress
.
If the bridge component is configured with a destinationAddress
, a warning will be shown in the UI that funds will be sent to destinationAddress
wallet rather than the connected wallet.
When Ape Portal is used with both Bridge and Swap components, the portal will automatically synchronize the selected tokens between the two components:
- If a user selects a source token in the Bridge component, the Swap component will automatically select the same token/chain, and then pre-select another token on that chain.
- If the destination token has a chain different from the source, we stash the token to reuse when users come back to the Bridge.
Ape Portal uses Tailwind CSS for styling, but with the prefix aw-
to prevent conflicts with other apps.
You can override these classes to fit your app's design.