Skip to content

Commit

Permalink
Emit ESModules alongside CommonJS and use eth-sdk in Vite + React exa…
Browse files Browse the repository at this point in the history
…mple (#28)

* Add vite-react example

* Transpile client both to ESM and CJS

* Add --no-lockfile flag

* Create blue-feet-eat.md

* List examples in readme
  • Loading branch information
hasparus authored Oct 28, 2021
1 parent e68c2c9 commit 6c0ae88
Show file tree
Hide file tree
Showing 72 changed files with 4,328 additions and 68 deletions.
6 changes: 6 additions & 0 deletions .changeset/blue-feet-eat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@dethcrypto/eth-sdk-client": patch
"@dethcrypto/eth-sdk": patch
---

Emit ESModules alongside CommonJS
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
parserOptions: {
project: './tsconfig.json',
sourceType: 'module',
extraFileExtensions: ['.mjs', '.cjs'],
},
rules: {
// this gets inlined into a package eslint, so it means: use current package's package.info or the one at the project root
Expand Down
7 changes: 4 additions & 3 deletions examples/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
"name": "hardhat-project",
"license": "MIT",
"scripts": {
"postinstall": "eth-sdk",
"verify": "yarn format && yarn lint && yarn test && yarn typecheck",
"test": "hardhat run ./scripts/exploit.ts",
"test": "yarn generate-types && hardhat run ./scripts/exploit.ts",
"format": "../../node_modules/.bin/prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --check \"./**/*.ts\"",
"format:fix": "../../node_modules/.bin/prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --write \"./**/*.ts\"",
"lint": "../../node_modules/.bin/eslint --ext .ts scripts",
"lint:fix": "yarn lint --fix",
"typecheck": "tsc --noEmit --incremental false --composite false",
"clean": "rm -rf dist && rm -f tsconfig.build.tsbuildinfo",
"test:fix": "yarn lint:fix && yarn format:fix && yarn test && yarn typecheck"
"test:fix": "yarn lint:fix && yarn format:fix && yarn test && yarn typecheck",
"generate-types": "eth-sdk",
"postinstall": "yarn generate-types"
},
"devDependencies": {
"@dethcrypto/eth-sdk": "file:../../packages/eth-sdk",
Expand Down
6 changes: 6 additions & 0 deletions examples/vite-react/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
cache
4 changes: 4 additions & 0 deletions examples/vite-react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
You can run the dev server in the example with `yarn dev` or build

If you copy the directory outside of eth-sdk repo, make sure to change `@dethcrypto` dependencies from relative
`file:../../` installs to newest released versions.
1 change: 1 addition & 0 deletions examples/vite-react/eth-sdk/abis/mainnet/dai.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"inputs":[{"internalType":"uint256","name":"chainId_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"pull","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"push","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
5 changes: 5 additions & 0 deletions examples/vite-react/eth-sdk/contracts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"mainnet": {
"dai": "0x6b175474e89094c44da98b954eedeac495271d0f"
}
}
48 changes: 48 additions & 0 deletions examples/vite-react/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require('@nomiclabs/hardhat-ethers') as typeof import('@nomiclabs/hardhat-ethers')

const { task } = require('hardhat/config') as typeof import('hardhat/config')

require('dotenv').config()

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners()

for (const account of accounts) {
console.log(addressWithBalance(account, hre))
}
})

const ALCHEMY_THROWAWAY_URL = 'https://eth-mainnet.alchemyapi.io/v2/Dr5usbY6KnDFmPBD-ky7I1J8DBny-i-G'

const config: import('hardhat/config').HardhatUserConfig = {
solidity: {
version: '0.8.7',
settings: {
optimizer: {
enabled: true,
runs: 1000,
},
},
},
networks: {
hardhat: {
initialBaseFeePerGas: 0,
forking: {
url: ALCHEMY_THROWAWAY_URL,
blockNumber: 13485726,
},
},
},
}

module.exports = { default: config }

async function addressWithBalance(
{ address }: { address: string },
hre: import('hardhat/types').HardhatRuntimeEnvironment,
) {
const balance = await hre.ethers.provider.getBalance(address)
return `${address} ${hre.ethers.utils.formatEther(balance)} ETH`
}
13 changes: 13 additions & 0 deletions examples/vite-react/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>eth-sdk React Vite example</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
39 changes: 39 additions & 0 deletions examples/vite-react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@dethcrpyot/vite-react-example",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "concurrently --names \"hhat\",\"vite\" --c \"magenta,cyan\" \"hardhat node\" \"vite\"",
"build": "tsc && vite build",
"serve": "vite preview",
"generate-types": "eth-sdk",
"verify": "yarn build && yarn format && yarn lint && yarn test",
"postinstall": "yarn generate-types",
"format": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --check \"./**/*.ts\"",
"format:fix": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --write \"./**/*.ts\"",
"lint": "eslint --ext .ts scripts",
"lint:fix": "yarn lint --fix",
"typecheck": "tsc --noEmit --incremental false --composite false",
"clean": "rm -rf dist && rm -f tsconfig.build.tsbuildinfo",
"test:fix": "yarn lint:fix && yarn format:fix && yarn test && yarn typecheck"
},
"dependencies": {
"@dethcrypto/eth-sdk": "file:../../packages/eth-sdk",
"@dethcrypto/eth-sdk-client": "file:../../packages/client",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"ethers": "^5.4.7",
"hardhat": "^2.6.5",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-query": "^3.28.0"
},
"devDependencies": {
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@vitejs/plugin-react": "^1.0.0",
"concurrently": "^6.3.0",
"ts-node": "^10.4.0",
"typescript": "^4.4.0",
"vite": "^2.6.4"
}
}
57 changes: 57 additions & 0 deletions examples/vite-react/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.holders-list {
list-style: none;
display: flex;
flex-direction: column;
gap: 0.5em;
padding: 0;
margin: 0;
}

