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

EIP-6551 compat #27

Merged
merged 43 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
23c3a86
upgrade to latest account-abstraction contracts
jfschwarz Apr 26, 2023
f76da22
fix package json
jfschwarz May 10, 2023
4170293
adjust tests
jfschwarz May 10, 2023
4e7cf06
trial to fix vercel routes
jfschwarz May 10, 2023
217223d
fix deploy script for gnosis chain
jfschwarz May 11, 2023
6e53bb0
implement IERC6551Account
jfschwarz May 30, 2023
3d6d79d
restructure contract inheritance hierarchy
jfschwarz Jun 7, 2023
203d1d2
add mech factory
jfschwarz Jun 7, 2023
1f67b0c
refactor contracts
jfschwarz Jun 12, 2023
de98dec
add erc20 threshold mech
jfschwarz Jun 12, 2023
c749149
cleanup
jfschwarz Jun 12, 2023
e264243
update docs
jfschwarz Jun 12, 2023
06d0971
adjust all deploy functions and migrate them to viem
jfschwarz Jun 14, 2023
b608faa
add hierarchy graph
jfschwarz Jun 20, 2023
139d356
adding exports
jfschwarz Jul 13, 2023
f8436f9
Merge branch 'main' into erc-6551
jfschwarz Aug 18, 2023
52484d9
fixes after merge
jfschwarz Aug 18, 2023
cdab142
upgrade deps
jfschwarz Aug 18, 2023
98c79c1
6551 updates and prevent ownership cycles
jfschwarz Aug 21, 2023
eb19c39
fine-tune execution interface
jfschwarz Aug 21, 2023
81dbd52
upgrade tooling
jfschwarz Aug 21, 2023
00304e4
ethers v5 -> v6 migration
jfschwarz Aug 21, 2023
8d249e6
erc165
jfschwarz Aug 21, 2023
a5a32fe
tokenbound deterministic deployment test green
jfschwarz Aug 25, 2023
cd7e95d
update 4337 entrypoint address
jfschwarz Aug 25, 2023
4167db5
fix 4337 tests
jfschwarz Aug 25, 2023
f399e1d
fix missing onlyOperator annotation
jfschwarz Aug 25, 2023
ee82d3f
improve test coverage
jfschwarz Aug 25, 2023
c2f8e3c
test fixes
jfschwarz Aug 28, 2023
a39dc16
front-end updates
jfschwarz Aug 28, 2023
5186a9c
fix deploy scripts
jfschwarz Aug 28, 2023
9fe7e05
migrate from n.xyz to sequencer
jfschwarz Sep 1, 2023
9f371eb
Merge pull request #28 from gnosis/sequencer
jfschwarz Sep 1, 2023
c57769b
deploy 6551 factory
jfschwarz Sep 4, 2023
3198123
more solid deploy script
jfschwarz Sep 4, 2023
1381bd4
fix wallet connect
jfschwarz Sep 4, 2023
63edc04
fix a JS error when switching chains
jfschwarz Oct 12, 2023
7354c08
work around issue of tokenID not being set by sequence api
jfschwarz Oct 12, 2023
0c7cc8c
fix walletconnect v2 issues
jfschwarz Oct 12, 2023
3ca7ec0
fix a ux issue
jfschwarz Oct 12, 2023
bf94f2e
upgrade to latest 6551 contract and adjust accordingly
jfschwarz Oct 13, 2023
11e9b4d
fix tests
jfschwarz Oct 13, 2023
39ef6c7
update eip6551 registry address
jfschwarz Oct 13, 2023
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
Prev Previous commit
Next Next commit
migrate from n.xyz to sequencer
  • Loading branch information
