Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.
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
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,15 @@
"react-dom": "^18.2.0",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
"typescript": "^5.8.3"
},
"dependencies": {
"@poolzfinance/strapi": "file:../InterfaceStrapi",
"@tanstack/react-query": "^5.80.10",
"@wagmi/core": "^2.17.3",
"bignumber.js": "^9.1.1",
"viem": "~2.31.3",
"wagmi": "^2.15.6",
"web3": "^1.10.0",
"web3-eth-contract": "^1.10.0",
"web3-types": "^1.10.0",
Expand Down
2,921 changes: 2,872 additions & 49 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions src/components/Context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createContext } from "react"
import { IThePoolzContextInterface } from "../types/IThePoolzInterface"
import { createContext, useContext } from "react"

const ThePoolzContext = createContext<IThePoolzContextInterface>(null as any)
const ThePoolzContext = createContext<any>(null as any)

export const PoolzAppContext = createContext<{ chains: any[] }>({ chains: [] })
export const usePoolzApp = () => useContext(PoolzAppContext)

export default ThePoolzContext
69 changes: 39 additions & 30 deletions src/components/Provider.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,45 @@
import React from "react"
import Web3 from "web3"
import ThePoolzContext from "./Context"
import ThePoolz from "../poolz/ThePoolz"
import { TChainConfig } from "../types/IThePoolzInterface"

