-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from babylonlabs-io/293-bwc-implement-widget-api
feat: widget API
- Loading branch information
Showing
38 changed files
with
853 additions
and
264 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { createContext, PropsWithChildren, useEffect, useState, useCallback, useContext } from "react"; | ||
import { useAppState } from "@/state/state"; | ||
import { WalletConnector } from "@/core/WalletConnector"; | ||
import type { NetworkConfig } from "@/core/types"; | ||
|
||
import metadata from "@/core/wallets"; | ||
import { BTCProvider } from "@/core/wallets/btc/BTCProvider"; | ||
import { BBNProvider } from "@/core/wallets/bbn/BBNProvider"; | ||
|
||
interface ProviderProps { | ||
context: any; | ||
config: NetworkConfig; | ||
} | ||
|
||
export interface Connectors { | ||
BTC: WalletConnector<"BTC", BTCProvider> | null; | ||
BBN: WalletConnector<"BBN", BBNProvider> | null; | ||
} | ||
|
||
export type SupportedChains = keyof Connectors; | ||
|
||
const defaultState: Connectors = { | ||
BTC: null, | ||
BBN: null, | ||
}; | ||
|
||
const Context = createContext<Connectors>(defaultState); | ||
|
||
export function ChainProvider({ children, context, config }: PropsWithChildren<ProviderProps>) { | ||
const [connectors, setConnectors] = useState(defaultState); | ||
const { addChain, displayLoader, displayTermsOfService } = useAppState(); | ||
|
||
const init = useCallback(async () => { | ||
displayLoader?.(); | ||
|
||
const metadataArr = Object.values(metadata); | ||
const connectorArr = await Promise.all(metadataArr.map((data) => WalletConnector.create(data, context, config))); | ||
|
||
return connectorArr.reduce((acc, connector) => ({ ...acc, [connector.id]: connector }), {} as Connectors); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (!displayLoader || !addChain || !setConnectors || !displayTermsOfService) return; | ||
|
||
displayLoader(); | ||
|
||
init().then((connectors) => { | ||
setConnectors(connectors); | ||
|
||
Object.values(connectors).forEach((connector) => { | ||
addChain(connector); | ||
}); | ||
|
||
displayTermsOfService(); | ||
}); | ||
}, [displayLoader, addChain, setConnectors, init, displayTermsOfService]); | ||
|
||
return <Context.Provider value={connectors}>{children}</Context.Provider>; | ||
} | ||
|
||
export const useChainProviders = () => { | ||
return useContext(Context); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { createContext, PropsWithChildren, useContext, useMemo } from "react"; | ||
|
||
import { usePersistState } from "@/hooks/usePersistState"; | ||
|
||
interface InscriptionContext { | ||
lockInscriptions: boolean; | ||
showAgain: boolean; | ||
toggleLockInscriptions?: (value: boolean) => void; | ||
toggleShowAgain?: (value: boolean) => void; | ||
} | ||
|
||
const Context = createContext<InscriptionContext>({ lockInscriptions: true, showAgain: true }); | ||
|
||
export function InscriptionProvider({ children, context }: PropsWithChildren<{ context: any }>) { | ||
const [showAgain, toggleShowAgain] = usePersistState("bwc-inscription-modal-show-again", context.localStorage, true); | ||
const [lockInscriptions, toggleLockInscriptions] = usePersistState( | ||
"bwc-inscription-modal-lock", | ||
context.localStorage, | ||
true, | ||
); | ||
|
||
const inscriptionContext = useMemo( | ||
() => ({ | ||
showAgain, | ||
lockInscriptions, | ||
toggleLockInscriptions, | ||
toggleShowAgain, | ||
}), | ||
[showAgain, lockInscriptions, toggleLockInscriptions, toggleShowAgain], | ||
); | ||
|
||
return <Context.Provider value={inscriptionContext}>{children}</Context.Provider>; | ||
} | ||
|
||
export const useInscriptionProvider = () => useContext(Context); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,51 @@ | ||
import { Wallet } from "@/core/Wallet"; | ||
import type { NetworkConfig, IProvider, IChain, ConnectMetadata } from "@/core/types"; | ||
import type { NetworkConfig, IProvider, IChain, ChainMetadata } from "@/core/types"; | ||
|
||
export class WalletConnector<P extends IProvider> implements IChain { | ||
connectedWallet: Wallet<P> | null = null; | ||
export class WalletConnector<N extends string, P extends IProvider> implements IChain { | ||
private _connectedWallet: Wallet<P> | null = null; | ||
|
||
static async create<P extends IProvider>( | ||
metadata: ConnectMetadata<P>, | ||
config: NetworkConfig, | ||
static async create<N extends string, P extends IProvider>( | ||
metadata: ChainMetadata<N, P>, | ||
context: any, | ||
): Promise<WalletConnector<P>> { | ||
config: NetworkConfig, | ||
): Promise<WalletConnector<N, P>> { | ||
const wallets: Wallet<P>[] = []; | ||
|
||
for (const walletMetadata of metadata.wallets) { | ||
wallets.push(await Wallet.create(walletMetadata, context, config)); | ||
} | ||
|
||
return new WalletConnector(metadata.chain, metadata.icon, wallets); | ||
return new WalletConnector(metadata.chain, metadata.name, metadata.icon, wallets); | ||
} | ||
|
||
constructor( | ||
public readonly chain: string, | ||
public readonly id: N, | ||
public readonly name: string, | ||
public readonly icon: string, | ||
public readonly wallets: Wallet<P>[], | ||
) {} | ||
|
||
async connect(name: string) { | ||
const wallet = this.wallets.find((wallet) => wallet.name.toLowerCase() === name.toLowerCase()); | ||
get connectedWallet() { | ||
return this._connectedWallet; | ||
} | ||
|
||
async connect(walletId: string) { | ||
const wallet = this.wallets.find((wallet) => wallet.id === walletId); | ||
|
||
if (!wallet) { | ||
throw new Error("Wallet not found"); | ||
} | ||
|
||
this.connectedWallet = (await wallet?.connect()) ?? null; | ||
this._connectedWallet = await wallet.connect(); | ||
|
||
return this.connectedWallet; | ||
} | ||
|
||
disconnect() { | ||
this._connectedWallet = null; | ||
} | ||
|
||
clone() { | ||
return new WalletConnector(this.id, this.name, this.icon, this.wallets); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { IProvider } from "@/core/types"; | ||
|
||
export abstract class BBNProvider implements IProvider { | ||
async connectWallet() { | ||
return this; | ||
} | ||
|
||
abstract getAddress(): Promise<string>; | ||
|
||
abstract getPublicKeyHex(): Promise<string>; | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { BBNProvider } from "./BBNProvider"; | ||
import icon from "./babylon.jpeg"; | ||
|
||
import { ChainMetadata } from "@/core/types"; | ||
|
||
const metadata: ChainMetadata<"BBN", BBNProvider> = { | ||
chain: "BBN", | ||
name: "Babylon Chain", | ||
icon, | ||
wallets: [], | ||
}; | ||
|
||
export default metadata; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import btc from "./btc"; | ||
import bbn from "./bbn"; | ||
|
||
export default { btc, bbn } as const; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* eslint-disable @typescript-eslint/no-empty-object-type */ | ||
import { ComponentType, memo, useMemo } from "react"; | ||
import { useAppState } from "@/state/state"; | ||
import type { Actions, State } from "@/state/state.d"; | ||
|
||
export const withAppState = | ||
<OP, IP = {}, P = {}>(stateMapper: (state: State & Actions) => IP) => | ||
(Component: ComponentType<P>) => { | ||
const Container = (props: OP) => { | ||
const appState = useAppState(); | ||
const outerProps = useMemo(() => stateMapper(appState), [appState, stateMapper]); | ||
const PureComponent = memo(Component); | ||
|
||
return <PureComponent {...(props as any)} {...outerProps} />; | ||
}; | ||
|
||
return Container; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { type SupportedChains, useChainProviders } from "@/context/Chain.context"; | ||
|
||
export function useChainConnector<K extends SupportedChains>(chainId: K) { | ||
const connectors = useChainProviders(); | ||
|
||
return connectors?.[chainId] ?? null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
"use client"; | ||
|
||
import { type SetStateAction, type Dispatch, useState, useEffect } from "react"; | ||
|
||
export function usePersistState<S>(key: string, storage: Storage, initialState?: S): [S, Dispatch<SetStateAction<S>>] { | ||
function getDefaultState() { | ||
const defaultValue = typeof initialState === "function" ? (initialState as () => S)() : initialState; | ||
const persistValue = storage.getItem(key); | ||
const defaultState = persistValue ? (JSON.parse(persistValue) as S) : null; | ||
|
||
return (defaultState ?? defaultValue) as S; | ||
} | ||
|
||
const [state, setState] = useState<S>(getDefaultState); | ||
|
||
useEffect( | ||
function updateLocalStorage() { | ||
storage.setItem(key, JSON.stringify(state ?? "")); | ||
}, | ||
[key, storage, state], | ||
); | ||
|
||
return [state, setState]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,33 @@ | ||
import type { IChain, IWalllet } from "@/core/types"; | ||
|
||
type Step = "loading" | "acceptTermsOfService" | "selectChain" | "selectWallet" | "lockInscriptions"; | ||
type Screen<T extends string = string> = { | ||
type: T; | ||
params?: Record<string, string | number>; | ||
}; | ||
|
||
type Screens = | ||
| Screen<"LOADER"> | ||
| Screen<"TERMS_OF_SERVICE"> | ||
| Screen<"CHAINS"> | ||
| Screen<"WALLETS"> | ||
| Screen<"INSCRIPTIONS">; | ||
|
||
export interface State { | ||
visible: boolean; | ||
loading: boolean; | ||
step: Step; | ||
screen: Screens; | ||
selectedWallets: Record<string, IWalllet>; | ||
visibleWallets: string; | ||
chains: Record<string, IChain>; | ||
displayTermsOfService?: () => void; | ||
} | ||
|
||
export interface Actions { | ||
open?: () => void; | ||
close?: () => void; | ||
displayLoader?: () => void; | ||
displayChains?: () => void; | ||
displayWallets?: (chain: string) => void; | ||
displayInscriptions?: () => void; | ||
displayTermsOfService?: () => void; | ||
selectWallet?: (chain: string, wallet: IWalllet) => void; | ||
removeWallet?: (chain: string) => void; | ||
addChain?: (chain: IChain) => void; | ||
setLoading?: (value: boolean) => void; | ||
open?: () => void; | ||
close?: () => void; | ||
} |
Oops, something went wrong.