Skip to content

Commit

Permalink
Waas integration (#9)
Browse files Browse the repository at this point in the history
* WIP

* Fix disconnect

* Fixes and demo improvements

* Refactor

* Fix duplicate connector issue, add proper session name

* Network switching, updated provider

* Show current chain in demo

* Reset prev demo state of sent txn and signed message on chain change

* Remove unnecessary call

* Add default return to request for unhandled cases

* Update package.json

* pnpm version

* version update to 2.0.5-beta.1

* react example updated package

* Temp prod key for clients

* Fix address view for mobile

* Update demo content height and padding for mobile

* version 2.0.5-beta.2

* Update kit versions in example app

* Waas request confirmation (WIP)

* WIP

* Confirmation request type for hook, better signature confirmation view

* Fix dup values added for testing

* Email connector (WIP)

* Refactor config

* Add id for confirmation requests

* Email connector selection

* Refactor, hook for email auth

* Waas email auth

* Error handling

* Minor fixes

* Apple login (WIP) and other fixes

* 2.0.5-beta.3

* Use kit v beta.3

* Fix script loading, publish 2.0.5-beta.4

* Apple login missing parts

* 2.0.5-beta.5

* Apple response undefined check

* Use 2.0.5-beta.5

* Regenerate hash on disconnect

* 2.0.5-beta.6

* Use 2.0.5-beta.6

* Update sequence to v1.9.0

* 2.0.5-beta.7

* Use 2.0.5-beta.7

* Update styles

* 2.0.5-beta.8

* Use 2.0.5-beta.8

* Bump sequence.js version in example

* Fix initial jsonRpcProvider network issue

* 2.0.5-beta.9

* Bump sequence version to 1.9.6

* Improvements

* 2.0.5-beta.10

* appleRedirectURI from host

* Use 2.0.5-beta.10

* Check for wallet deployment only for waas connectors

* Update example

* Remove console log

* Improved WaaS confirmation pop up

* Fix type warnings

* 2.0.5-beta.11

* NFT demo, other fixes

* Ignore warning

* New beta version

* Add confirmation toggle

* Wallet package improvements

* 2.0.5-beta.13

* Fix wallet issues

* 2.0.5-beta.14

* Use 2.0.5-beta.14 in examples/react

* Improve getting default connectors

* Merge branch 'master' into waas-integration

* Add option for fetching balance with 'verifiedOnly: false'

* Update sequence.js deps

* Make enableConfirmationModal param optional

* Add useWaasFeeOptions hook

* 2.0.8-beta

* Fix overflow issue

* Add simpler example for waas

* 2.0.8-beta.1

* Use universal wallet config for main demo

* Handle txnData as hash in case it's not an object

* Hide use confirmation toggle if not using waas in examples/react

* Fix confirmation handler order, add missing type

* Improve waas demo

* Update comment

* Remove unnecessary imports

* 2.0.8-beta.2

* Add missing import

* Remove pre.json, update package.json

---------

Co-authored-by: samuelea <[email protected]>
  • Loading branch information
tolgahan-arikan and SamueleA authored Apr 12, 2024
1 parent b81895d commit abb352d
Show file tree
Hide file tree
Showing 74 changed files with 5,886 additions and 882 deletions.
18 changes: 18 additions & 0 deletions examples/react-waas/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
30 changes: 30 additions & 0 deletions examples/react-waas/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

- Configure the top-level `parserOptions` property like this:

```js
export default {
// other rules...
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
}
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
13 changes: 13 additions & 0 deletions examples/react-waas/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="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
34 changes: 34 additions & 0 deletions examples/react-waas/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@0xsequence/kit-example-react-waas",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "vite --port 4444",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"0xsequence": "^1.9.11",
"@0xsequence/kit": "workspace:*",
"@0xsequence/kit-checkout": "workspace:*",
"@tanstack/react-query": "^4.36.1",
"viem": "^2.5.7",
"wagmi": "^2.5.7"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"typescript": "^5.2.2",
"vite": "^5.2.0"
}
}
59 changes: 59 additions & 0 deletions examples/react-waas/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 10px;
margin: 6px;
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
justify-content: center;
background: rgba(29, 32, 35, 0.5);
border-radius: 6px;
width: 100%;
}

.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 440px;
}

.read-the-docs {
color: #888;
}
205 changes: 205 additions & 0 deletions examples/react-waas/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import './App.css'
import { useOpenConnectModal, useWaasFeeOptions } from '@0xsequence/kit'
import {
useAccount,
useChainId,
useDisconnect,
usePublicClient,
useSendTransaction,
useSwitchChain,
useWalletClient
} from 'wagmi'
import { sequence } from '0xsequence'
import { formatUnits } from 'viem'
import { useEffect, useState } from 'react'

function App() {
const { setOpenConnectModal } = useOpenConnectModal()
const { disconnect } = useDisconnect()
const { data: walletClient } = useWalletClient()
const { address, isConnected } = useAccount()

// Switching chain
const { switchChain } = useSwitchChain()
const chainId = useChainId()
const networkForCurrentChainId = sequence.network.allNetworks.find(n => n.chainId === chainId)

const switchNetwork = () => {
if (chainId === 421614) {
switchChain({ chainId: 42170 })
} else {
switchChain({ chainId: 421614 })
}

setLastTxnDataHash(undefined)
setMessageSig(undefined)
setIsMessageValid(undefined)
}

// Signing and verifying message
const messageToSign = 'Two roads diverged in a yellow wood'
const publicClient = usePublicClient({ chainId })

const [isSigningMessage, setIsSigningMessage] = useState(false)
const [messageSig, setMessageSig] = useState<string | undefined>()
const [isMessageValid, setIsMessageValid] = useState<boolean | undefined>()

const signMessage = async () => {
if (!walletClient) {
return
}

setMessageSig(undefined)
setIsMessageValid(undefined)

setIsSigningMessage(true)

try {
const message = messageToSign

// sign
const sig = await walletClient.signMessage({
account: address || ('' as `0x${string}`),
message
})
console.log('address', address)
console.log('signature:', sig)
console.log('chainId in homepage', chainId)

const [account] = await walletClient.getAddresses()

const isValid = await publicClient?.verifyMessage({
address: account,
message,
signature: sig
})

setIsSigningMessage(false)
setIsMessageValid(isValid)
setMessageSig(sig)

console.log('isValid?', isValid)
} catch (e) {
setIsSigningMessage(false)
console.error(e)
}
}

// Sending txn
const [lastTxnDataHash, setLastTxnDataHash] = useState<string | undefined>()

const { data: txnData, sendTransaction, isLoading } = useSendTransaction()
const runSendTransaction = async () => {
if (!walletClient) {
return
}

const [account] = await walletClient.getAddresses()

sendTransaction({ to: account, value: '0', gas: null })
}

useEffect(() => {
if (txnData) {
setLastTxnDataHash(txnData.hash ?? txnData)
}
}, [txnData])

// Fee options are required when txn is not gas sponsored (not needed on testnets)
const [pendingFeeOptionConfirmation, confirmPendingFeeOption, rejectPendingFeeOption] = useWaasFeeOptions()

const [selectedFeeTokenAddress, setSelectedFeeTokenAddress] = useState<string | null | undefined>() // option is null for native token, string for erc20 token
useEffect(() => {
if (pendingFeeOptionConfirmation) {
setSelectedFeeTokenAddress(pendingFeeOptionConfirmation.options[0].token.contractAddress) // preselect first option
}
}, [pendingFeeOptionConfirmation])

const confirmFeeOption = () => {
if (pendingFeeOptionConfirmation && selectedFeeTokenAddress !== undefined) {
confirmPendingFeeOption(pendingFeeOptionConfirmation.id, selectedFeeTokenAddress)
}
}

return (
<div>
<div className="container">
<h2 style={{ marginBottom: '10px' }}>Vite + React + Sequence Kit with WaaS</h2>
{!isConnected && (
<div className="card" style={{ background: 'transparent' }}>
<button onClick={() => setOpenConnectModal(true)}>Connect</button>
</div>
)}

{isConnected && (
<>
<div className="card">{isConnected && <p>Wallet address: ({address})</p>}</div>

<div className="card">
<p>Network: {networkForCurrentChainId?.name}</p>
<button onClick={() => switchNetwork()} disabled={isLoading}>
Switch network
</button>
</div>
<div className="card">
<button onClick={() => runSendTransaction()} disabled={isLoading}>
Send transaction
</button>

{isLoading && <p>Transaction is pending...</p>}

{lastTxnDataHash && (
<div>
<p style={{ overflowWrap: 'anywhere' }}>Transaction hash: {lastTxnDataHash}</p>

<a target="_blank" href={`${networkForCurrentChainId?.blockExplorer.rootUrl}/tx/${lastTxnDataHash}`}>
View on {networkForCurrentChainId?.name} explorer
</a>
</div>
)}

{pendingFeeOptionConfirmation && (
<div className="card">
<p>Select fee option</p>
<select className="fee-option-select" onChange={e => setSelectedFeeTokenAddress(e.target.value)}>
{pendingFeeOptionConfirmation.options.map(option => {
return (
<option key={option.token.contractAddress} value={option.token.contractAddress}>
{option.token.name} - {formatUnits(BigInt(option.value), option.token!.decimals!)}
</option>
)
})}
</select>

<button style={{ display: 'block' }} onClick={() => confirmFeeOption()}>
Confirm fee option
</button>
</div>
)}
</div>

<div className="card">
<p>Sign message</p>
<p>Message: {messageToSign}</p>
<button onClick={signMessage} disabled={isLoading}>
Sign message
</button>

{isSigningMessage && <p>Signing message...</p>}

{messageSig && <p style={{ overflowWrap: 'anywhere' }}>Signature: {messageSig}</p>}

{isMessageValid && <p>isValid: {isMessageValid.toString()}</p>}
</div>

<div className="card" style={{ background: 'transparent' }}>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
</>
)}
</div>
</div>
)
}

export default App
Loading

0 comments on commit abb352d

Please sign in to comment.