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

Document RPC requests, with code samples #72

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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 .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/node_modules
/docs/dist
/generated
Binary file modified bun.lockb
Binary file not shown.
14 changes: 14 additions & 0 deletions docs/components/sandpack/RequestAccountsHTML.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Sandpack } from "@codesandbox/sandpack-react";
import { staticRequestAccounts, staticRequestAccountsScript } from "../../../generated/sandpackFiles";

export default function RequestAccountsHTML() {
return (
<Sandpack
template="static"
files={{
"index.html": staticRequestAccounts,
"app.js": staticRequestAccountsScript,
}}
/>
);
}
19 changes: 19 additions & 0 deletions docs/components/sandpack/RequestAccountsReact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Sandpack } from "@codesandbox/sandpack-react";
import { reactConfig, reactRequestAccounts } from "../../../generated/sandpackFiles";

export default function RequestAccountsReact() {
return (
<Sandpack
template="react"
customSetup={{
dependencies: {
"@coinbase/wallet-sdk": "latest",
},
}}
files={{
"App.js": reactRequestAccounts,
"config.js": reactConfig,
}}
/>
);
}
25 changes: 25 additions & 0 deletions docs/components/sandpack/files/react/RequestAccounts.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState } from "react";
import { sdk } from "./config";

export default function App() {
const [address, setAddress] = useState(undefined);
const provider = sdk.makeWeb3Provider({ options: "smartWalletOnly" });

const handleClick = async () => {
const accounts = await provider.request({ method: "eth_requestAccounts" });
setAddress(accounts[0]);
};

return (
<>
{!address && (
<button
onClick={handleClick}
>
Connect
</button>
)}
{address && <p>Connected address: {address}</p>}
</>
);
}
8 changes: 8 additions & 0 deletions docs/components/sandpack/files/react/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { CoinbaseWalletSDK } from "@coinbase/wallet-sdk";

const baseSepoliaChainId = 84532;

export const sdk = new CoinbaseWalletSDK({
appName: "My App Name",
appChainIds: [baseSepoliaChainId],
});
17 changes: 17 additions & 0 deletions docs/components/sandpack/files/static/requestAccounts.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Connect to Coinbase Wallet</title>
<script src="app.js" type="module"></script>
</head>
<body>
<div id="app">
<button id="connectButton">Connect</button>
<p id="connectedAddress" style="display: none;">
Connected address: <span id="address"></span>
</p>
</div>
</body>
</html>
32 changes: 32 additions & 0 deletions docs/components/sandpack/files/static/requestAccountsScript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import CoinbaseWalletSDK from "https://esm.sh/@coinbase/wallet-sdk";

