Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add docs for Earn component, hooks, and utilities #1981

Merged
merged 25 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions playground/nextjs-app-router/lib/url-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const URL_PARAM_MAPPING: Partial<Record<OnchainKitComponent, string[]>> = {
[OnchainKitComponent.NFTCardDefault]: ['chainId', 'nftToken'],
[OnchainKitComponent.NFTMintCard]: ['chainId', 'nftToken'],
[OnchainKitComponent.NFTMintCardDefault]: ['chainId', 'nftToken'],
[OnchainKitComponent.Earn]: ['vaultAddress'],
};

export function getShareableUrl(activeComponent?: OnchainKitComponent) {
Expand Down
6 changes: 3 additions & 3 deletions playground/nextjs-app-router/onchainkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coinbase/onchainkit",
"version": "0.36.10",
"version": "0.36.11",
"type": "module",
"repository": "https://github.com/coinbase/onchainkit.git",
"license": "MIT",
Expand Down Expand Up @@ -42,8 +42,8 @@
"qrcode": "^1.5.4",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
"viem": "^2.21.33",
"wagmi": "^2.12.24"
"viem": "^2.23.0",
"wagmi": "^2.14.11"
},
"devDependencies": {
"@biomejs/biome": "1.8.3",
Expand Down
89 changes: 89 additions & 0 deletions site/docs/components/EarnComponents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this page being displayed?

DepositAmountInput,
DepositBalance,
DepositButton,
Earn,
EarnDeposit as EarnDepositComponent,
EarnDetails,
useEarnContext,
} from '@coinbase/onchainkit/earn';
import App from './App.tsx';

const VAULT_ADDRESS = '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A';

export function EarnMain() {
return (
<App>
<Earn vaultAddress={VAULT_ADDRESS} />
</App>
);
}

export function EarnDeposit() {
return (
<App>
<Earn vaultAddress={VAULT_ADDRESS}>
<div className="flex justify-center bg-[var(--ock-bg-primary)] py-2 text-[var(--ock-text-inverse)]">
Custom header
</div>
<EarnDepositComponent />
<div className="flex justify-center bg-[var(--ock-bg-primary)] py-2 text-[var(--ock-text-inverse)]">
Custom footer
</div>
</Earn>
</App>
);
}

export function RearrangedEarnDeposit() {
return (
<App>
<Earn vaultAddress={VAULT_ADDRESS}>
<EarnDepositComponent>
<EarnDetails />
<DepositBalance />
<DepositAmountInput className="border-2 border-green-400" />
<DepositButton />
</EarnDepositComponent>
</Earn>
</App>
);
}

const predefinedAmounts = ['0.1', '1', '10'];

function CustomDepositInterface() {
const { depositAmount, setDepositAmount } = useEarnContext();

return (
<EarnDepositComponent>
<EarnDetails />
<div className="grid grid-cols-3 gap-2">
{predefinedAmounts.map((amount) => {
const selected = amount === depositAmount;
return (
<button
key={amount}
type="button"
onClick={() => setDepositAmount(amount)}
className={`rounded-md px-4 py-2 ${selected ? 'bg-[var(--ock-bg-primary)] text-[var(--ock-text-inverse)]' : 'bg-[var(--ock-bg-secondary)] text-[var(--ock-text-primary)]'}`}
>
{amount}
</button>
);
})}
</div>
<DepositButton />
</EarnDepositComponent>
);
}

export function PredefinedInputDeposit() {
return (
<App>
<Earn vaultAddress={VAULT_ADDRESS}>
<CustomDepositInterface />
</Earn>
</App>
);
}
24 changes: 24 additions & 0 deletions site/docs/pages/api/build-deposit-to-morpho-tx.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# `buildDepositToMorphoTx`

