From c62ca076c1249642c270fcd7f3c5e44d8c195e84 Mon Sep 17 00:00:00 2001
From: Alec Chen <93971719+0xAlec@users.noreply.github.com>
Date: Thu, 8 Aug 2024 21:19:20 -0700
Subject: [PATCH 01/51] `WalletDropdownFundLink` component
---
src/internal/svg/fundWallet.tsx | 17 +++++++
.../WalletDropdownFundLink.test.tsx | 47 +++++++++++++++++++
.../components/WalletDropdownFundLink.tsx | 44 +++++++++++++++++
3 files changed, 108 insertions(+)
create mode 100644 src/internal/svg/fundWallet.tsx
create mode 100644 src/wallet/components/WalletDropdownFundLink.test.tsx
create mode 100644 src/wallet/components/WalletDropdownFundLink.tsx
diff --git a/src/internal/svg/fundWallet.tsx b/src/internal/svg/fundWallet.tsx
new file mode 100644
index 0000000000..91aa26df62
--- /dev/null
+++ b/src/internal/svg/fundWallet.tsx
@@ -0,0 +1,17 @@
+import { fill } from '../../styles/theme';
+
+export const FundWalletSvg = (
+
+);
diff --git a/src/wallet/components/WalletDropdownFundLink.test.tsx b/src/wallet/components/WalletDropdownFundLink.test.tsx
new file mode 100644
index 0000000000..f3bdb35854
--- /dev/null
+++ b/src/wallet/components/WalletDropdownFundLink.test.tsx
@@ -0,0 +1,47 @@
+import { render, screen } from '@testing-library/react';
+import { describe, expect, it } from 'vitest';
+import { WalletDropdownFundLink } from './WalletDropdownFundLink';
+
+const FUNDING_URL =
+ 'http://keys.coinbase.com/funding?dappName=&dappUrl=http://localhost:3000/';
+
+describe('WalletDropdownFundLink', () => {
+ it('renders correctly with default props', () => {
+ render();
+
+ const linkElement = screen.getByRole('link');
+ expect(linkElement).toBeInTheDocument();
+ expect(linkElement).toHaveAttribute('href', FUNDING_URL);
+ expect(screen.getByText('Deposit Funds')).toBeInTheDocument();
+ });
+
+ it('renders correctly with custom icon element', () => {
+ const customIcon = ;
+ render(
+
+ Link Text
+
+ );
+
+ const linkElement = screen.getByRole('link');
+ expect(linkElement).toBeInTheDocument();
+ expect(linkElement).toHaveAttribute('href', FUNDING_URL);
+ expect(screen.getByText('Link Text')).toBeInTheDocument();
+ expect(screen.getByLabelText('custom-icon')).toBeInTheDocument();
+ });
+
+ it('renders correctly with target and rel attributes', () => {
+ render(
+
+ Link Text
+
+ );
+
+ const linkElement = screen.getByRole('link');
+ expect(linkElement).toBeInTheDocument();
+ expect(linkElement).toHaveAttribute('href', FUNDING_URL);
+ expect(linkElement).toHaveAttribute('target', '_blank');
+ expect(linkElement).toHaveAttribute('rel', 'noopener noreferrer');
+ expect(screen.getByText('Link Text')).toBeInTheDocument();
+ });
+});
diff --git a/src/wallet/components/WalletDropdownFundLink.tsx b/src/wallet/components/WalletDropdownFundLink.tsx
new file mode 100644
index 0000000000..01deaeb40c
--- /dev/null
+++ b/src/wallet/components/WalletDropdownFundLink.tsx
@@ -0,0 +1,44 @@
+import { isValidElement, useMemo } from 'react';
+import { FundWalletSvg } from '../../internal/svg/fundWallet';
+import { cn, pressable, text } from '../../styles/theme';
+import type { WalletDropdownLinkReact } from '../types';
+
+export function WalletDropdownFundLink({
+ children,
+ className,
+ icon,
+ rel,
+ target,
+}: WalletDropdownLinkReact) {
+ const iconSvg = useMemo(() => {
+ if (icon === undefined) {
+ return FundWalletSvg;
+ }
+ if (isValidElement(icon)) {
+ return icon;
+ }
+ }, [icon]);
+
+ const currentURL = window.location.href;
+ const tabName = document.title;
+
+ return (
+
+
+ {iconSvg}
+
+
+ {children || 'Deposit Funds'}
+
+
+ );
+}
From 1f8aa0e3d3203cb41a283ea3a9490a9575fbdb8b Mon Sep 17 00:00:00 2001
From: Alec Chen <93971719+0xAlec@users.noreply.github.com>
Date: Fri, 9 Aug 2024 09:39:10 -0700
Subject: [PATCH 02/51] types
---
src/wallet/index.ts | 2 ++
src/wallet/types.ts | 14 ++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/src/wallet/index.ts b/src/wallet/index.ts
index 6063116126..eec4f9abea 100644
--- a/src/wallet/index.ts
+++ b/src/wallet/index.ts
@@ -4,6 +4,7 @@ export { Wallet } from './components/Wallet';
export { WalletDropdown } from './components/WalletDropdown';
export { WalletDropdownBaseName } from './components/WalletDropdownBaseName';
export { WalletDropdownDisconnect } from './components/WalletDropdownDisconnect';
+export { WalletDropdownFundLink } from './components/WalletDropdownFundLink';
export { WalletDropdownLink } from './components/WalletDropdownLink';
export { isValidAAEntrypoint } from './utils/isValidAAEntrypoint';
export { isWalletACoinbaseSmartWallet } from './utils/isWalletACoinbaseSmartWallet';
@@ -16,6 +17,7 @@ export type {
WalletDropdownBaseNameReact,
WalletDropdownDisconnectReact,
WalletDropdownLinkReact,
+ WalletDropdownFundLinkReact,
WalletDropdownReact,
WalletReact,
} from './types';
diff --git a/src/wallet/types.ts b/src/wallet/types.ts
index 631a2566f9..24e1b15b42 100644
--- a/src/wallet/types.ts
+++ b/src/wallet/types.ts
@@ -107,3 +107,17 @@ export type WalletDropdownLinkReact = {
rel?: string;
target?: string;
};
+
+/**
+ * Note: exported as public Type
+ */
+export type WalletDropdownFundLinkReact = {
+ className?: string; // Optional className override for the element
+ href: string;
+ icon?: ReactNode;
+ rel?: string;
+ target?: string;
+ text?: string;
+ type?: 'window' | 'tab';
+ size?: 's' | 'm' | 'l';
+};
From ae3e8dd69ee62926085aa0e6a406e5789f0c94c2 Mon Sep 17 00:00:00 2001
From: Alec Chen <93971719+0xAlec@users.noreply.github.com>
Date: Fri, 9 Aug 2024 09:39:18 -0700
Subject: [PATCH 03/51] window mode
---
.../WalletDropdownFundLink.test.tsx | 48 +++++++++-----
.../components/WalletDropdownFundLink.tsx | 64 ++++++++++++++-----
2 files changed, 78 insertions(+), 34 deletions(-)
diff --git a/src/wallet/components/WalletDropdownFundLink.test.tsx b/src/wallet/components/WalletDropdownFundLink.test.tsx
index f3bdb35854..bab4714aa3 100644
--- a/src/wallet/components/WalletDropdownFundLink.test.tsx
+++ b/src/wallet/components/WalletDropdownFundLink.test.tsx
@@ -1,5 +1,5 @@
-import { render, screen } from '@testing-library/react';
-import { describe, expect, it } from 'vitest';
+import { render, screen, fireEvent } from '@testing-library/react';
+import { describe, expect, it, vi } from 'vitest';
import { WalletDropdownFundLink } from './WalletDropdownFundLink';
const FUNDING_URL =
@@ -17,31 +17,45 @@ describe('WalletDropdownFundLink', () => {
it('renders correctly with custom icon element', () => {
const customIcon = ;
- render(
-
- Link Text
-
- );
+ render();
const linkElement = screen.getByRole('link');
expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute('href', FUNDING_URL);
- expect(screen.getByText('Link Text')).toBeInTheDocument();
+ expect(screen.getByText('Deposit Funds')).toBeInTheDocument();
expect(screen.getByLabelText('custom-icon')).toBeInTheDocument();
});
- it('renders correctly with target and rel attributes', () => {
- render(
-
- Link Text
-
- );
+ it('renders correctly with custom text', () => {
+ render();
const linkElement = screen.getByRole('link');
expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute('href', FUNDING_URL);
- expect(linkElement).toHaveAttribute('target', '_blank');
- expect(linkElement).toHaveAttribute('rel', 'noopener noreferrer');
- expect(screen.getByText('Link Text')).toBeInTheDocument();
+ expect(screen.getByText('test')).toBeInTheDocument();
+ });
+
+ it('opens a new window when clicked with type="window"', () => {
+ // Mock window.open
+ const mockOpen = vi.fn();
+ vi.stubGlobal('open', mockOpen);
+
+ // Mock window.screen
+ vi.stubGlobal('screen', { width: 1024, height: 768 });
+
+ render();
+
+ const linkElement = screen.getByText('Deposit Funds');
+ fireEvent.click(linkElement);
+
+ // Check if window.open was called with the correct arguments
+ expect(mockOpen).toHaveBeenCalledWith(
+ expect.stringContaining('http://keys.coinbase.com/funding'),
+ 'Coinbase Fund Wallet',
+ expect.stringContaining('width=600,height=700'),
+ );
+
+ // Clean up
+ vi.unstubAllGlobals();
});
});
diff --git a/src/wallet/components/WalletDropdownFundLink.tsx b/src/wallet/components/WalletDropdownFundLink.tsx
index 01deaeb40c..6c2b2359cc 100644
--- a/src/wallet/components/WalletDropdownFundLink.tsx
+++ b/src/wallet/components/WalletDropdownFundLink.tsx
@@ -1,15 +1,17 @@
import { isValidElement, useMemo } from 'react';
import { FundWalletSvg } from '../../internal/svg/fundWallet';
-import { cn, pressable, text } from '../../styles/theme';
-import type { WalletDropdownLinkReact } from '../types';
+import { cn, pressable, text as themeText } from '../../styles/theme';
+import type { WalletDropdownFundLinkReact } from '../types';
export function WalletDropdownFundLink({
- children,
className,
icon,
rel,
target,
-}: WalletDropdownLinkReact) {
+ text = 'Deposit Funds',
+ type = 'tab',
+ size = 'm',
+}: WalletDropdownFundLinkReact) {
const iconSvg = useMemo(() => {
if (icon === undefined) {
return FundWalletSvg;
@@ -21,24 +23,52 @@ export function WalletDropdownFundLink({
const currentURL = window.location.href;
const tabName = document.title;
+ const windowSizes: Record<
+ 's' | 'm' | 'l',
+ {
+ width: number;
+ height: number;
+ }
+ > = {
+ s: { width: 400, height: 500 },
+ m: { width: 600, height: 700 },
+ l: { width: 800, height: 900 },
+ };
+
+ const handleClick = (e: React.MouseEvent) => {
+ e.preventDefault();
+ const url = `http://keys.coinbase.com/funding?dappName=${tabName}&dappUrl=${currentURL}`;
+ const { width, height } = windowSizes[size];
+ const left = (window.screen.width - width) / 2;
+ const top = (window.screen.height - height) / 2;
+ const windowFeatures = `width=${width},height=${height},resizable,scrollbars=yes,status=1,left=${left},top=${top}`;
+ window.open(url, 'Coinbase Fund Wallet', windowFeatures);
+ };
+
+ const commonProps = {
+ className: cn(
+ pressable.default,
+ 'relative flex items-center px-4 py-3',
+ className,
+ ),
+ };
+
+ const linkProps =
+ type === 'tab'
+ ? {
+ ...commonProps,
+ href: `http://keys.coinbase.com/funding?dappName=${tabName}&dappUrl=${currentURL}`,
+ target,
+ rel,
+ }
+ : { ...commonProps, onClick: handleClick };
return (
-
+
{iconSvg}
-
- {children || 'Deposit Funds'}
-
+ {text}
);
}
From 89112aac59c64d634cf62500c287d95359d7288e Mon Sep 17 00:00:00 2001
From: Alec Chen <93971719+0xAlec@users.noreply.github.com>
Date: Fri, 9 Aug 2024 09:39:23 -0700
Subject: [PATCH 04/51] docs
---
site/docs/pages/wallet/types.mdx | 15 ++
.../wallet/wallet-dropdown-fund-link.mdx | 185 ++++++++++++++++++
site/sidebar.ts | 6 +-
3 files changed, 203 insertions(+), 3 deletions(-)
create mode 100644 site/docs/pages/wallet/wallet-dropdown-fund-link.mdx
diff --git a/site/docs/pages/wallet/types.mdx b/site/docs/pages/wallet/types.mdx
index b8a617f0a8..7445fe133e 100644
--- a/site/docs/pages/wallet/types.mdx
+++ b/site/docs/pages/wallet/types.mdx
@@ -94,3 +94,18 @@ export type WalletDropdownLinkReact = {
target?: string;
};
```
+
+## `WalletDropdownFundLinkReact`
+
+```ts
+export type WalletDropdownFundLinkReact = {
+ className?: string; // Optional className override for the element
+ href: string;
+ icon?: ReactNode;
+ rel?: string;
+ target?: string;
+ text?: string;
+ type?: 'popup' | 'link';
+ size?: 's' | 'm' | 'l';
+};
+```
diff --git a/site/docs/pages/wallet/wallet-dropdown-fund-link.mdx b/site/docs/pages/wallet/wallet-dropdown-fund-link.mdx
new file mode 100644
index 0000000000..c21328a058
--- /dev/null
+++ b/site/docs/pages/wallet/wallet-dropdown-fund-link.mdx
@@ -0,0 +1,185 @@
+---
+title: Wallet Components & Utilities · OnchainKit
+description: Introduction to Wallet Components & Utilities
+---
+
+import {
+ ConnectWallet,
+ Wallet,
+ WalletDropdown,
+ WalletDropdownLink,
+ WalletDropdownDisconnect,
+ WalletDropdownFundLink,
+} from '../src/wallet';
+import { Address, Avatar, Name, Identity, EthBalance } from '../src/identity';
+import { color } from '@coinbase/onchainkit/theme';
+import AppWithRK from '../../components/AppWithRK';
+import WalletComponents from '../../components/WalletComponents';
+
+# ``
+
+The Wallet Dropdown Fund Link provides an easy way for to access the [Funding](https://keys.coinbase.com/funding) flow for a Coinbase Smart Wallet.
+
+## Usage
+
+```tsx
+import {
+ // [!code focus]
+ ConnectWallet,
+ Wallet,
+ WalletDropdown,
+ WalletDropdownLink,
+ WalletDropdownDisconnect,
+ WalletDropdownFundLink, // [!code focus]
+} from '@coinbase/onchainkit/wallet'; // [!code focus]
+import {
+ Address,
+ Avatar,
+ Name,
+ Identity,
+ EthBalance,
+} from '@coinbase/onchainkit/identity';
+import { color } from '@coinbase/onchainkit/theme';
+
+export function WalletComponents() {
+ return (
+
+
+
+
+
+
+ // [!code focus]
+
+ // [!code focus]
+
+
+
+
+
+
+ // [!code focus]
+
+ Wallet
+
+
+
+
+ // [!code focus]
+
+ );
+}
+```
+
+
+
+
+
+
+
+
+
+
+ Wallet
+
+
+
+
+
+
+### Override text
+
+You can override component text using the `text` prop.
+
+```tsx
+// omitted for brevity
+
+
+
+ ...
+
+
+ ...
+ // [!code focus]
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+### Open in window
+
+You can override default link behavior to open the funding flow in a popup window by using the `type` prop.
+
+```tsx
+// omitted for brevity
+
+
+
+ ...
+
+
+ ...
+ // [!code focus]
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+### Customizing the window size
+
+When using popup mode, you're able to customize the size of the popup window using the `size` prop. Valid values are `s`, `m`, and `l`.
+
+```tsx
+// omitted for brevity
+
+
+
+ ...
+
+
+ ...
+ // [!code focus]
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Props
+
+- [`WalletDropdownFundLinkReact`](/wallet/types#walletdropdownfundlinkreact)
diff --git a/site/sidebar.ts b/site/sidebar.ts
index 37046d9fa8..b85e867221 100644
--- a/site/sidebar.ts
+++ b/site/sidebar.ts
@@ -141,7 +141,7 @@ export const sidebar = [
}
],
},
- ]
+ ],
},
{
text: 'Utilities',
@@ -249,7 +249,7 @@ export const sidebar = [
},
],
},
- ]
+ ],
},
{
text: 'Types',
@@ -287,6 +287,6 @@ export const sidebar = [
text: 'Wallet',
link: '/wallet/types',
},
- ]
+ ],
},
] as const satisfies Sidebar;
From ec4550349694c06fba1698dc766a2bd38ecfda40 Mon Sep 17 00:00:00 2001
From: Alec Chen <93971719+0xAlec@users.noreply.github.com>
Date: Fri, 9 Aug 2024 09:43:38 -0700
Subject: [PATCH 05/51] lint
---
src/internal/svg/fundWallet.tsx | 2 ++
src/wallet/components/WalletDropdownFundLink.test.tsx | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/internal/svg/fundWallet.tsx b/src/internal/svg/fundWallet.tsx
index 91aa26df62..a71f805203 100644
--- a/src/internal/svg/fundWallet.tsx
+++ b/src/internal/svg/fundWallet.tsx
@@ -2,6 +2,8 @@ import { fill } from '../../styles/theme';
export const FundWalletSvg = (