document.addEventListener("DOMContentLoaded", () => {
const baseSepoliaChainId = 84532;

const coinbaseWallet = new CoinbaseWalletSDK({
appName: "My App Name",
appChainIds: [baseSepoliaChainId], // Replace with your chain IDs if needed
});

const provider = coinbaseWallet.makeWeb3Provider({ options: "smartWalletOnly" });

const connectButton = document.getElementById("connectButton");
const connectedAddressParagraph = document.getElementById("connectedAddress");
const addressSpan = document.getElementById("address");

// Event listener for the connect button
connectButton.addEventListener("click", async () => {
try {
// Request accounts from the provider
const accounts = await provider.request({ method: "eth_requestAccounts" });
if (accounts.length > 0) {
// Update the UI to show the connected address
addressSpan.textContent = accounts[0];
connectedAddressParagraph.style.display = "block";
connectButton.style.display = "none";
}
} catch (error) {
console.error("Error connecting to Coinbase Wallet:", error);
}
});
});
Empty file.
8 changes: 8 additions & 0 deletions docs/pages/sdk/CoinbaseWalletProvider/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Overview
## Introduction
CoinbaseWalletProvider is an [JavaScript Ethereum provider](https://eips.ethereum.org/EIPS/eip-1193).
It allows JavaScript applications to make Ethereum RPC requests, via its `request` method.
These requests will be handled in one of three ways
1. Sent to the Wallet (Wallet mobile app, extension, or popup window).
2. Handled locally
3. Passed onto default RPC provider for the given chain, if it exists.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import RequestAccountsReact from '../../../../components/sandpack/RequestAccountsReact';
import RequestAccountsHTML from '../../../../components/sandpack/RequestAccountsHTML';

# eth_requestAccounts
Defined in [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102)
> Calling this method MAY trigger a user interface that allows the user to approve or reject account access for a given app.


## Returns
`Array<string>`

An array of Ethereum addresses, which the connected user controls.

## Errors
| Code | Message |
| ---- | ------- |
| 4001 | User denied connection request |


## Examples
:::code-group

<div data-title="React">
<RequestAccountsReact />
</div>

<div data-title="HTML + JS">
<RequestAccountsHTML/>
</div>
:::
86 changes: 86 additions & 0 deletions docs/pages/sdk/CoinbaseWalletProvider/request/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Overview
The `request` method allows apps to make make Ethereum RPC requests to the wallet.

## Specification

```ts twoslash
interface RequestArguments {
readonly method: string;
readonly params?: readonly unknown[] | object;
}

interface ProviderRpcError extends Error {
code: number;
data?: unknown;
}

interface CoinbaseWalletProvider {
/**
* @param {RequestArguments} args request arguments.
* @returns A promise that resolves with the result.
* @throws {ProviderRpcError} incase of error.
* @fires CoinbaseWalletProvider#connect When the provider successfully connects.
*/
request: (args: RequestArguments) => Promise<unknown>
}
```
### Example
:::code-group
```ts twoslash [example.ts]
import {provider} from "./setup";

const addresses = await provider.request({method: 'eth_requestAccounts'});
const txHash = await provider.request({
method: 'eth_sendTransaction',
params: [{from: addresses[0], to: addresses[0], value: 1}]
}
);
```

```ts twoslash [setup.ts] filename="setup.ts"
import { CoinbaseWalletSDK } from '@coinbase/wallet-sdk'

const baseSepoliaChainId = 84532;

export const sdk = new CoinbaseWalletSDK({
appName: 'My App Name',
appChainIds: [baseSepoliaChainId]
});

const provider = sdk.makeWeb3Provider();
```
:::

## Request Handling
Requests are hanlded in one of three ways
1. Sent to the Wallet application (Wallet mobile app, extension, or popup window).
2. Handled locally by the SDK.
3. Passed onto default RPC provider for the given chain, if it exists.

### 1. Sent to the Wallet application
The following RPC requests are sent to the Wallet application:
- eth_ecRecover
- personal_sign
- personal_ecRecover
- eth_signTransaction
- eth_sendTransaction
- eth_signTypedData_v1
- eth_signTypedData_v3
- eth_signTypedData_v4
- eth_signTypedData
- wallet_addEthereumChain
- wallet_watchAsset
- wallet_sendCalls
- wallet_showCallsStatus

### 2. Handled Locally by the SDK
The following requests are handled locally by the SDK, with no external calls.
- eth_requestAccounts
- eth_accounts
- eth_coinbase
- net_version
- eth_chainId
- wallet_getCapabilities
- wallet_switchEthereumChain


1 change: 0 additions & 1 deletion docs/pages/sdk/install.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ yarn add @coinbase/wallet-sdk
bun i @coinbase/wallet-sdk
```
:::

Empty file.
5 changes: 4 additions & 1 deletion dprint.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"json": {
},
"markup": {
},
"markdown": {
},
"typescript": {
Expand All @@ -12,6 +14,7 @@
"plugins": [
"https://plugins.dprint.dev/json-0.19.2.wasm",
"https://plugins.dprint.dev/markdown-0.16.4.wasm",
"https://plugins.dprint.dev/typescript-0.90.4.wasm"
"https://plugins.dprint.dev/typescript-0.90.4.wasm",
"https://plugins.dprint.dev/g-plane/markup_fmt-v0.11.0.wasm"
]
}
46 changes: 46 additions & 0 deletions generateSandpackFiles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const fs = require("fs");
const path = require("path");

const sandpackDir = path.join(__dirname, "docs", "components", "sandpack", "files");
const outputFile = path.join(__dirname, "generated", "sandpackFiles.ts");

function readDirectoryRecursively(dir) {
const results = {};
const list = fs.readdirSync(dir);

list.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);

if (stat && stat.isDirectory()) {
results[file] = readDirectoryRecursively(filePath);
} else {
results[file] = fs.readFileSync(filePath, "utf8");
}
});

return results;
}

const sandpackExamples = readDirectoryRecursively(sandpackDir);

// Generate TypeScript content
let tsContent = `// This file is auto-generated. Do not edit manually.\n\n`;

Object.entries(sandpackExamples).forEach(([framework, examples]) => {
Object.entries(examples).forEach(([exampleName, files]) => {
const name = exampleName.split(".")[0];
const varName = `${framework.split(".")[0]}${name.charAt(0).toUpperCase() + name.slice(1)}`;
tsContent += `export const ${varName} = ${JSON.stringify(files, null, 2)};\n\n`;
});
});

// Ensure the output directory exists
const outputDir = path.dirname(outputFile);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}

fs.writeFileSync(outputFile, tsContent);

console.log("Sandpack examples TypeScript file generated successfully!");
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vocs dev",
"build": "vocs build",
"generate": "bun generateSandpackFiles.js",
"dev": "bun generate && vocs dev",
"build": "bun generate && vocs build",
"preview": "vocs preview",
"format": "dprint fmt",
"prepare": "bun x simple-git-hooks"
},
"dependencies": {
"@codesandbox/sandpack-react": "^2.18.0",
"@codesandbox/sandpack-themes": "^2.0.21",
"@types/react": "latest",
"@vercel/analytics": "^1.2.2",
"react": "latest",
Expand Down
8 changes: 7 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,11 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["**/*.ts", "**/*.tsx"]
"include": [
"**/*.ts",
"**/*.tsx",
"generateSandpackFiles.js",
"docs/components/sandpack/files/react/config.js",
"docs/components/sandpack/files/react/RequestAccounts.jsx"
]
}
13 changes: 13 additions & 0 deletions vocs.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ export default defineConfig({
text: "Upgrading from 3.x",
link: "/sdk/v3-to-v4-changes",
},
{
text: "CoinbaseWalletProvider",
items: [
{ text: "Overview", link: "/sdk/CoinbaseWalletProvider/overview" },
{
text: "request",
items: [
{ text: "Overview", link: "/sdk/CoinbaseWalletProvider/request/overview" },
{ text: "eth_requestAccounts", link: "/sdk/CoinbaseWalletProvider/request/eth_requestAccounts" },
],
},
],
},
],
},
{
Expand Down
Loading