diff --git a/.changeset/cool-spiders-return.md b/.changeset/cool-spiders-return.md
new file mode 100644
index 0000000000..74e8a19ff9
--- /dev/null
+++ b/.changeset/cool-spiders-return.md
@@ -0,0 +1,23 @@
+---
+"@rainbow-me/rainbowkit": patch
+---
+
+SafePal Wallet Support
+
+**Example usage**
+
+```ts
+import {
+ getDefaultWallets,
+ connectorsForWallets,
+} from '@rainbow-me/rainbowkit';
+import { safepalWallet } from '@rainbow-me/rainbowkit/wallets';
+const { wallets } = getDefaultWallets({ appName, chains });
+const connectors = connectorsForWallets([
+ ...wallets,
+ {
+ groupName: 'Other',
+ wallets: [safepalWallet({ projectId, chains })],
+ },
+]);
+```
diff --git a/packages/example/pages/_app.tsx b/packages/example/pages/_app.tsx
index 1f8ab138e1..ad9f2e2620 100644
--- a/packages/example/pages/_app.tsx
+++ b/packages/example/pages/_app.tsx
@@ -37,6 +37,7 @@ import {
phantomWallet,
rabbyWallet,
safeheronWallet,
+ safepalWallet,
tahoWallet,
talismanWallet,
tokenPocketWallet,
@@ -131,6 +132,7 @@ const connectors = connectorsForWallets([
phantomWallet({ chains }),
rabbyWallet({ chains }),
safeheronWallet({ chains }),
+ safepalWallet({ chains, projectId }),
tahoWallet({ chains }),
talismanWallet({ chains }),
tokenPocketWallet({ chains, projectId }),
diff --git a/packages/rainbowkit/src/locales/en_US.json b/packages/rainbowkit/src/locales/en_US.json
index dab6d91691..febd7b521d 100644
--- a/packages/rainbowkit/src/locales/en_US.json
+++ b/packages/rainbowkit/src/locales/en_US.json
@@ -807,6 +807,37 @@
"description": "Once you set up your wallet, click below to refresh the browser and load up the extension."
}
}
+ },
+
+ "safepal": {
+ "extension": {
+ "step1": {
+ "title": "Install the SafePal Wallet extension",
+ "description": "Click at the top right of your browser and pin SafePal Wallet for easy access."
+ },
+ "step2": {
+ "title": "Create or Import a wallet",
+ "description": "Create a new wallet or import an existing one."
+ },
+ "step3": {
+ "title": "Refresh your browser",
+ "description": "Once you set up SafePal Wallet, click below to refresh the browser and load up the extension."
+ }
+ },
+ "qr_code": {
+ "step1": {
+ "title": "Open the SafePal Wallet app",
+ "description": "Put SafePal Wallet on your home screen for faster access to your wallet."
+ },
+ "step2": {
+ "title": "Create or Import a Wallet",
+ "description": "Create a new wallet or import an existing one."
+ },
+ "step3": {
+ "title": "Tap WalletConnect in Settings",
+ "description": "Choose New Connection, then scan the QR code and confirm the prompt to connect."
+ }
+ }
}
}
}
diff --git a/packages/rainbowkit/src/wallets/walletConnectors/index.ts b/packages/rainbowkit/src/wallets/walletConnectors/index.ts
index 7efa10e40f..7951e2f084 100644
--- a/packages/rainbowkit/src/wallets/walletConnectors/index.ts
+++ b/packages/rainbowkit/src/wallets/walletConnectors/index.ts
@@ -24,6 +24,7 @@ import { rabbyWallet } from './rabbyWallet/rabbyWallet';
import { rainbowWallet } from './rainbowWallet/rainbowWallet';
import { safeWallet } from './safeWallet/safeWallet';
import { safeheronWallet } from './safeheronWallet/safeheronWallet';
+import { safepalWallet } from './safepalWallet/safepalWallet';
import { tahoWallet } from './tahoWallet/tahoWallet';
import { talismanWallet } from './talismanWallet/talismanWallet';
import { tokenPocketWallet } from './tokenPocketWallet/tokenPocketWallet';
@@ -62,6 +63,7 @@ export {
rainbowWallet,
safeWallet,
safeheronWallet,
+ safepalWallet,
tahoWallet,
talismanWallet,
tokenPocketWallet,
diff --git a/packages/rainbowkit/src/wallets/walletConnectors/safepalWallet/safepalWallet.svg b/packages/rainbowkit/src/wallets/walletConnectors/safepalWallet/safepalWallet.svg
new file mode 100644
index 0000000000..4b16b1eabb
--- /dev/null
+++ b/packages/rainbowkit/src/wallets/walletConnectors/safepalWallet/safepalWallet.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/rainbowkit/src/wallets/walletConnectors/safepalWallet/safepalWallet.ts b/packages/rainbowkit/src/wallets/walletConnectors/safepalWallet/safepalWallet.ts
new file mode 100644
index 0000000000..e582f3b950
--- /dev/null
+++ b/packages/rainbowkit/src/wallets/walletConnectors/safepalWallet/safepalWallet.ts
@@ -0,0 +1,200 @@
+import type { InjectedConnectorOptions } from '@wagmi/core/connectors/injected';
+import { InjectedConnector } from 'wagmi/connectors/injected';
+import { Chain } from '../../../components/RainbowKitProvider/RainbowKitChainContext';
+import { getWalletConnectUri } from '../../../utils/getWalletConnectUri';
+import { InstructionStepName, Wallet } from '../../Wallet';
+import { getWalletConnectConnector } from '../../getWalletConnectConnector';
+import type {
+ WalletConnectConnectorOptions,
+ WalletConnectLegacyConnectorOptions,
+} from '../../getWalletConnectConnector';
+
+declare global {
+ interface Window {
+ safepalProvider: Window['ethereum'];
+ }
+}
+
+export interface SafepalWalletLegacyOptions {
+ projectId?: string;
+ chains: Chain[];
+ walletConnectVersion: '1';
+ walletConnectOptions?: WalletConnectLegacyConnectorOptions;
+}
+
+export interface SafepalWalletOptions {
+ projectId: string;
+ chains: Chain[];
+ walletConnectVersion?: '2';
+ walletConnectOptions?: WalletConnectConnectorOptions;
+}
+
+function getSafepalWalletInjectedProvider(): Window['ethereum'] {
+ const isSafePalWallet = (ethereum: NonNullable | any) => {
+ // Identify if SafePal Wallet injected provider is present.
+ const safepalWallet = !!ethereum.isSafePal;
+
+ return safepalWallet;
+ };
+
+ const injectedProviderExist =
+ typeof window !== 'undefined' && typeof window.ethereum !== 'undefined';
+
+ // No injected providers exist.
+ if (!injectedProviderExist) {
+ return;
+ }
+
+ // SafePal Wallet injected provider is available in the global scope.
+ // There are cases that some cases injected providers can replace window.ethereum
+ // without updating the ethereum.providers array. To prevent issues where
+ // the TW connector does not recognize the provider when TW extension is installed,
+ // we begin our checks by relying on TW's global object.
+ if (window['safepalProvider']) {
+ return window['safepalProvider'];
+ }
+
+ // SafePal Wallet was injected into window.ethereum.
+ if (isSafePalWallet(window.ethereum!)) {
+ return window.ethereum;
+ }
+
+ // SafePal Wallet provider might be replaced by another
+ // injected provider, check the providers array.
+ if (window.ethereum?.providers) {
+ // ethereum.providers array is a non-standard way to
+ // preserve multiple injected providers. Eventually, EIP-5749
+ // will become a living standard and we will have to update this.
+ return window.ethereum.providers.find(isSafePalWallet);
+ }
+}
+
+export const safepalWallet = ({
+ chains,
+ projectId,
+ walletConnectOptions,
+ walletConnectVersion = '2',
+ ...options
+}: (SafepalWalletLegacyOptions | SafepalWalletOptions) &
+ InjectedConnectorOptions): Wallet => {
+ const isSafePalWalletInjected = Boolean(getSafepalWalletInjectedProvider());
+ const shouldUseWalletConnect = !isSafePalWalletInjected;
+
+ return {
+ id: 'safepal',
+ name: 'SafePal Wallet',
+ iconUrl: async () => (await import('./safepalWallet.svg')).default,
+ // Note that we never resolve `installed` to `false` because the
+ // SafePal Wallet provider falls back to other connection methods if
+ // the injected connector isn't available
+ installed: isSafePalWalletInjected || undefined,
+ iconAccent: '#3375BB',
+ iconBackground: '#fff',
+ downloadUrls: {
+ android:
+ 'https://play.google.com/store/apps/details?id=io.safepal.wallet&referrer=utm_source%3Drainbowkit%26utm_medium%3Ddisplay%26utm_campaign%3Ddownload',
+ ios: 'https://apps.apple.com/app/apple-store/id1548297139?pt=122504219&ct=rainbowkit&mt=8',
+ mobile: 'https://www.safepal.com/en/download',
+ qrCode: 'https://www.safepal.com/en/download',
+ chrome:
+ 'https://chrome.google.com/webstore/detail/safepal-extension-wallet/lgmpcpglpngdoalbgeoldeajfclnhafa',
+ browserExtension: 'https://www.safepal.com/download?product=2',
+ },
+ createConnector: () => {
+ const getUriMobile = async () => {
+ const uri = await getWalletConnectUri(connector, walletConnectVersion);
+
+ return `safepalwallet://wc?uri=${encodeURIComponent(uri)}`;
+ };
+
+ const getUriQR = async () => {
+ const uri = await getWalletConnectUri(connector, walletConnectVersion);
+
+ return uri;
+ };
+
+ const connector = shouldUseWalletConnect
+ ? getWalletConnectConnector({
+ projectId,
+ chains,
+ version: walletConnectVersion,
+ options: walletConnectOptions,
+ })
+ : new InjectedConnector({
+ chains,
+ options: {
+ getProvider: getSafepalWalletInjectedProvider,
+ ...options,
+ },
+ });
+
+ const mobileConnector = {
+ getUri: shouldUseWalletConnect ? getUriMobile : undefined,
+ };
+
+ let qrConnector = undefined;
+
+ if (shouldUseWalletConnect) {
+ qrConnector = {
+ getUri: getUriQR,
+ instructions: {
+ learnMoreUrl: 'https://safepal.com/',
+ steps: [
+ {
+ description:
+ 'wallet_connectors.safepal.qr_code.step1.description',
+ step: 'install' as InstructionStepName,
+ title: 'wallet_connectors.safepal.qr_code.step1.title',
+ },
+ {
+ description:
+ 'wallet_connectors.safepal.qr_code.step2.description',
+ step: 'create' as InstructionStepName,
+ title: 'wallet_connectors.safepal.qr_code.step2.title',
+ },
+ {
+ description:
+ 'wallet_connectors.safepal.qr_code.step3.description',
+ step: 'scan' as InstructionStepName,
+ title: 'wallet_connectors.safepal.qr_code.step3.title',
+ },
+ ],
+ },
+ };
+ }
+
+ const extensionConnector = {
+ instructions: {
+ learnMoreUrl: 'https://www.safepal.com/download?product=2',
+ steps: [
+ {
+ description:
+ 'wallet_connectors.safepal.extension.step1.description',
+ step: 'install' as InstructionStepName,
+ title: 'wallet_connectors.safepal.extension.step1.title',
+ },
+ {
+ description:
+ 'wallet_connectors.safepal.extension.step2.description',
+ step: 'create' as InstructionStepName,
+ title: 'wallet_connectors.safepal.extension.step2.title',
+ },
+ {
+ description:
+ 'wallet_connectors.safepal.extension.step3.description',
+ step: 'refresh' as InstructionStepName,
+ title: 'wallet_connectors.safepal.extension.step3.title',
+ },
+ ],
+ },
+ };
+
+ return {
+ connector,
+ mobile: mobileConnector,
+ qrCode: qrConnector,
+ extension: extensionConnector,
+ };
+ },
+ };
+};
diff --git a/site/data/docs/custom-wallet-list.mdx b/site/data/docs/custom-wallet-list.mdx
index 9ae0dc359a..43af870e14 100644
--- a/site/data/docs/custom-wallet-list.mdx
+++ b/site/data/docs/custom-wallet-list.mdx
@@ -374,6 +374,16 @@ safeheronWallet(options: {
});
```
+#### SafePal Wallet
+
+```tsx
+import { safepalWallet } from '@rainbow-me/rainbowkit/wallets';
+safepalWallet(options: {
+ projectId: string;
+ chains: Chain[];
+});
+```
+
#### Taho
```tsx