Skip to content

Commit

Permalink
feat: lens sign less api (#11133)
Browse files Browse the repository at this point in the history
  • Loading branch information
nuanyang233 authored Nov 15, 2023
1 parent 456ad6f commit 7331732
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export function FollowLensDialog({ handle, onClose }: Props) {
profile?.id,
currentProfile?.id,
followModule,
currentProfile?.signless,
(event: MouseEvent<HTMLElement>) => {
showConfettiExplosion(event.currentTarget.offsetWidth, event.currentTarget.offsetHeight)
setIsFollowing(true)
Expand All @@ -208,6 +209,7 @@ export function FollowLensDialog({ handle, onClose }: Props) {
const { loading: unfollowLoading, handleUnfollow } = useUnfollow(
profile?.id,
currentProfile?.id,
currentProfile?.signless,
(event: MouseEvent<HTMLElement>) => {
setIsFollowing(false)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
useWallet,
useWeb3Others,
} from '@masknet/web3-hooks-base'
import { ProviderType } from '@masknet/web3-shared-evm'
import { ChainId, ProviderType } from '@masknet/web3-shared-evm'
import type { LensBaseAPI } from '@masknet/web3-providers/types'
import { Icons } from '@masknet/icons'
import { ProfilePopup } from './ProfilePopup.js'
Expand Down Expand Up @@ -85,7 +85,12 @@ export const HandlerDescription = memo<HandlerDescriptionProps>(({ profiles, cur
</Box>
<Button
variant="text"
onClick={() => SelectProviderModal.open({ requiredSupportPluginID: NetworkPluginID.PLUGIN_EVM })}>
onClick={() =>
SelectProviderModal.open({
requiredSupportPluginID: NetworkPluginID.PLUGIN_EVM,
requiredSupportChainIds: [ChainId.Matic],
})
}>
{t.wallet_status_button_change()}
</Button>
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Icons } from '@masknet/icons'
import { Image } from '@masknet/shared'
import { CrossIsolationMessages } from '@masknet/shared-base'
import { CrossIsolationMessages, EMPTY_LIST } from '@masknet/shared-base'
import { ActionButton, makeStyles } from '@masknet/theme'
import type { FireflyBaseAPI } from '@masknet/web3-providers/types'
import { List, ListItem, Typography, type ListProps } from '@mui/material'
Expand Down Expand Up @@ -82,9 +82,9 @@ export const LensList = memo(({ className, accounts, ...rest }: Props) => {
const { account: wallet } = useChainContext()

const { data = accounts, isLoading } = useQuery({
queryKey: ['Lens', 'Popup-List', accounts.map((x) => x.handle).join('')],
queryKey: ['Lens', 'Popup-List', accounts.map((x) => x.handle).join(''), wallet],
queryFn: async () => {
if (!accounts.length) return
if (!accounts.length) return EMPTY_LIST
let currentProfile = await Lens.queryDefaultProfileByAddress(wallet)
if (!currentProfile?.id) {
const profiles = await Lens.queryProfilesByAddress(wallet)
Expand Down Expand Up @@ -120,6 +120,7 @@ export const LensList = memo(({ className, accounts, ...rest }: Props) => {
}),
)
},

refetchOnWindowFocus: false,
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from '@mui/material'
import { memo } from 'react'
import { Image, SelectProviderModal, WalletIcon } from '@masknet/shared'
import { formatEthereumAddress } from '@masknet/web3-shared-evm'
import { ChainId, formatEthereumAddress } from '@masknet/web3-shared-evm'
import { NetworkPluginID } from '@masknet/shared-base'
import { Others } from '@masknet/web3-providers'
import { useChainContext, useProviderDescriptor } from '@masknet/web3-hooks-base'
Expand Down Expand Up @@ -174,7 +174,12 @@ export const ProfilePopup = memo<ProfilePopupProps>(function ProfilePopup({
</Box>
<Button
variant="text"
onClick={() => SelectProviderModal.open({ requiredSupportPluginID: NetworkPluginID.PLUGIN_EVM })}>
onClick={() =>
SelectProviderModal.open({
requiredSupportPluginID: NetworkPluginID.PLUGIN_EVM,
requiredSupportChainIds: [ChainId.Matic],
})
}>
{t.wallet_status_button_change()}
</Button>
</Box>
Expand Down
162 changes: 101 additions & 61 deletions packages/plugins/Web3Profile/src/SiteAdaptor/hooks/Lens/useFollow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export function useFollow(
profileId?: string,
currentProfileId?: string,
followModule?: FollowModuleTypedData,
signless?: boolean,
onSuccess?: (event: MouseEvent<HTMLElement>) => void,
onFailed?: () => void,
) {
Expand All @@ -43,6 +44,75 @@ export function useFollow(
[showSnackbar, closeSnackbar],
)

const broadcastAction = useCallback(
async (event: MouseEvent<HTMLElement>) => {
if (!profileId || chainId !== ChainId.Matic) return
const token = await handleQueryAuthenticate()
if (!token) return

const typedData = await Lens.createFollowTypedData(profileId, { token, followModule })

if (!typedData) return

const signature = await Web3.signMessage(
'typedData',
JSON.stringify({
domain: typedData.typedData.domain,
primaryType: 'Follow',
message: typedData.typedData.value,
types: {
Follow: typedData.typedData.types.Follow,
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
},
}),
{ chainId },
)

const { v, r, s } = splitSignature(signature)

const { deadline, idsOfProfilesToFollow, followerProfileId, followTokenIds, datas } =
typedData.typedData.value

let hash: string | undefined

try {
const broadcast = await Lens.broadcast(typedData.id, signature, { token, fetcher: fetchJSON })
if (broadcast?.__typename === BroadcastType.RelayError) throw new Error(broadcast.reason)
else hash = broadcast?.txHash
} catch {
onFailed?.()
const tx = await new ContractTransaction(lensHub).fillAll(
lensHub?.methods.followWithSig(followerProfileId, idsOfProfilesToFollow, followTokenIds, datas, [
account,
v,
r,
s,
deadline,
]),
{
from: account,
},
)

hash = await Web3.sendTransaction(tx)
}

if (!hash) return
onSuccess?.(event)

const receipt = await Web3.confirmTransaction(hash, {
signal: AbortSignal.timeout(3 * 60 * 1000),
})
if (!receipt.status) throw new Error('Failed to Follow')
},
[handleQueryAuthenticate, profileId, account, chainId, onSuccess, fetchJSON, onFailed],
)

const handleFollow = useCallback<(event: MouseEvent<HTMLElement>) => Promise<void>>(
async (event: MouseEvent<HTMLElement>) => {
const cloneEvent = cloneDeep(event)
Expand All @@ -53,67 +123,27 @@ export function useFollow(
const token = await handleQueryAuthenticate()
if (!token) return

setLoading(true)
const typedData = await Lens.createFollowTypedData(profileId, { token, followModule })

if (!typedData) return

const signature = await Web3.signMessage(
'typedData',
JSON.stringify({
domain: typedData.typedData.domain,
primaryType: 'Follow',
message: typedData.typedData.value,
types: {
Follow: typedData.typedData.types.Follow,
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
},
}),
{ chainId },
)

const { v, r, s } = splitSignature(signature)

const { deadline, idsOfProfilesToFollow, followerProfileId, followTokenIds, datas } =
typedData.typedData.value

let hash: string | undefined

try {
const broadcast = await Lens.broadcast(typedData.id, signature, { token, fetcher: fetchJSON })
if (broadcast?.__typename === BroadcastType.RelayError) throw new Error(broadcast.reason)
else hash = broadcast?.txHash
} catch {
onFailed?.()
const tx = await new ContractTransaction(lensHub).fillAll(
lensHub?.methods.followWithSig(
followerProfileId,
idsOfProfilesToFollow,
followTokenIds,
datas,
[account, v, r, s, deadline],
),
{
from: account,
},
)

hash = await Web3.sendTransaction(tx)
if (signless && !followModule?.feeFollowModule) {
try {
const result = await Lens.follow(profileId, { token, followModule, fetcher: fetchJSON })
if (result?.__typename === BroadcastType.RelayError) throw new Error('Failed to follow')
else if (result?.txHash) {
setLoading(false)
onSuccess?.(cloneEvent)
const receipt = await Web3.confirmTransaction(result.txHash, {
signal: AbortSignal.timeout(3 * 60 * 1000),
})
if (!receipt.status) {
onFailed?.()
throw new Error('Failed to follow')
}
}
} catch {
broadcastAction(cloneEvent)
}
} else {
broadcastAction(cloneEvent)
}

if (!hash) return
onSuccess?.(cloneEvent)
setLoading(false)

const receipt = await Web3.confirmTransaction(hash, {
signal: AbortSignal.timeout(3 * 60 * 1000),
})
if (!receipt.status) throw new Error('Failed to Follow')
} catch (error) {
if (
error instanceof Error &&
Expand All @@ -134,7 +164,17 @@ export function useFollow(
setLoading(false)
}
},
[handleQueryAuthenticate, profileId, account, chainId, onSuccess, fetchJSON, showSingletonSnackbar, onFailed],
[
signless,
profileId,
onSuccess,
onFailed,
handleQueryAuthenticate,
broadcastAction,
followModule,
fetchJSON,
chainId,
],
)

return { loading, handleFollow }
Expand Down
Loading

0 comments on commit 7331732

Please sign in to comment.