The `buildDepositToMorphoTx` function is used to build [Calls](/transaction/types#calls) for depositing an asset to Morpho. These calls can be passed the `<Transaction />` component to send a transaction.

## Usage

```tsx twoslash [code]
import { buildDepositToMorphoTx } from '@coinbase/onchainkit/earn';

const calls = await buildDepositToMorphoTx({
vaultAddress: '0x...', // Morpho vault address on Base
tokenAddress: '0x...', // Address of the token to deposit
amount: 1000000000000000000n, // Amount of tokens to deposit
recipientAddress: '0x...', // Address of the recipient
});
```

## Returns

[`Call[]`](/transaction/types#calls)

## Parameters

[`DepositToMorphoParams`](/earn/types#deposittomorphoparams)
24 changes: 24 additions & 0 deletions site/docs/pages/api/build-withdraw-from-morpho-tx.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# `buildWithdrawFromMorphoTx`

The `buildWithdrawFromMorphoTx` function is used to build [Calls](/transaction/types#calls) for withdrawing an asset from Morpho. These calls can be passed the `<Transaction />` component to send a transaction.

## Usage

```tsx twoslash [code]
import { buildWithdrawFromMorphoTx } from '@coinbase/onchainkit/earn';

const calls = await buildWithdrawFromMorphoTx({
vaultAddress: '0x...', // Morpho vault address on Base
amount: 1000000000000000000n, // Amount of tokens to withdraw
recipientAddress: '0x...', // Address of the recipient
});
```


## Returns

[`Call[]`](/transaction/types#calls)

## Parameters

[`WithdrawFromMorphoParams`](/earn/types#withdrawfrommorphoparams)
206 changes: 206 additions & 0 deletions site/docs/pages/earn/earn.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
---
title: <Earn /> · OnchainKit
description: Earn interest on your crypto with OnchainKit
---

import { EarnMain, EarnDeposit, RearrangedEarnDeposit, PredefinedInputDeposit } from '../../components/EarnComponents';

# `<Earn />`

The `Earn` component provides a simple interface for earning interest on your crypto via Morpho vaults on Base.

## Prerequisites

Before using the `Earn` component, ensure you've completed the [Getting Started](/getting-started) steps.

### Starting a new project

If you're starting a new project, we recommend using `create onchain` to scaffold your project.

```bash
npm create onchain@latest
```

### Adding to an existing project

If you're adding `Earn` to an existing project, simply install OnchainKit.

:::code-group

```bash [npm]
npm install @coinbase/onchainkit
```

```bash [yarn]
yarn add @coinbase/onchainkit
```

```bash [pnpm]
pnpm add @coinbase/onchainkit
```

```bash [bun]
bun add @coinbase/onchainkit
```

:::

Wrap the `<OnchainKitProvider />` around your app, following the steps in [Getting Started](/getting-started#add-providers).

## Quickstart

To use `Earn`, you'll need to provide a `vaultAddress` prop. A vault address can be obtained from Morpho's [Vaults page](https://app.morpho.org/base/earn).

```tsx twoslash
// @noErrors: 2307
import { Earn } from '@coinbase/onchainkit/earn'; // [!code focus]

<Earn vaultAddress="0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A" /> // [!code focus]
```

<EarnMain />

## Customization

### Custom components and layouts

`Earn` accepts a `children` prop that can be used to render `Earn` subcomponents or custom components.

For instance, you can render the `EarnDeposit` component by itself within the `Earn` component, along with any other custom components you'd like to render.

```tsx twoslash
// @noErrors: 2307
import { Earn, EarnDeposit } from '@coinbase/onchainkit/earn';

<Earn vaultAddress="0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A">
<div>Custom header</div>
<EarnDeposit />
<div>Custom footer</div>
</Earn>
```

<EarnDeposit />

For more granular control, you can also render lower level subcomponents within `EarnDeposit` and `EarnWithdraw`. These subcomponents accept `className` props to customize their styles.

```tsx twoslash
// @noErrors: 2307
import { Earn, EarnDeposit, EarnDetails, DepositBalance, DepositAmountInput, DepositButton } from '@coinbase/onchainkit/earn';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these imports cut off, import in multiple lines


<Earn vaultAddress="0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A">
<EarnDeposit>
<EarnDetails />
<DepositBalance />
<DepositAmountInput className="border-2 border-green-400" />
<DepositButton />
</EarnDeposit>
</Earn>
```

<RearrangedEarnDeposit />

### Customizing styles

The `Earn` component is best styled via a [OnchainKit theme](/guides/themes#custom-theme). You can also override individual component styles using `className`.


## Advanced Usage
If you'd like to implement your own custom components, you can use `useEarnContext` within an `Earn` component to access context and build your own components.

You can find the full interface for `EarnContextType` on the [Types page](/earn/types#earncontexttype).

Below, we use `useEarnContext` to implement a custom deposit interface by using `useEarnContext` to access the `depositAmount` and `setDepositAmount` context values.

:::code-group

```tsx twoslash [index.tsx]
// @noErrors: 2307
import { Earn, useEarnContext } from '@coinbase/onchainkit/earn';
import { CustomDepositButtons } from './custom-deposit-buttons';

<Earn vaultAddress="0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A">
<CustomDepositButtons />
</Earn>

```

```tsx twoslash [custom-deposit-buttons.tsx]
import {EarnDetails, EarnDeposit, useEarnContext, DepositButton} from '@coinbase/onchainkit/earn';
const predefinedAmounts = ['0.1', '1', '10'];

function CustomDepositButtons() {
const { depositAmount, setDepositAmount } = useEarnContext();

return (
<EarnDeposit>
<EarnDetails />
<div className="grid grid-cols-3 gap-2">
{predefinedAmounts.map((amount) => {
const selected = amount === depositAmount;
return (
<button
key={amount}
type="button"
onClick={() => setDepositAmount(amount)}
className={`rounded-md px-4 py-2 ${selected ? 'bg-[var(--ock-bg-primary)] text-[var(--ock-text-inverse)]' : 'bg-[var(--ock-bg-secondary)] text-[var(--ock-text-primary)]'}`}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: classes cut off,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2025-02-12 at 3 28 32 PM

>
{amount}
</button>
);
})}
</div>
<DepositButton />
</EarnDeposit>
);
}
```
:::

<PredefinedInputDeposit />

Taking advantage of the data and methods provided by `useEarnContext`, developers can implement fully custom deposit and withdraw interfaces, modifying everything from UI elements to input behavior.


## Components

The `Earn` component includes the following subcomponents:

- `<Earn />` - A fully built Withdraw and Deposit component. Also includes a `children` prop to render custom components and provides `useEarnContext` to access the context values.
- `<EarnProvider />` - A headless provider that provides the `useEarnContext` hook to the `Earn` component.
- `<EarnDeposit />` - A fully built deposit card.
- `<EarnWithdraw />` - A fully built withdraw card.
- `<EarnDetails />` - A component that displays the details of the vault.
- `<DepositAmountInput />` - A component that handles the deposit amount input.
- `<DepositBalance />` - A component that displays the balance underlying asset in the user's wallet.
- `<DepositButton />` - A component that triggers the deposit transaction.
- `<WithdrawAmountInput />` - A component that handles the withdraw amount input.
- `<WithdrawBalance />` - A component that displays how much the user can withdraw from a vault.
- `<WithdrawButton />` - A component that triggers the withdraw transaction.
- `<YieldDetails />` - A component that displays the yield details of the vault.
- `<VaultDetails />` - A component that displays the vault details.


## Hooks

- [`useEarnContext`](/hooks/use-earn-context) - A hook that provides the context values of the `Earn` component.
- [`useBuildDepositToMorphoTx`](/hooks/use-build-deposit-to-morpho-tx) - A hook that builds a deposit transaction to Morpho.
- [`useBuildWithdrawFromMorphoTx`](/hooks/use-build-withdraw-from-morpho-tx) - A hook that builds a withdraw transaction from Morpho.
- [`useMorphoVault`](/hooks/use-morpho-vault) - A hook that provides the details of a Morpho vault.

## Props

- [`LifecycleStatus`](/earn/types#lifecyclestatus)
- [`EarnReact`](/earn/types#earnreact)
- [`EarnProviderReact`](/earn/types#earnproviderreact)
- [`EarnContextType`](/earn/types#earncontexttype)
- [`EarnAmountInputReact`](/earn/types#earnamountinputreact)
- [`DepositAmountInputReact`](/earn/types#depositamountinputreact)
- [`WithdrawAmountInputReact`](/earn/types#withdrawamountinputreact)
- [`EarnBalanceReact`](/earn/types#earnbalancereact)
- [`DepositBalanceReact`](/earn/types#depositbalancereact)
- [`WithdrawBalanceReact`](/earn/types#withdrawbalancereact)
- [`EarnDepositReact`](/earn/types#earndepositreact)
- [`EarnWithdrawReact`](/earn/types#earnwithdrawreact)
- [`EarnDetailsReact`](/earn/types#earndetailsreact)
- [`DepositButtonReact`](/earn/types#depositbuttonreact)
- [`WithdrawButtonReact`](/earn/types#withdrawbuttonreact)
Loading