Skip to content

Commit

Permalink
chore: support fevm to native forward (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
hugomrdias committed Jul 24, 2023
1 parent 2faba16 commit 7996524
Show file tree
Hide file tree
Showing 16 changed files with 2,046 additions and 151 deletions.
8 changes: 6 additions & 2 deletions examples/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,22 @@
"dependencies": {
"@acab/reset.css": "^0.5.3",
"@preact/signals": "^1.1.5",
"clsx": "^2.0.0",
"filsnap-adapter": "workspace:^",
"iso-filecoin": "^1.2.0",
"iso-base": "^1.1.1",
"iso-filecoin": "^1.3.0",
"metamask-testing-tools": "^1.1.4",
"preact": "^10.16.0",
"react-hook-form": "^7.45.2",
"viem": "^1.4.1",
"wagmi": "^1.3.9",
"water.css": "^2.1.1"
},
"devDependencies": {
"@babel/core": "^7.22.9",
"@playwright/test": "^1.36.1",
"@preact/preset-vite": "^2.5.0",
"@types/node": "^20.4.3",
"@types/node": "^20.4.4",
"vite": "^4.4.6"
},
"eslintConfig": {
Expand Down
7 changes: 5 additions & 2 deletions examples/demo/src/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Network from './components/network.jsx'
import Send from './components/send.tsx'
import SignMessage from './components/sign-message.jsx'
import { useFilsnapContext } from './hooks/filsnap.js'
import ConnectFEVM from './components/connect-fevm.jsx'
import Forward from './components/forward.tsx'

export function App() {
const { isConnected } = useFilsnapContext()
Expand All @@ -13,10 +15,12 @@ export function App() {
<h1>⨎ Filsnap</h1>
<div class="Grid">
<Connect />
<Network />
{isConnected && (
<>
<Network />
<Send />
<ConnectFEVM />
<Forward />
<details class="Cell100">
<summary>Advanced</summary>
<Account />
Expand Down Expand Up @@ -50,7 +54,6 @@ export function App() {
</a>
</li>
</ul>
<br />
</div>
</div>
</main>
Expand Down
56 changes: 56 additions & 0 deletions examples/demo/src/components/connect-fevm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* eslint-disable unicorn/no-null */
/* eslint-disable unicorn/no-useless-undefined */
import { clsx } from 'clsx'
import { useAccount, useBalance, useConnect } from 'wagmi'
import { filecoin, filecoinCalibration } from 'wagmi/chains'
import { MetaMaskConnector } from 'wagmi/connectors/metaMask'
import { useFilsnapContext } from '../hooks/filsnap.js'
import ExplorerLink from './explorer-link.jsx'

export default function ConnectFEVM() {
const { account } = useFilsnapContext()
const { address, isConnected, isConnecting } = useAccount()
const { connect } = useConnect({
chainId:
account?.config.network === 'mainnet'
? filecoin.id
: filecoinCalibration.id,
connector: new MetaMaskConnector({
chains: [filecoinCalibration, filecoin],
}),
})

const { data } = useBalance({
chainId:
account?.config.network === 'mainnet'
? filecoin.id
: filecoinCalibration.id,
address,
formatUnits: 'ether',
})

let out = <button onClick={() => connect()}>Connect to Filecoin</button>
if (isConnected) {
out = (
<>
<h3>FEVM Account</h3>
<div>
<b>
{data?.formatted} {data?.symbol}
</b>
</div>
<ExplorerLink address={address} chain="ethereum" />
<ExplorerLink address={address} chain="filecoin" />
</>
)
}

if (isConnecting) {
out = <div>Connecting...</div>
}
return (
<div class={clsx('Cell75', 'Box', !isConnected && 'u-AlignCenter')}>
{out}
</div>
)
}
36 changes: 15 additions & 21 deletions examples/demo/src/components/connect.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
/* eslint-disable unicorn/no-useless-undefined */
import { useFilsnapContext } from '../hooks/filsnap.js'
import { Token } from 'iso-filecoin/token'
import { clsx } from 'clsx'
import ExplorerLink from './explorer-link.jsx'

export default function Connect() {
const { isLoading, hasFlask, isConnected, connect, account, error } =
Expand All @@ -19,7 +21,7 @@ export default function Connect() {

if (!hasFlask) {
out = (
<span data-testid="install-mm-flask">
<div data-testid="install-mm-flask">
Install Metamask{' '}
<a
href="https://chrome.google.com/webstore/detail/metamask-flask-developmen/ljfoeinjpaedjfecbmggjgodbgkmjkjk"
Expand All @@ -28,43 +30,31 @@ export default function Connect() {
>
Flask
</a>
</span>
</div>
)
}

if (isConnected) {
out = (
<>
<h3 title={account.balance + ' attoFIL'}>
<h3>Native Account</h3>
<div title={account.balance + ' attoFIL'}>
<b>
{account
? Token.fromAttoFIL(account.balance).toFIL().toFormat(6)
? Token.fromAttoFIL(account.balance).toFIL().toFormat(18)
: 'unknown'}{' '}
FIL
</b>
</h3>
</div>
<span data-testid="account-info">
Connected to{' '}
<a
target="_blank"
rel="noreferrer"
href={`https://explorer.glif.io/address/${
account.address
}/?network=${
account?.config.network === 'mainnet'
? 'mainnet'
: 'calibrationnet'
}`}
>
{account ? account.address : 'unknown'}
</a>{' '}
<ExplorerLink address={account.address} chain="filecoin" />
</span>
</>
)
}

if (isLoading) {
out = <span>Loading...</span>
out = <div>Loading...</div>
}

if (error) {
Expand All @@ -77,5 +67,9 @@ export default function Connect() {
</>
)
}
return <div class="Cell75 Box">{out}</div>
return (
<div class={clsx('Cell75', 'Box', !isConnected && 'u-AlignCenter')}>
{out}
</div>
)
}
47 changes: 47 additions & 0 deletions examples/demo/src/components/explorer-link.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as Address from 'iso-filecoin/address'
import { useFilsnapContext } from '../hooks/filsnap.js'

/**
*
* @param {object} param0
* @param {string} [param0.address]
* @param {'filecoin' | 'ethereum'} [param0.chain]
*/
export default function ExplorerLink({ address, chain }) {
const { account } = useFilsnapContext()

if (!address) return null

if (chain === 'filecoin') {
const fAddress = Address.from(address, account?.config.network).toString()
return (
<div>
{' '}
<a
target="_blank"
rel="noreferrer"
href={`https://explorer.glif.io/address/${fAddress}/?network=${
account?.config.network === 'mainnet' ? 'mainnet' : 'calibrationnet'
}`}
>
{fAddress || 'unknown'}
</a>
</div>
)
}

return (
<div>
Ξ{' '}
<a
target="_blank"
rel="noreferrer"
href={`https://explorer.glif.io/address/${address}/?network=${
account?.config.network === 'mainnet' ? 'mainnet' : 'calibrationnet'
}`}
>
{address || 'unknown'}
</a>
</div>
)
}
114 changes: 114 additions & 0 deletions examples/demo/src/components/forward.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable no-nested-ternary */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/* eslint-disable unicorn/no-useless-undefined */
import * as Address from 'iso-filecoin/address'
import { Token } from 'iso-filecoin/token'
import { useForm, type SubmitHandler } from 'react-hook-form'
import { useContractWrite } from 'wagmi'
import { abi } from '../fil-forwarder.js'
import { useFilsnapContext } from '../hooks/filsnap.js'

interface Inputs {
recipient: string
amount: string
}

/**
* Send fil to an address
*/
function Forward() {
const { account } = useFilsnapContext()
const { data, isLoading, isSuccess, error, write } = useContractWrite({
address: '0x2B3ef6906429b580b7b2080de5CA893BC282c225',
abi,
functionName: 'forward',
value: 0n,
})
// eslint-disable-next-line no-console
console.log(
'🚀 ~ file: connect-fevm.jsx:33 ~ ConnectFEVM ~ isLoading:',
isLoading,
isSuccess,
error
)

const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm<Inputs>()

const onSubmit: SubmitHandler<Inputs> = async (data) => {
if (write != null) {
const { recipient, amount } = data
write({
value: Token.fromFIL(amount).toBigInt(),
args: [Address.from(recipient).toContractDestination()],
})
reset()
}
}

return (
<div class="Box Cell100">
<h3>Forward ⨎ </h3>
{error != null && <code data-testid="error">{error.message}</code>}
<form onSubmit={handleSubmit(onSubmit)}>
<label for="recipient" id="recipient">
Recipient
</label>
<input
style={{ width: '100%' }}
disabled={isLoading}
placeholder="f0, f1, f2, f3, f4"
{...register('recipient', { required: true })}
/>
{errors.recipient != null && (
<div>
<small>This field is required</small>
</div>
)}
<label for="amount" id="amount">
Amount
</label>
<input
disabled={isLoading}
placeholder="FIL"
{...register('amount', { required: true })}
/>
{errors.amount != null && (
<div>
<small>This field is required</small>
</div>
)}

<button type="submit" data-testid="send-tx" disabled={isLoading}>
{isLoading ? 'Forwarding...' : 'Forward'}
</button>
</form>

{isSuccess && data && (
<small>
{' '}
Tx:{' '}
<a
target="_blank"
rel="noreferrer"
title="View on Glif explorer"
href={`https://explorer.glif.io/tx/${data?.hash}/?network=${
account?.config.network === 'mainnet'
? 'mainnet'
: 'calibrationnet'
}`}
>
{data?.hash}
</a>
</small>
)}
</div>
)
}

export default Forward
7 changes: 4 additions & 3 deletions examples/demo/src/components/network.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
import { useFilsnapContext } from '../hooks/filsnap.js'

export default function Connect() {
const { isLoading, connect, account } = useFilsnapContext()
const { isLoading, setSnapConfig, account } = useFilsnapContext()

return (
<div class="Cell25 Box">
<div class="Cell25 Box" style="overflow: hidden">
<h3>Network</h3>
<select
name="network"
id="network"
disabled={isLoading}
onChange={(event) => {
// @ts-ignore
connect({ network: event?.currentTarget.value })
setSnapConfig({ network: event?.currentTarget.value })
}}
class="u-FullWidth"
>
<option
value="testnet"
Expand Down

0 comments on commit 7996524

Please sign in to comment.