Skip to content
Closed
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
8 changes: 8 additions & 0 deletions .changeset/six-zebras-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"thirdweb": minor
---

Add Glyph wallet connector to `createWallet`, export the connector and also export new chains:

- `apechain` (mainnet)
- `curtis` (testnet)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
import {
abstract,
apechain,
arbitrum,
arbitrumSepolia,
base,
Expand Down Expand Up @@ -126,6 +127,7 @@ export function RightSection(props: {
optimism,
arbitrum,
abstract,
apechain,
sepolia,
baseSepolia,
optimismSepolia,
Expand Down Expand Up @@ -185,7 +187,7 @@ export function RightSection(props: {
// TODO: should show the expanded connected modal here instead
connectButton
) : (
<div className="relative overflow-hidden">
<div className="overflow-hidden relative">
<ConnectEmbed
accountAbstraction={
connectOptions.enableAccountAbstraction
Expand Down Expand Up @@ -214,7 +216,7 @@ export function RightSection(props: {
/>
{/* Fake X icon to make it looks exactly like a modal */}
<XIcon
className="absolute top-6 right-6 size-6 cursor-not-allowed"
className="absolute top-6 right-6 cursor-not-allowed size-6"
style={{
color: themeObj.colors.secondaryIconColor,
}}
Expand Down Expand Up @@ -283,7 +285,7 @@ function TabButtons(props: {
}) {
return (
<div>
<div className="flex justify-start gap-1 rounded-lg border bg-card p-1 md:inline-flex">
<div className="flex gap-1 justify-start p-1 rounded-lg border bg-card md:inline-flex">
{props.tabs.map((tab) => (
<Button
className={cn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useTheme } from "next-themes";
import {
abstract,
apechain,
arbitrum,
arbitrumSepolia,
base,
Expand Down Expand Up @@ -33,6 +34,7 @@ export function StyledConnectButton(
polygonAmoy,
arbitrumSepolia,
abstract,
apechain,
base,
ethereum,
polygon,
Expand Down
2 changes: 2 additions & 0 deletions apps/playground-web/src/components/styled-connect-embed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useTheme } from "next-themes";
import {
abstract,
apechain,
arbitrum,
arbitrumSepolia,
base,
Expand Down Expand Up @@ -47,6 +48,7 @@ export function StyledConnectEmbed(
polygonAmoy,
arbitrumSepolia,
abstract,
apechain,
]}
client={THIRDWEB_CLIENT}
className="!max-w-full"
Expand Down
2 changes: 2 additions & 0 deletions packages/thirdweb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@noble/curves": "1.8.2",
"@noble/hashes": "1.7.2",
"@passwordless-id/webauthn": "^2.1.2",
"@privy-io/cross-app-connect": "^0.2.3",
"@radix-ui/react-dialog": "1.1.14",
"@radix-ui/react-focus-scope": "1.1.7",
"@radix-ui/react-icons": "1.3.2",
Expand All @@ -25,6 +26,7 @@
"@tanstack/react-query": "5.81.5",
"@thirdweb-dev/engine": "workspace:*",
"@thirdweb-dev/insight": "workspace:*",
"@wagmi/core": "^2.17.2",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah these dependencies cannot be here. Needs to be its own package and users will install both your package and thirdweb together. Check how we do it for abstract

"@walletconnect/sign-client": "2.20.1",
"@walletconnect/universal-provider": "2.21.4",
"abitype": "1.0.8",
Expand Down
20 changes: 20 additions & 0 deletions packages/thirdweb/src/chains/chain-definitions/apechain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineChain } from "../utils.js";

/**
* @chain
*/
export const apechain = /* @__PURE__ */ defineChain({
blockExplorers: [
{
name: "Apescan",
url: "https://apescan.io",
},
],
id: 33139,
name: "Ape Chain",
nativeCurrency: {
name: "ApeCoin",
symbol: "APE",
decimals: 18,
},
});
18 changes: 18 additions & 0 deletions packages/thirdweb/src/chains/chain-definitions/curtis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineChain } from "../utils.js";

/**
* @chain
* Curtis test network (Ape Chain testnet variant).
*/
export const curtis = /* @__PURE__ */ defineChain({
blockExplorers: [
{
name: "Curtis Explorer",
url: "https://explorer.curtis.apechain.com",
},
],
id: 33_111,
name: "Curtis",
nativeCurrency: { name: "ApeCoin", symbol: "APE", decimals: 18 },
testnet: true,
});
2 changes: 2 additions & 0 deletions packages/thirdweb/src/exports/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

export { abstract } from "../chains/chain-definitions/abstract.js";
export { abstractTestnet } from "../chains/chain-definitions/abstract-testnet.js";
export { apechain } from "../chains/chain-definitions/apechain.js";
export { curtis } from "../chains/chain-definitions/curtis.js";

/**
* PRE_DEFINED CHAINS
Expand Down
4 changes: 4 additions & 0 deletions packages/thirdweb/src/exports/wallets/glyph.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export {
glyphWalletTW,
glyphWalletWagmiConnector,
} from "../../wallets/glyph/glyph-wallet.js";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm these should be in their own package, not directly baked into the thirdweb package. Same thing we do with abstract global wallet.

9 changes: 9 additions & 0 deletions packages/thirdweb/src/wallets/create-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { coinbaseWalletSDK } from "./coinbase/coinbase-wallet.js";
import { getCoinbaseWebProvider } from "./coinbase/coinbase-web.js";
import { COINBASE } from "./constants.js";
import { isEcosystemWallet } from "./ecosystem/is-ecosystem-wallet.js";
import { glyphWalletTW } from "./glyph/glyph-wallet.js";
import { ecosystemWallet } from "./in-app/web/ecosystem.js";
import { inAppWallet } from "./in-app/web/in-app.js";
import { getInjectedProvider } from "./injected/index.js";
Expand Down Expand Up @@ -185,6 +186,14 @@ export function createWallet<const ID extends WalletId>(
providerFactory: () => getCoinbaseWebProvider(options),
}) as Wallet<ID>;
}

/**
* GLYPH WALLET
*/
case id === "io.useglyph": {
return glyphWalletTW() as Wallet<ID>;
}

/**
* WALLET CONNECT AND INJECTED WALLETS + walletConnect standalone
*/
Expand Down
15 changes: 15 additions & 0 deletions packages/thirdweb/src/wallets/glyph/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** Staging tenant id for Glyph Cross-App Connect. @internal */
export const STAGING_GLYPH_APP_ID = "clxt9p8e601al6tgmsyhu7j3t";
/** Production tenant id for Glyph Cross-App Connect. @internal */
export const GLYPH_APP_ID = "cly38x0w10ac945q9yg9sm71i";
/** Icon used in connectors & UIs. @internal */
export const GLYPH_ICON_URL = "https://i.ibb.co/TxcwPQyr/Group-12489-1.png";

export const glyphConnectorDetails = {
id: "io.useglyph.privy",
name: "Glyph",
iconUrl: GLYPH_ICON_URL,
iconBackground: "#ffffff",
shortName: "Glyph",
type: "injected",
} as const;
123 changes: 123 additions & 0 deletions packages/thirdweb/src/wallets/glyph/glyph-wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { toPrivyWalletConnector } from "@privy-io/cross-app-connect/rainbow-kit";
import type { CreateConnectorFn } from "@wagmi/core";
import { createEmitter } from "@wagmi/core/internal";
import type { Chain, EIP1193Provider } from "viem";
import {
abstract,
apeChain,
arbitrum,
arbitrumSepolia,
base,
baseSepolia,
curtis,
mainnet,
optimism,
optimismSepolia,
polygon,
sepolia,
} from "viem/chains";
import { fromProvider } from "../../adapters/eip1193/from-eip1193.js";
import {
GLYPH_APP_ID,
glyphConnectorDetails,
STAGING_GLYPH_APP_ID,
} from "../../wallets/glyph/constants.js";
import type { Wallet } from "../../wallets/interfaces/wallet.js";

/**
* Create a wagmi connector for the Glyph Global Wallet.
*
* Adapted from wagmi injected connector as a reference implementation:
* https://github.com/wevm/wagmi/blob/main/packages/core/src/connectors/injected.ts#L94
*
* @example
* import { createConfig, http } from "wagmi";
* import { apeChain } from "wagmi/chains";
* import { glyphWalletWagmiConnector } from "thirdweb/wallets/glyph"
*
* export const wagmiConfig = createConfig({
* chains: [apeChain],
* transports: {
* [apeChain.id]: http(),
* },
* connectors: [glyphWalletWagmiConnector()],
* ssr: true,
* });
*/
function glyphWalletWagmiConnector(options?: {
useStagingTenant?: boolean;
}): CreateConnectorFn {
const { useStagingTenant } = options ?? {};

return (params) => {
const connector = toPrivyWalletConnector({
iconUrl: glyphConnectorDetails.iconUrl,
id: useStagingTenant ? STAGING_GLYPH_APP_ID : GLYPH_APP_ID,
name: glyphConnectorDetails.name,
})(params);

const getGlyphProvider = async (
parameters?: { chainId?: number | undefined } | undefined,
) => {
const chainId =
parameters?.chainId ?? params.chains?.[0]?.id ?? apeChain.id;

const provider = await connector.getProvider({
chainId,
});

return provider;
};

const glyphConnector = {
...connector,
getProvider: getGlyphProvider,
type: glyphConnectorDetails.type,
id: glyphConnectorDetails.id,
};
return glyphConnector;
};
}

/**
* Create a thirdweb wallet for Glyph Global Wallet
*
* @returns A wallet instance wrapping Glyph Global Wallet to be used with the thirdweb Connect SDK
*
* @example
* ```tsx
* import { createThirdwebClient } from "thirdweb";
* import { glyphWalletTW } from "thirdweb/wallets/glyph"
*
* const client = createThirdwebClient({ clientId });
*
* <ConnectButton client={client} wallets=[glyphWalletTW()]>
* ```
*/
function glyphWalletTW(chains?: [Chain, ...Chain[]]): Wallet {
const connector = glyphWalletWagmiConnector()({
chains: chains ?? [
apeChain,
curtis,
mainnet,
base,
arbitrum,
polygon,
optimism,
abstract,
sepolia,
baseSepolia,
optimismSepolia,
arbitrumSepolia,
],
emitter: createEmitter("io.useglyph"),
});
return fromProvider({
provider: connector.getProvider as (
parameters?: { chainId?: number | undefined } | undefined,
) => Promise<EIP1193Provider>,
walletId: "io.useglyph",
});
}

export { glyphWalletTW, glyphWalletWagmiConnector };
9 changes: 9 additions & 0 deletions packages/thirdweb/src/wallets/native/create-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getCoinbaseMobileProvider } from "../coinbase/coinbase-mobile.js";
import { coinbaseWalletSDK } from "../coinbase/coinbase-wallet.js";
import { COINBASE } from "../constants.js";
import { isEcosystemWallet } from "../ecosystem/is-ecosystem-wallet.js";
import { glyphWalletTW } from "../glyph/glyph-wallet.js";
import { ecosystemWallet } from "../in-app/native/ecosystem.js";
import { inAppWallet } from "../in-app/native/in-app.js";
import type { Account, Wallet } from "../interfaces/wallet.js";
Expand All @@ -23,6 +24,7 @@ import type {
WalletId,
} from "../wallet-types.js";


/**
* Creates a wallet based on the provided ID and arguments.
* @param args - The arguments for creating the wallet.
Expand Down Expand Up @@ -85,6 +87,13 @@ export function createWallet<const ID extends WalletId>(
}) as Wallet<ID>;
}

/**
* GLYPH WALLET
*/
case id === "io.useglyph": {
return glyphWalletTW() as Wallet<ID>;
}

/**
* WALLET CONNECT only in react native for everything else
*/
Expand Down
Loading