const ThePoolzProvider = ({ children, overrides }: { children: React.ReactNode, overrides?: TChainConfig }) => {
const [thePoolzInstance, setThePoolzInstance] = React.useState(new ThePoolz(Web3.givenProvider))
const [provider, setProvider] = React.useState(Web3.givenProvider)

const contextValue = React.useMemo(() => ({ thePoolz: thePoolzInstance, setProvider }), [thePoolzInstance, setProvider])

React.useEffect(() => {
if (!provider) return

const init = async () => {
const instance = new ThePoolz(provider, overrides)
await instance.init()
setThePoolzInstance(instance)
import React, { useMemo } from "react"
import { WagmiProvider, createConfig, http } from "wagmi"
import { QueryClientProvider } from "@tanstack/react-query"
import { useChains } from "@poolzfinance/strapi"
import { mainnet } from "viem/chains"
import { queryClient } from "../utils/query-client"
import { PoolzAppContext } from "./Context"
import { WALLET_CONNECT_CONFIG } from "../constants/wagmi"
import { coinbaseWallet, injected, walletConnect } from "wagmi/connectors"
import { validateAndMapChains } from "../utils/chain-mapper"

const Provider = ({ children }: { children: React.ReactNode }) => {
const { data: chainsData } = useChains()

const chains = useMemo(() => {
if (!chainsData) return []
try {
return validateAndMapChains(chainsData)
} catch {
return []
}
init().catch(console.error)
provider
.on("accountsChanged", init)
.on("chainChanged", init)


}, [provider, setThePoolzInstance]) // eslint-disable-line react-hooks/exhaustive-deps
}, [chainsData])

const chainsForConfig = (chains.length ? chains : [mainnet]) as [typeof mainnet, ...typeof chains]

const wagmiConfig = useMemo(
() =>
createConfig({
chains: chainsForConfig,
connectors: [injected(), walletConnect(WALLET_CONNECT_CONFIG), coinbaseWallet({ appName: "Poolz" })],
transports: Object.fromEntries(chainsForConfig.map((c) => [c.id, http()]))
}),
[chainsForConfig]
)

return (
<ThePoolzContext.Provider value={contextValue}>
{children}
</ThePoolzContext.Provider>
<PoolzAppContext.Provider value={{ chains }}>
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</WagmiProvider>
</PoolzAppContext.Provider>
)
}

export default ThePoolzProvider
export default Provider
14 changes: 14 additions & 0 deletions src/components/ThePoolzProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react"
import StrapiProvider from "@poolzfinance/strapi"
import Provider from "./Provider"
import { TChainConfig } from "../types/IThePoolzInterface"

const ThePoolzProvider = ({ children, overrides }: { children: React.ReactNode; overrides?: TChainConfig }) => {
return (
<StrapiProvider>
<Provider overrides={overrides}>{children}</Provider>
</StrapiProvider>
)
}

export default ThePoolzProvider
8 changes: 8 additions & 0 deletions src/constants/wagmi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const WALLET_CONNECT_CONFIG = {
projectId: "1234",
appName: "Poolz",
appLogoUrl: "https://www.poolz.finance/assets/LogoDark-3da5a4ae.svg",
appUrl: "https://www.poolz.finance",
appDescription:
"Poolz is a decentralized cross-chain IDO platform built on top of Web 3.0 infrastructure to enable crypto projects to raise funds before listing.",
} as const
67 changes: 16 additions & 51 deletions src/hooks/useConnectWallet.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,21 @@
import { useMemo } from "react"
import { useThePoolz, useSetProvider } from "./useThePoolz"
import { TGivenProvider } from "../types/TConnectWallet"

const initionalState = {
isMultipleWallets: false,
isMetaMask: false,
isCoinbaseWallet: false,
isTrustWallet: false,
connectMetamask: async () => window.open(`https://metamask.app.link/dapp/${window.location.host}`, "_blank", "noreferrer noopener"),
connectCoinbaseWallet: async () => window.open(`https://www.coinbase.com/wallet`, "_blank", "noreferrer noopener"),
connectTrustWallet: async () => window.open(`https://trustwallet.com/download`, "_blank", "noreferrer noopener")
}
import { useConnect, useAccount } from "wagmi"

export const useConnectWallet = () => {
const setProvider = useSetProvider()
const thePoolz = useThePoolz()
const { web3 } = thePoolz

return useMemo(() => {
const { isMetaMask, isCoinbaseWallet, isTrustWallet, providers, request } = (web3.givenProvider || {
isMetaMask: false,
isCoinbaseWallet: false,
isTrustWallet: false,
providers: [],
request: Promise.resolve
}) as TGivenProvider

if (Array.isArray(providers) && providers.length) {
initionalState.isMultipleWallets = true
for (const provider of providers) {
const connect = async () => {
setProvider(provider)
return provider.request({ method: "eth_requestAccounts" })
}
if (provider.isMetaMask) {
initionalState.isMetaMask = true
initionalState.connectMetamask = connect
continue
}
if (provider.isCoinbaseWallet) {
initionalState.isCoinbaseWallet = true
initionalState.connectCoinbaseWallet = connect
}
}
return initionalState
}
const connect = async () => await request({ method: "eth_requestAccounts" })
const { connect, connectors, isPending } = useConnect()
const { isConnected, address } = useAccount()

if (isMetaMask) initionalState.connectMetamask = connect
if (isCoinbaseWallet) initionalState.connectCoinbaseWallet = connect
if (isTrustWallet) initionalState.connectTrustWallet = connect
const metamaskConnector = connectors.find((c) => c.name.toLowerCase().includes("meta"))
const coinbaseConnector = connectors.find((c) => c.name.toLowerCase().includes("coinbase"))
const walletConnectConnector = connectors.find((c) => c.name.toLowerCase().includes("walletconnect"))

return { ...initionalState, isMetaMask, isCoinbaseWallet, isTrustWallet }
}, [web3, setProvider])
return {
isConnected,
address,
isPending,
connectMetamask: metamaskConnector ? () => connect({ connector: metamaskConnector }) : undefined,
connectCoinbaseWallet: coinbaseConnector ? () => connect({ connector: coinbaseConnector }) : undefined,
connectWalletConnect: walletConnectConnector ? () => connect({ connector: walletConnectConnector }) : undefined,
connectors,
connect
}
}
39 changes: 39 additions & 0 deletions src/hooks/useWagmiConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { createConfig, http, type Config } from "wagmi"
import { coinbaseWallet, injected, walletConnect } from "wagmi/connectors"
import type { Chain } from "viem/chains"
import { WALLET_CONNECT_CONFIG } from "../constants/wagmi"

export function createWagmiConfig(chains: Chain[]): Config {
if (chains.length === 0) {
throw new Error("No chains provided")
}

const supportedChains = chains as [Chain, ...Chain[]]

return createConfig({
chains: supportedChains,
connectors: [
injected(),
coinbaseWallet({
appName: WALLET_CONNECT_CONFIG.appName,
appLogoUrl: WALLET_CONNECT_CONFIG.appLogoUrl
}),
walletConnect({
projectId: WALLET_CONNECT_CONFIG.projectId,
metadata: {
name: WALLET_CONNECT_CONFIG.appName,
description: WALLET_CONNECT_CONFIG.appDescription,
url: WALLET_CONNECT_CONFIG.appUrl,
icons: [WALLET_CONNECT_CONFIG.appLogoUrl]
}
})
],
transports: supportedChains.reduce((acc, chain) => {
const rpcUrl = chain.rpcUrls.default.http[0]
if (rpcUrl) {
acc[chain.id] = http(rpcUrl)
}
return acc
}, {} as Record<number, ReturnType<typeof http>>)
})
}
15 changes: 4 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import ThePoolzProvider from "./components/Provider"
import { useThePoolz, useSetProvider } from "./hooks/useThePoolz"
import { useConnectWallet } from "./hooks/useConnectWallet"
import { useTheSiwe } from "./hooks/useTheSiwe"
import { useSidNameForAddress } from "./hooks/useSid"
import { useSyncProviders } from "./hooks/useSyncProviders"
export { CUSTOMER_ACCOUNT_VARIABLE, DEFAULT_CHAIN_ID } from "./constants"
export { WALLET_CONNECT_CONFIG } from "./constants/wagmi"

export { ThePoolzProvider, useThePoolz, useSetProvider, useConnectWallet, useSidNameForAddress, useTheSiwe, useSyncProviders }
export type { IThePoolzInterface, IERC20Info, IChainConfig, TChainConfig } from "./types/IThePoolzInterface"
export * from "./utils"
export * from "./constants"
export type { Contract } from "web3-eth-contract"
export { validateAndMapChains } from "./utils/chain-mapper"
export { queryClient } from "./utils/query-client"
23 changes: 23 additions & 0 deletions src/types/chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type React from "react"
import { TChainConfig } from "./IThePoolzInterface"

export interface ApiChain {
chainId: number
name: string
symbol: string
isTest: boolean
contracts_on_chain?: {
Decimals?: number
RPC?: string
Explorer?: string
}
}

export interface ChainsResponse {
chains: ApiChain[]
}

export interface ProviderProps {
children: React.ReactNode
overrides?: TChainConfig
}
46 changes: 46 additions & 0 deletions src/utils/chain-mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Chain } from "viem/chains"
import type { ApiChain } from "../types/chain"

export function mapApiChainToViemChain(apiChain: ApiChain): Chain {
if (!apiChain.chainId || !apiChain.name) {
throw new Error(`Invalid chain data: missing chainId or name`)
}

const rpcUrl = apiChain.contracts_on_chain?.RPC ?? ""

return {
id: apiChain.chainId,
name: apiChain.name,
nativeCurrency: {
name: apiChain.name,
symbol: apiChain.symbol || "ETH",
decimals: apiChain.contracts_on_chain?.Decimals || 18,
},
rpcUrls: {
default: { http: [rpcUrl] },
},
blockExplorers: apiChain.contracts_on_chain?.Explorer
? {
default: {
name: `${apiChain.name} Explorer`,
url: apiChain.contracts_on_chain.Explorer,
},
}
: undefined,
testnet: apiChain.isTest,
}
}

export function validateAndMapChains(chainsData: unknown): Chain[] {
if (!chainsData || typeof chainsData !== "object") {
throw new Error("Invalid chains data received")
}

const data = chainsData as { chains?: ApiChain[] }

if (!Array.isArray(data.chains) || data.chains.length === 0) {
throw new Error("No valid chains found")
}

return data.chains.map(mapApiChainToViemChain)
}
3 changes: 3 additions & 0 deletions src/utils/query-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { QueryClient } from "@tanstack/react-query";

export const queryClient = new QueryClient()
Loading