.holders-list-item {
border-radius: 0.5em;
height: 4.5em;
padding: 0 0.5em;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}

.text-mono {
font-family: var(--mono);
}

.text-small {
font-size: 0.8em;
}

.text-italic {
font-style: italic;
}

.text-bold {
font-weight: bold;
}

.text-gray {
color: #777;
}

.column {
display: flex;
flex-direction: column;
}

.App {
max-width: 800px;
overflow: hidden;
text-overflow: ellipsis;

margin: 0 auto;
padding: 1em 0;

display: flex;
flex-direction: column;
gap: 0.5em;
}
80 changes: 80 additions & 0 deletions examples/vite-react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import './App.css'

import { getMainnetSdk } from '@dethcrypto/eth-sdk-client'
import { ethers } from 'ethers'
import { Suspense, useState } from 'react'
import { useQuery } from 'react-query'

export function App() {
const [address, setAddress] = useState(defaultSigner.address)
const balance = useDaiBalance(address)

return (
<main className="App">
<label className="column">
<div className="text-small">Address</div>
<input
onChange={(event) => {
const { value } = event.target
if (value.length === 42) setAddress(value)
}}
/>
</label>
<div>
<div id="balance-label" className="text-small">
DAI Balance {balance.isLoading && <span className="text-italic text-small text-gray">Loading...</span>}
</div>
<output aria-labelledby="balance-label">{balance.data}</output>
</div>
<hr />
<ul className="holders-list">
{holders.map((holder, i) => (
<Suspense fallback={null} key={i}>
<li className="holders-list-item">
<div className="text-small">{holder.address}</div>
<div className="text-small text-bold text-gray">{holder.tag}</div>
<Balance address={holder.address} />
</li>
</Suspense>
))}
</ul>
</main>
)
}

const mainnetProvider = ethers.getDefaultProvider('mainnet')
const defaultSigner = ethers.Wallet.createRandom().connect(mainnetProvider)
const { dai } = getMainnetSdk(defaultSigner)

function useDaiBalance(address: string, options: { suspense?: boolean } = {}) {
return useQuery(
`balanceOf-${address}`,
async () => {
const balance = await dai.balanceOf(address)

return ethers.utils.formatUnits(balance, 18)
},
options,
)
}

function Balance({ address }: { address: string }) {
const balance = useDaiBalance(address, { suspense: true })

return <span className="text-mono">{balance.data}</span>
}

const holders = [
{
tag: 'Curve.fi: DAI/USDC/USDT Pool',
address: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
},
{
tag: 'Compound: cDAI Token',
address: '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643',
},
{
tag: 'Aave: aDAI Token V2',
address: '0x028171bca77440897b824ca71d1c56cac55b68a3',
},
]
15 changes: 15 additions & 0 deletions examples/vite-react/src/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions examples/vite-react/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
html {
font-size: calc(10px + 1.5vmin);

--body: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
'Droid Sans', 'Helvetica Neue', sans-serif;
--mono: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
}

body {
margin: 0;
font-family: var(--body);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: var(--mono);
}

input {
font: inherit;
padding: 0.5em;
font-family: var(--mono);
}

hr {
width: 100%;
border: none;
border-block-start: 5px dashed #f5f5f5;
}
18 changes: 18 additions & 0 deletions examples/vite-react/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import './index.css'

import React from 'react'
import ReactDOM from 'react-dom'
import { QueryClient, QueryClientProvider } from 'react-query'

import { App } from './App'

const queryClient = new QueryClient()

ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</React.StrictMode>,
document.getElementById('root'),
)
1 change: 1 addition & 0 deletions examples/vite-react/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
19 changes: 19 additions & 0 deletions examples/vite-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["./src"]
}
4 changes: 4 additions & 0 deletions examples/vite-react/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'

export default defineConfig({ plugins: [react()] })
1 change: 1 addition & 0 deletions packages/client/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '.dethcrypto/eth-sdk-client'
Loading

0 comments on commit 6c0ae88

Please sign in to comment.