jfschwarz committed Sep 1, 2023
commit 9fe7e052bfbafdfddacc165caa878f5506091118
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"0xsequence": "^1.1.15",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"@walletconnect/client": "^1.8.0",
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/chains.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SequenceIndexerServices } from "@0xsequence/indexer"
import {
mainnet,
goerli,
Expand All @@ -23,3 +24,11 @@ export const CHAINS = {
export type ChainId = keyof typeof CHAINS

export const DEFAULT_CHAIN = CHAINS[5]

export const SEQUENCER_ENDPOINTS: Record<ChainId, SequenceIndexerServices> = {
1: SequenceIndexerServices.MAINNET,
5: SequenceIndexerServices.GOERLI,
100: SequenceIndexerServices.GNOSIS,
137: SequenceIndexerServices.POLYGON,
80001: SequenceIndexerServices.POLYGON_MUMBAI,
}
64 changes: 16 additions & 48 deletions frontend/src/components/NFTGrid/index.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,43 @@
import { useEffect, useState } from "react"

import useNFTsByOwner, { MechNFT } from "../../hooks/useNFTsByOwner"
import { ContractType, TokenBalance } from "@0xsequence/indexer"
import NFTGridItem from "../NFTGridItem"
import Spinner from "../Spinner"
import Button from "../Button"

import classes from "./NFTGrid.module.css"
import clsx from "clsx"
import { useChainId } from "wagmi"
import { useDeployedMechs } from "../../hooks/useDeployMech"
import { calculateMechAddress } from "../../utils/calculateMechAddress"
import useTokenBalances from "../../hooks/useTokenBalances"

interface Props {
address: string
}

const NFTGrid: React.FC<Props> = ({ address }) => {
const [pageToken, setPageToken] = useState<string | undefined>(undefined)

const chainId = useChainId()

const { data, isLoading } = useNFTsByOwner({
walletAddress: address,
const { balances, isLoading } = useTokenBalances({
accountAddress: address,
chainId,
pageToken,
})

const [nftData, setNftData] = useState<MechNFT[]>([])

useEffect(() => {
setNftData((nftData) => {
if (nftData.length === 0) {
return data?.assets || []
}
const ids = new Set(
nftData.map((nft) => nft.nft.tokenID + nft.contractAddress)
)

// merge and dedupe
return [
...nftData,
...data?.assets.filter(
(nft) => !ids.has(nft.nft.tokenID + nft.contractAddress)
),
]
})
}, [data])
const nftBalances = balances.filter(
(balance) =>
balance.contractType === ContractType.ERC721 ||
balance.contractType === ContractType.ERC1155
)

const deployedMechs = useDeployedMechs(nftData)
const deployedMechs = useDeployedMechs(nftBalances)

const isDeployed = (nft: MechNFT) =>
const isDeployed = (nft: TokenBalance) =>
deployedMechs.some(
(mech) =>
mech.chainId === chainId &&
mech.address.toLowerCase() === calculateMechAddress(nft).toLowerCase()
)

const deployed = nftData.filter(isDeployed)
const undeployed = nftData.filter((nft) => !isDeployed(nft))
const deployed = nftBalances.filter(isDeployed)
const undeployed = nftBalances.filter((nft) => !isDeployed(nft))

return (
<div className={classes.container}>
Expand All @@ -75,7 +55,7 @@ const NFTGrid: React.FC<Props> = ({ address }) => {
<ul className={classes.grid}>
{deployed.map((nft, index) => (
<li key={`${index}-${nft.contractAddress}`}>
<NFTGridItem nftData={nft} />
<NFTGridItem tokenBalance={nft} />
</li>
))}
</ul>
Expand All @@ -89,24 +69,12 @@ const NFTGrid: React.FC<Props> = ({ address }) => {
<ul className={classes.grid}>
{undeployed.map((nft, index) => (
<li key={`${index}-${nft.contractAddress}`}>
<NFTGridItem nftData={nft} />
<NFTGridItem tokenBalance={nft} />
</li>
))}
</ul>
)}
{isLoading ? (
<Spinner />
) : (
<Button
onClick={() => {
console.log("set page token")
setPageToken(data?.nextPageToken)
}}
secondary
>
Load more
</Button>
)}
{isLoading && <Spinner />}
</div>
)
}
Expand Down
33 changes: 18 additions & 15 deletions frontend/src/components/NFTGridItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TokenBalance } from "@0xsequence/indexer"
import { useState } from "react"
import copy from "copy-to-clipboard"
import clsx from "clsx"
Expand All @@ -7,47 +8,49 @@ import classes from "./NFTItem.module.css"
import Button from "../Button"
import { shortenAddress } from "../../utils/shortenAddress"
import Spinner from "../Spinner"
import { MechNFT } from "../../hooks/useNFTsByOwner"
import ChainIcon from "../ChainIcon"
import { calculateMechAddress } from "../../utils/calculateMechAddress"
import { CHAINS, ChainId } from "../../chains"
import { useDeployMech } from "../../hooks/useDeployMech"

interface Props {
nftData: MechNFT
tokenBalance: TokenBalance
}

const NFTGridItem: React.FC<Props> = ({ nftData }) => {
const NFTGridItem: React.FC<Props> = ({ tokenBalance }) => {
const [imageError, setImageError] = useState(false)

const chain = CHAINS[parseInt(nftData.blockchain.shortChainID) as ChainId]
const chain = CHAINS[tokenBalance.chainId as ChainId]

const mechAddress = calculateMechAddress(nftData)
const { deploy, deployPending, deployed } = useDeployMech(nftData)
const mechAddress = calculateMechAddress(tokenBalance)
const { deploy, deployPending, deployed } = useDeployMech(tokenBalance)

const name =
tokenBalance.tokenMetadata?.name || tokenBalance.contractInfo?.name

return (
<div className={classes.itemContainer}>
<div className={classes.header}>
<p className={classes.tokenName}>
<Link
to={`mechs/${chain.prefix}:${nftData.contractAddress}/${nftData.nft.tokenID}`}
to={`mechs/${chain.prefix}:${tokenBalance.contractAddress}/${tokenBalance.tokenID}`}
>
{nftData.nft.title || nftData.nft.contractTitle || "..."}
{name || "..."}
</Link>
</p>
{nftData.nft.tokenID.length < 5 && (
<p className={classes.tokenId}>{nftData.nft.tokenID || "..."}</p>
{tokenBalance.tokenID.length < 5 && (
<p className={classes.tokenId}>{tokenBalance.tokenID || "..."}</p>
)}
</div>
<div className={classes.main}>
{(!nftData.nft.previews || imageError) && (
{(imageError || !tokenBalance.tokenMetadata?.image) && (
<div className={classes.noImage}></div>
)}
{!imageError && nftData.nft.previews && (
{!imageError && tokenBalance.tokenMetadata?.image && (
<div className={classes.imageContainer}>
<img
src={nftData.nft.previews[0].URI}
alt={nftData.nft.contractTitle}
src={tokenBalance.tokenMetadata?.image}
alt={name}
className={classes.image}
onError={() => setImageError(true)}
/>
Expand All @@ -68,7 +71,7 @@ const NFTGridItem: React.FC<Props> = ({ nftData }) => {
</div>
{deployed ? (
<Link
to={`mechs/${chain.prefix}:${nftData.contractAddress}/${nftData.nft.tokenID}`}
to={`mechs/${chain.prefix}:${tokenBalance.contractAddress}/${tokenBalance.tokenID}`}
>
<Button className={classes.useButton} onClick={() => {}}>
Use Mech
Expand Down
97 changes: 47 additions & 50 deletions frontend/src/components/NFTItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,57 @@
import { TokenBalance } from "@0xsequence/indexer"
import classes from "./NFTItem.module.css"
import { useState } from "react"
import { shortenAddress } from "../../utils/shortenAddress"
import copy from "copy-to-clipboard"
import clsx from "clsx"

import useAccountBalance from "../../hooks/useAccountBalance"
import useTokenBalances from "../../hooks/useTokenBalances"
import Spinner from "../Spinner"
import { useDeployMech } from "../../hooks/useDeployMech"

import { MechNFT } from "../../hooks/useNFTsByOwner"
import { calculateMechAddress } from "../../utils/calculateMechAddress"
import { formatUnits } from "viem"

interface Props {
nftData: MechNFT
tokenBalance: TokenBalance
}

const NFTItem: React.FC<Props> = ({ nftData }) => {
const mechAddress = calculateMechAddress(nftData)

const operatorAddress = nftData.nft.owner?.address as string | undefined
const operatorLabel =
operatorAddress &&
((nftData.nft.owner?.ens && nftData.nft.owner?.ens[0]?.name) ||
shortenAddress(operatorAddress))
const NFTItem: React.FC<Props> = ({ tokenBalance }) => {
const mechAddress = calculateMechAddress(tokenBalance)
const operatorAddress = tokenBalance.accountAddress

const [imageError, setImageError] = useState(false)

const {
isLoading: assetsLoading,
data: assetsData,
error: assetsError,
} = useAccountBalance({
address: mechAddress,
chainId: parseInt(nftData.blockchain.shortChainID),
balances: mechBalances,
isLoading: mechBalancesLoading,
error: mechBalancesError,
} = useTokenBalances({
accountAddress: mechAddress,
chainId: tokenBalance.chainId,
})

const { deployed } = useDeployMech(nftData)

const { deployed } = useDeployMech(tokenBalance)
const name =
tokenBalance.tokenMetadata?.name || tokenBalance.contractInfo?.name || "..."
return (
<div className={classes.itemContainer}>
<div className={classes.header}>
<p className={classes.tokenName}>
{nftData.nft.title || nftData.nft.contractTitle || "..."}
</p>
<p className={classes.tokenName}>{name}</p>

<p className={classes.tokenId} title={nftData.nft.tokenID}>
{nftData.nft.tokenID}
<p className={classes.tokenId} title={tokenBalance.tokenID}>
{tokenBalance.tokenID}
</p>
</div>
<div className={classes.main}>
{(imageError || !nftData.nft.previews) && (
{(imageError || !tokenBalance.tokenMetadata?.image) && (
<div className={classes.noImage}></div>
)}
{!imageError && nftData.nft.previews && (
{!imageError && tokenBalance.tokenMetadata?.image && (
<div className={classes.imageContainer}>
<img
src={nftData.nft.previews[0].URI}
alt={nftData.nft.contractTitle}
src={tokenBalance.tokenMetadata?.image}
alt={name}
className={classes.image}
onError={() => setImageError(true)}
/>
Expand Down Expand Up @@ -98,45 +93,47 @@ const NFTItem: React.FC<Props> = ({ nftData }) => {
title={operatorAddress}
>
<div className={classes.ellipsis}>
{operatorAddress ? operatorLabel : "\u2014"}
{operatorAddress ? shortenAddress(operatorAddress) : "\u2014"}
</div>
</div>
</li>
<li>
{/* <li>
<label>Balance</label>
<div className={clsx(classes.infoItem)}>
{assetsError || !assetsData
? "n/a"
: `$ ${assetsData.totalBalanceUSD}`}
</div>
</li>
</li> */}
</ul>
</div>
<label>Assets</label>
<div
className={clsx(
classes.assetsContainer,
assetsData && assetsData.assets.length === 0 && classes.empty
mechBalances.length === 0 && classes.empty
)}
>
{assetsError && <p>Failed to load assets</p>}
{assetsLoading && <Spinner />}
{assetsData && (
<>
{assetsData.assets.length === 0 && <p>No assets found</p>}
<ul className={classes.assetList}>
{assetsData.assets.map((asset, index) => (
<li key={index} className={classes.asset}>
<div className={classes.name}>{asset.name}</div>
<div className={classes.value}>
<p>{asset.pretty}</p>
<p>{asset.symbol}</p>
</div>
</li>
))}
</ul>
</>
)}
{mechBalancesError && <p>Failed to load assets</p>}
{mechBalancesLoading && <Spinner />}

{mechBalances.length === 0 && <p>No assets found</p>}
<ul className={classes.assetList}>
{mechBalances.map((balance, index) => (
<li key={index} className={classes.asset}>
<div className={classes.name}>{balance.contractInfo?.name}</div>
<div className={classes.value}>
<p>
{formatUnits(
BigInt(balance.balance),
balance.contractInfo?.decimals || 0
)}
</p>
<p>{balance.contractInfo?.symbol}</p>
</div>
</li>
))}
</ul>
</div>
</div>
)
Expand Down
Loading