Skip to content

Commit

Permalink
Adding More Methods for Testdapp (#1065)
Browse files Browse the repository at this point in the history
* added section to methods

* shortcuts

* more shortcuts for switch/add

* wider

* signMsg + send

* removed dup

* dynamically import SDK

* misc

* separate shortcuts and methods

* updated to master, 3.9, 3.7

* RpcRequestInput

* 3.9.0-canary.5

* bump version
  • Loading branch information
fan-zhang-sv authored Nov 17, 2023
1 parent a4a3194 commit b2f1e86
Show file tree
Hide file tree
Showing 20 changed files with 1,497 additions and 150 deletions.
3 changes: 3 additions & 0 deletions apps/testapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
"start": "next start"
},
"dependencies": {
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.8.0",
"@coinbase/wallet-sdk": "workspace:^",
"@coinbase/wallet-sdk-3.7": "npm:@coinbase/wallet-sdk@~3.7.2",
"@coinbase/wallet-sdk-3.9": "npm:@coinbase/wallet-sdk@~3.9.0-canary.5",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"framer-motion": "^10.13.1",
Expand Down
45 changes: 39 additions & 6 deletions apps/testapp/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,59 @@
import { Box, Button, Container, Flex, Heading } from '@chakra-ui/react';
import { CheckIcon, ChevronDownIcon } from '@chakra-ui/icons';
import {
Box,
Button,
Container,
Flex,
Heading,
Menu,
MenuButton,
MenuItem,
MenuList,
} from '@chakra-ui/react';

import { useCBWSDK } from '../context/CBWSDKProvider';
import { sdkVersions, useCBWSDK } from '../context/CBWSDKProvider';

type LayoutProps = {
children: React.ReactNode;
};

export const WIDTH_2XL = '1536px';

export function Layout({ children }: LayoutProps) {
const { sdk } = useCBWSDK();
const { sdk, sdkVersion, setSDKVersion } = useCBWSDK();
const handleDisconnect = () => {
if (sdk) {
sdk.disconnect();
}
};

return (
<Box minH="100vh" bg="blackAlpha.100">
<Box as="header" shadow="lg" py={6} bg="blackAlpha.900" color="whiteAlpha.900">
<Container maxW="container.xl">
<Container maxW={WIDTH_2XL}>
<Flex justifyContent="space-between" alignItems="center">
<Heading>Coinbase Wallet SDK - Playground</Heading>
{/* TODO: There is an issue where `this` is undefined within the sdk instance. */}
<Button onClick={handleDisconnect}>Disconnect</Button>
<Flex justifyContent="space-between" alignItems="center" gap={4}>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
{`SDK: ${sdkVersion}`}
</MenuButton>
<MenuList>
{sdkVersions.map((version) => (
<MenuItem
color={'MenuText'}
key={version}
icon={version === sdkVersion ? <CheckIcon /> : null}
onClick={() => setSDKVersion(version)}
>
{version}
</MenuItem>
))}
</MenuList>
</Menu>
{/* TODO: There is an issue where `this` is undefined within the sdk instance. */}
<Button onClick={handleDisconnect}>Disconnect</Button>
</Flex>
</Flex>
</Container>
</Box>
Expand Down
145 changes: 110 additions & 35 deletions apps/testapp/src/components/RpcMethods/RpcMethodCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Button,
Card,
CardBody,
Expand All @@ -7,6 +12,7 @@ import {
FormControl,
FormErrorMessage,
Heading,
HStack,
Input,
InputGroup,
InputLeftAddon,
Expand All @@ -16,11 +22,14 @@ import React, { useCallback } from 'react';
import { useForm } from 'react-hook-form';

import { useCBWSDK } from '../../context/CBWSDKProvider';
import { verifySignMsg } from './method/signMessageMethods';
import { ADDR_TO_FILL } from './shortcut/const';

export function RpcMethodCard({ connected, format, method, params }) {
const [response, setResponse] = React.useState<Record<string, unknown> | string | number | null>(
null
);
type ResponseType = string;

export function RpcMethodCard({ connected, format, method, params, shortcuts }) {
const [response, setResponse] = React.useState<Response | null>(null);
const [verifyResult, setVerifyResult] = React.useState<string | null>(null);
const [error, setError] = React.useState<Record<string, unknown> | string | number | null>(null);
const { provider } = useCBWSDK();

Expand All @@ -30,13 +39,36 @@ export function RpcMethodCard({ connected, format, method, params }) {
formState: { errors },
} = useForm();

const verify = useCallback(async (response: ResponseType, data: Record<string, string>) => {
const verifyResult = verifySignMsg({
method,
from: data.address,
sign: response,
message: data.message,
});
if (verifyResult) {
setVerifyResult(verifyResult);
return;
}
}, []);

const submit = useCallback(
async (data: Record<string, unknown>) => {
async (data: Record<string, string>) => {
setError(null);
setVerifyResult(null);
setResponse(null);
if (!provider) return;
let values = data;
if (format) {
// fill active address to the request
const addresses = await provider.request({ method: 'eth_accounts' });
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
if (data[key] === ADDR_TO_FILL) {
data[key] = addresses[0];
}
}
}
values = format(data);
}
try {
Expand All @@ -49,6 +81,7 @@ export function RpcMethodCard({ connected, format, method, params }) {
params: values,
});
setResponse(response);
verify(response, data);
} catch (err) {
if (err instanceof Error) {
setError(err.message);
Expand All @@ -61,8 +94,6 @@ export function RpcMethodCard({ connected, format, method, params }) {
[provider]
);

const hasParams = params && params.length > 0;

return (
<Card shadow="lg" as="form" onSubmit={handleSubmit(submit)}>
<CardBody>
Expand All @@ -74,38 +105,82 @@ export function RpcMethodCard({ connected, format, method, params }) {
Submit
</Button>
</Flex>
{hasParams && (
{params?.length > 0 && (
<>
<Heading as="h3" size="sm" mt={4}>
Params
</Heading>
<VStack spacing={2} mt={2}>
{params.map((param) => {
const err = errors[param.key];
return (
<FormControl key={param.key} isInvalid={!!err}>
<InputGroup size="sm">
<InputLeftAddon>{param.key}</InputLeftAddon>
<Input
{...register(param.key, {
required: param.required ? `${param.key} required` : false,
})}
/>
</InputGroup>
<FormErrorMessage>{err?.message as string}</FormErrorMessage>
</FormControl>
);
})}
</VStack>
<Accordion allowMultiple mt={4} defaultIndex={shortcuts ? [1] : [0]}>
<AccordionItem>
<AccordionButton>
<Heading as="h3" size="sm" marginY={2} flex="1" textAlign="left">
Params
</Heading>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<VStack spacing={2} mt={2}>
{params.map((param) => {
const err = errors[param.key];
return (
<FormControl key={param.key} isInvalid={!!err} isRequired={param.required}>
<InputGroup size="sm">
<InputLeftAddon>{param.key}</InputLeftAddon>
<Input
{...register(param.key, {
required: param.required ? `${param.key} required` : false,
})}
/>
</InputGroup>
<FormErrorMessage>{err?.message as string}</FormErrorMessage>
</FormControl>
);
})}
</VStack>
</AccordionPanel>
</AccordionItem>
{shortcuts?.length > 0 && (
<AccordionItem>
<AccordionButton>
<Heading as="h3" size="sm" marginY={2} flex="1" textAlign="left">
Shortcuts
</Heading>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<HStack spacing={2}>
{shortcuts.map((shortcut) => (
<Button key={shortcut.key} onClick={() => submit(shortcut.data)}>
{shortcut.key}
</Button>
))}
</HStack>
</AccordionPanel>
</AccordionItem>
)}
</Accordion>
</>
)}
<VStack mt={4}>
{response && (
{response && (
<VStack mt={4}>
<Code as="pre" p={4} wordBreak="break-word" whiteSpace="pre-wrap" w="100%">
{JSON.stringify(response, null, 2)}
</Code>
)}
{error && (
</VStack>
)}
{verifyResult && (
<VStack mt={4}>
<Code
as="pre"
p={4}
colorScheme={verifyResult.includes('Failed') ? 'red' : 'cyan'}
wordBreak="break-word"
whiteSpace="pre-wrap"
w="100%"
>
{JSON.stringify(verifyResult, null, 2)}
</Code>
</VStack>
)}
{error && (
<VStack mt={4}>
<Code
as="pre"
colorScheme="red"
Expand All @@ -116,8 +191,8 @@ export function RpcMethodCard({ connected, format, method, params }) {
>
{JSON.stringify(error, null, 2)}
</Code>
)}
</VStack>
</VStack>
)}
</CardBody>
</Card>
);
Expand Down
72 changes: 0 additions & 72 deletions apps/testapp/src/components/RpcMethods/index.ts

This file was deleted.

12 changes: 12 additions & 0 deletions apps/testapp/src/components/RpcMethods/method/RpcRequestInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { JSONRPCMethod } from '@coinbase/wallet-sdk/dist/provider/JSONRPC';

type FormattedParamsType = Record<string, unknown> | string;

type methodType = `${JSONRPCMethod}`;

export type RpcRequestInput = {
connected?: boolean;
method: methodType;
params: Array<{ key: string; required?: boolean }>;
format?: (data: Record<string, string>) => FormattedParamsType[];
};
13 changes: 13 additions & 0 deletions apps/testapp/src/components/RpcMethods/method/connectionMethods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { RpcRequestInput } from './RpcRequestInput';

const ethRequestAccounts: RpcRequestInput = {
method: 'eth_requestAccounts',
params: [],
};

const ethAccounts: RpcRequestInput = {
method: 'eth_accounts',
params: [],
};

export const connectionMethods = [ethRequestAccounts, ethAccounts];
Loading

0 comments on commit b2f1e86

Please sign in to comment.