Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function NftRedPacket({ payload, currentPluginID }: NftRedPacketProps) {
isPending: loading,
refetch: retryAvailability,
error: availabilityError,
} = useAvailabilityNftRedPacket(payload.id, account, payload.chainId)
} = useAvailabilityNftRedPacket(payload.id as HexString, account as HexString, payload.chainId)

const [{ loading: isClaiming }, claimCallback] = useClaimNftRedpacketCallback(payload, availability?.totalAmount)

Expand All @@ -93,7 +93,7 @@ export function NftRedPacket({ payload, currentPluginID }: NftRedPacketProps) {
const { data: claimedAsset, error: assetError } = useNonFungibleAsset(
NetworkPluginID.PLUGIN_EVM,
payload.contractAddress,
availability?.claimed_id,
availability?.claimed_id === undefined ? undefined : String(availability.claimed_id),
{
chainId: payload.chainId,
sourceType: SourceType.SimpleHash,
Expand Down Expand Up @@ -181,7 +181,7 @@ export function NftRedPacket({ payload, currentPluginID }: NftRedPacketProps) {
creator={payload.senderName}
chainId={payload.chainId}
address={payload.contractAddress}
tokenId={availability.claimed_id}
tokenId={availability.claimed_id === undefined ? undefined : String(availability.claimed_id)}
shares={availability.totalAmount}
claimedCount={+availability.claimedAmount}
total={availability.totalAmount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export const NftRedPacketRecord = memo(function NftRedPacketRecord({
backgroundIcon: networkDescriptor ? `url("${networkDescriptor.icon}")` : undefined,
})

const { canSend, isPasswordValid, password } = useNftAvailabilityComputed(account, patchedHistory)
const { canSend, isPasswordValid, password } = useNftAvailabilityComputed(account as HexString | '', patchedHistory)

const collection = collections.find((x) => isSameAddress(x.address, patchedHistory.token_address))

Expand All @@ -190,7 +190,11 @@ export const NftRedPacketRecord = memo(function NftRedPacketRecord({
onSend({ ...patchedHistory, password: patchedHistory.password || password }, collection)
}, [onSend, canSend, patchedHistory, collection, isPasswordValid, password])

const { data: redpacketStatus } = useAvailabilityNftRedPacket(rpid, account, patchedHistory.chainId)
const { data: redpacketStatus } = useAvailabilityNftRedPacket(
rpid as HexString | '',
account as HexString | '',
patchedHistory.chainId,
)
const bitStatusList =
redpacketStatus ? redpacketStatus.bitStatusList : fill(Array(patchedHistory.token_ids.length), false)
const locale = useLingui().i18n.locale
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import type { ChainId } from '@masknet/web3-shared-evm'
import { useQuery } from '@tanstack/react-query'
import { BigNumber } from 'bignumber.js'
import { createNftRedpacketContract } from './useNftRedPacketContract.js'

export function useAvailabilityNftRedPacket(id: string, from: string, chainId?: ChainId) {
export function useAvailabilityNftRedPacket(id: HexString | '', from: HexString | '', chainId?: ChainId) {
return useQuery({
queryKey: ['nft-redpacket', 'availability', chainId, from, id],
queryFn: async () => {
const nftRedPacketContract = createNftRedpacketContract(chainId)
if (!id || !nftRedPacketContract) return null
const availability = await nftRedPacketContract.methods.check_availability(id).call({
// check availability is ok w/o account
from,
})
const [token_address, balance, total_pkts, expired, claimed_id, bit_status] =
await nftRedPacketContract.read.check_availability([id], {
// check availability is ok w/o account
account: from || undefined,
})

const result = await nftRedPacketContract.methods.check_erc721_remain_ids(id).call({
const [bit_status2, erc721_token_ids] = await nftRedPacketContract.read.check_erc721_remain_ids([id], {
// check availability is ok w/o account
from,
account: from || undefined,
})

const isClaimed = availability.claimed_id !== '0'
const totalAmount = result.erc721_token_ids.length
const bits = new BigNumber(result.bit_status).toString(2).split('')
const isClaimed = claimed_id !== 0n
const totalAmount = erc721_token_ids.length
const bits = bit_status2.toString(2).split('')
const claimedAmount = bits.filter((bit) => bit === '1').length
const isClaimedAll = totalAmount === claimedAmount
const isCompleted = isClaimedAll && !isClaimed
const isEnd = isCompleted || availability.expired
const isEnd = isCompleted || expired

const bitStatusList = bits.reverse().map((bit) => bit === '1')

Expand All @@ -40,8 +40,12 @@ export function useAvailabilityNftRedPacket(id: string, from: string, chainId?:
isCompleted,
isEnd,
bitStatusList,
...availability,
claimed_id: availability.claimed_id === '0' ? undefined : availability.claimed_id,
token_address,
balance,
total_pkts,
expired,
bit_status,
claimed_id: claimed_id === 0n ? undefined : claimed_id,
}
},
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { toHex, type NetworkPluginID } from '@masknet/shared-base'
import { NftRedPacketAbi, type NftRedPacket } from '@masknet/web3-contracts/types/NftRedPacket.js'
import { NftRedPacketAbi } from '@masknet/web3-contracts/types/NftRedPacket.js'
import { useChainContext } from '@masknet/web3-hooks-base'
import { useGasConfig } from '@masknet/web3-hooks-evm'
import { EVMWeb3 } from '@masknet/web3-providers'
Expand All @@ -17,14 +17,15 @@ import { BigNumber } from 'bignumber.js'
import { useMemo } from 'react'
import { useAsyncFn } from 'react-use'
import { createNftRedpacketContract } from './useNftRedPacketContract.js'
import { keccak256 } from 'viem'
import { encodeFunctionData, keccak256 } from 'viem'
import type { AbiParametersToPrimitiveTypes, ExtractAbiFunction } from 'abitype'

interface Options {
publicKey: string
publicKey: HexString
duration: number
message: string
creator: string
contractAddress: string
contractAddress: HexString
tokenIds: string[]
gasOption?: GasConfig
}
Expand All @@ -39,15 +40,19 @@ export function useCreateNftRedpacketCallback({
gasOption,
}: Options) {
const { account, chainId } = useChainContext<NetworkPluginID.PLUGIN_EVM>()
const params: Parameters<NftRedPacket['methods']['create_red_packet']> = useMemo(() => {
const params = useMemo((): AbiParametersToPrimitiveTypes<
ExtractAbiFunction<NftRedPacketAbi, 'create_red_packet'>['inputs'],
'inputs',
true
> => {
return [
publicKey,
duration,
BigInt(duration),
keccak256(toHex(Math.random().toString())),
message,
creator,
contractAddress,
tokenIds,
tokenIds.map(BigInt),
]
}, [publicKey, duration, message, creator, contractAddress, tokenIds])

Expand All @@ -66,13 +71,13 @@ export function useCreateNftRedpacketCallback({
],
refetchInterval: 10,
queryFn: async () => {
if (!account) return null
if (!account || !contractAddress) return null
const nftRedPacketContract = createNftRedpacketContract(chainId)
if (!nftRedPacketContract) return null

const gasLimit = await nftRedPacketContract.methods
.create_red_packet(...params)
.estimateGas({ from: account })
const gasLimit = await nftRedPacketContract.estimateGas.create_red_packet(params, {
account: account as HexString,
})
return gasLimit
},
})
Expand All @@ -81,7 +86,7 @@ export function useCreateNftRedpacketCallback({
const estimateGasFee = useMemo(() => {
if (!gasLimit) return undefined
if (!gasPrice || gasPrice === '0') return undefined
return new BigNumber(gasPrice).multipliedBy(gasLimit).multipliedBy(1.5).toFixed()
return new BigNumber(gasPrice).multipliedBy(String(gasLimit)).multipliedBy(1.5).toFixed()
}, [gasLimit, gasPrice])

const [{ loading }, createCallback] = useAsyncFn(async (): Promise<
Expand All @@ -99,22 +104,24 @@ export function useCreateNftRedpacketCallback({
}

// #region check ownership
const checkParams: Parameters<NftRedPacket['methods']['check_ownership']> = [tokenIds, contractAddress]

const isOwner = await nftRedPacketContract.methods.check_ownership(...checkParams).call({ from: account })
const isOwner = await nftRedPacketContract.read.check_ownership([tokenIds.map(BigInt), contractAddress], {
account: (account || undefined) as HexString | undefined,
})
if (!isOwner) return

// #endregion

const tx = await new ContractTransaction(nftRedPacketContract.options.address).fillAll(
nftRedPacketContract.methods.create_red_packet(...params),
{
from: account,
chainId,
...gasOption,
gas: addGasMargin(BigNumber.max(gasLimit, gasOption?.gas ?? 0), 0.3),
},
)
const tx = ContractTransaction.normalizeTransaction({
from: account,
chainId,
...gasOption,
gas: addGasMargin(BigNumber.max(String(gasLimit), gasOption?.gas ?? 0), 0.3),
to: nftRedPacketContract.address,
data: encodeFunctionData({
abi: NftRedPacketAbi,
functionName: 'create_red_packet',
args: params,
}),
})

const hash = await EVMWeb3.sendTransaction(tx, {
paymentToken: gasOption?.gasCurrency,
Expand All @@ -129,7 +136,7 @@ export function useCreateNftRedpacketCallback({
}
}
return { hash, receipt, events: undefined }
}, [duration, message, creator, contractAddress, tokenIds, account, chainId, gasOption, gasLimit])
}, [duration, message, creator, contractAddress, tokenIds, account, chainId, gasOption, gasLimit, params])

return { gasLimit, estimateGasFee, loading, createCallback }
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { useAvailabilityNftRedPacket } from './useAvailabilityNftRedPacket.js'
*/
export function useNftAvailabilityComputed(account: string, payload: NftRedPacketJSONPayload) {
const { chainId } = useChainContext<NetworkPluginID.PLUGIN_EVM>()
const { data: availability } = useAvailabilityNftRedPacket(payload?.rpid, account, chainId)
const { data: availability } = useAvailabilityNftRedPacket(
payload?.rpid as HexString | '',
account as HexString | '',
chainId,
)

if (!availability) {
return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ChainId, createContract, getNftRedPacketConstant, useNftRedPacketConstants } from '@masknet/web3-shared-evm'
import { ChainId, getNftRedPacketConstant, useNftRedPacketConstants } from '@masknet/web3-shared-evm'
import { NftRedPacketAbi, type NftRedPacket } from '@masknet/web3-contracts/types/NftRedPacket.js'
import { useContract } from '@masknet/web3-hooks-evm'
import { EVMWeb3 } from '@masknet/web3-providers'
import { getContract } from 'viem'

export function useNftRedPacketContract(chainId: ChainId) {
const { RED_PACKET_NFT_ADDRESS } = useNftRedPacketConstants(chainId)
Expand All @@ -10,5 +11,10 @@ export function useNftRedPacketContract(chainId: ChainId) {

export function createNftRedpacketContract(chainId: ChainId | undefined) {
const RED_PACKET_NFT_ADDRESS = getNftRedPacketConstant(chainId ?? ChainId.Mainnet, 'RED_PACKET_NFT_ADDRESS')
return createContract<NftRedPacket>(EVMWeb3.getWeb3({ chainId }), RED_PACKET_NFT_ADDRESS, NftRedPacketAbi)
if (!RED_PACKET_NFT_ADDRESS) return null
return getContract({
abi: NftRedPacketAbi,
client: EVMWeb3.getViem({ chainId }),
address: RED_PACKET_NFT_ADDRESS as HexString,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,11 @@ export function NftRedPacketConfirm() {
estimateGasFee,
createCallback,
} = useCreateNftRedpacketCallback({
publicKey: redpacketPubkey,
publicKey: redpacketPubkey as HexString,
duration,
message,
creator,
contractAddress: collection?.address ?? '',
contractAddress: collection?.address as HexString,
tokenIds,
gasOption,
})
Expand Down Expand Up @@ -240,7 +240,7 @@ export function NftRedPacketConfirm() {
nativeToken={nativeTokenDetailed}
nativeTokenPrice={nativeTokenPrice}
gasConfig={gasOption}
gasLimit={gasLimit ?? 0}
gasLimit={gasLimit}
onChange={setGasOption}
estimateGasFee={estimateGasFee}
editMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface SelectGasSettingsToolbarProps<T extends NetworkPluginID = Netwo
chainId?: Web3Helper.ChainIdAll
nativeToken: Web3Helper.FungibleTokenAll
nativeTokenPrice: number
gasLimit: number
gasLimit: number | bigint | null | undefined
gasConfig?: GasConfig
estimateGasFee?: string
editMode?: boolean
Expand Down Expand Up @@ -153,12 +153,12 @@ export function SelectGasSettingsToolbarUI({
{
maxFeePerGas,
maxPriorityFeePerGas,
gas: new BigNumber(gasLimit).toString(),
gas: new BigNumber(String(gasLimit ?? 0)).toString(),
gasOptionType: isCustomGas ? GasOptionType.CUSTOM : currentGasOptionType,
}
: {
gasPrice: new BigNumber(maxFeePerGas).gt(0) ? maxFeePerGas : gasPrice,
gas: new BigNumber(gasLimit).toString(),
gas: new BigNumber(String(gasLimit ?? 0)).toString(),
gasOptionType: isCustomGas ? GasOptionType.CUSTOM : currentGasOptionType,
},
),
Expand Down Expand Up @@ -250,7 +250,7 @@ export function SelectGasSettingsToolbarUI({

const gasFee = useMemo(() => {
if (!gasOption || !gasLimit) return ZERO
const result = GasEditor.fromConfig(chainId as ChainId, gasOption).getGasFee(gasLimit)
const result = GasEditor.fromConfig(chainId as ChainId, gasOption).getGasFee(String(gasLimit))
return result
}, [gasLimit, gasOption, nativeToken])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export class EVMConnectionReadonlyAPI
return this.Request.getWeb3(initial)
}

getViem(initial?: EVMConnectionOptions) {
return this.Request.getViem(initial)
}

getWeb3Provider(initial?: EVMConnectionOptions) {
return this.Request.getWeb3Provider(initial)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { EVMConnectionOptions } from '../types/index.js'
import { createWeb3FromURL } from '../../../helpers/createWeb3FromURL.js'
import { createWeb3ProviderFromURL } from '../../../helpers/createWeb3ProviderFromURL.js'
import type { ConnectionOptionsProvider } from '../../Base/apis/ConnectionOptions.js'
import { createViemClientFromURL } from '../../../helpers/createViemClient.js'

export class EVMRequestReadonlyAPI {
static Default = new EVMRequestReadonlyAPI()
Expand All @@ -32,6 +33,11 @@ export class EVMRequestReadonlyAPI {
return createWeb3FromURL(options.providerURL ?? ProviderURL.from(options.chainId))
}

getViem(initial?: EVMConnectionOptions) {
const options = this.ConnectionOptions.fill(initial)
return createViemClientFromURL(options.chainId, options.providerURL ?? ProviderURL.from(options.chainId))
}

getWeb3Provider(initial?: EVMConnectionOptions) {
const options = this.ConnectionOptions.fill(initial)
return createWeb3ProviderFromURL(options.providerURL ?? ProviderURL.from(options.chainId))
Expand Down
Loading
Loading