|
1 |
| -import { Show, createEffect, createSignal } from "solid-js"; |
| 1 | +import log from "loglevel"; |
| 2 | +import { IoClose } from "solid-icons/io"; |
| 3 | +import { |
| 4 | + Accessor, |
| 5 | + For, |
| 6 | + Setter, |
| 7 | + Show, |
| 8 | + createEffect, |
| 9 | + createMemo, |
| 10 | + createSignal, |
| 11 | +} from "solid-js"; |
2 | 12 |
|
3 | 13 | import { useCreateContext } from "../context/Create";
|
4 | 14 | import { useGlobalContext } from "../context/Global";
|
5 |
| -import { useWeb3Signer } from "../context/Web3"; |
| 15 | +import { EIP6963ProviderInfo, useWeb3Signer } from "../context/Web3"; |
| 16 | +import "../style/web3.scss"; |
| 17 | +import { formatError } from "../utils/errors"; |
6 | 18 |
|
7 |
| -const ConnectMetamask = ({ showAddress }) => { |
8 |
| - const [address, setAddress] = createSignal<string | undefined>(); |
9 |
| - const [buttonText, setButtonText] = createSignal<string | undefined>(); |
| 19 | +const connect = async ( |
| 20 | + notify: (type: string, message: string) => void, |
| 21 | + connectProvider: (rdns: string) => Promise<void>, |
| 22 | + provider: EIP6963ProviderInfo, |
| 23 | +) => { |
| 24 | + try { |
| 25 | + await connectProvider(provider.rdns); |
| 26 | + } catch (e) { |
| 27 | + log.error( |
| 28 | + `Provider connect to ${provider.rdns} failed: ${formatError(e)}`, |
| 29 | + ); |
| 30 | + notify("error", `Wallet connection failed: ${formatError(e)}`); |
| 31 | + } |
| 32 | +}; |
10 | 33 |
|
11 |
| - const { t } = useGlobalContext(); |
12 |
| - const { setAddressValid, setOnchainAddress } = useCreateContext(); |
| 34 | +const Modal = ({ |
| 35 | + show, |
| 36 | + setShow, |
| 37 | +}: { |
| 38 | + show: Accessor<boolean>; |
| 39 | + setShow: Setter<boolean>; |
| 40 | +}) => { |
| 41 | + const { t, notify } = useGlobalContext(); |
| 42 | + const { providers, connectProvider } = useWeb3Signer(); |
13 | 43 |
|
14 |
| - const setButtonTextAddress = () => { |
15 |
| - setButtonText(address() || t("connect_to_address")); |
| 44 | + const Provider = ({ provider }: { provider: EIP6963ProviderInfo }) => { |
| 45 | + return ( |
| 46 | + <div |
| 47 | + class="provider-modal-entry-wrapper" |
| 48 | + onClick={() => connect(notify, connectProvider, provider)}> |
| 49 | + <hr /> |
| 50 | + <div class="provider-modal-entry"> |
| 51 | + <img |
| 52 | + class="provider-modal-icon" |
| 53 | + src={provider.icon} |
| 54 | + alt={`${provider.name} icon`} |
| 55 | + /> |
| 56 | + <h4>{provider.name}</h4> |
| 57 | + </div> |
| 58 | + </div> |
| 59 | + ); |
16 | 60 | };
|
17 | 61 |
|
18 |
| - createEffect(() => { |
19 |
| - setButtonTextAddress(); |
20 |
| - }); |
| 62 | + return ( |
| 63 | + <div |
| 64 | + id="settings-menu" |
| 65 | + class="frame assets-select" |
| 66 | + onClick={() => setShow(false)} |
| 67 | + style={show() ? "display: block;" : "display: none;"}> |
| 68 | + <div onClick={(e) => e.stopPropagation()}> |
| 69 | + <h2>{t("select_wallet")}</h2> |
| 70 | + <span class="close" onClick={() => setShow(false)}> |
| 71 | + <IoClose /> |
| 72 | + </span> |
| 73 | + <hr class="spacer" /> |
| 74 | + <For |
| 75 | + each={Object.values(providers()).sort((a, b) => |
| 76 | + a.info.name |
| 77 | + .toLowerCase() |
| 78 | + .localeCompare(b.info.name.toLowerCase()), |
| 79 | + )}> |
| 80 | + {(item) => <Provider provider={item.info} />} |
| 81 | + </For> |
| 82 | + </div> |
| 83 | + </div> |
| 84 | + ); |
| 85 | +}; |
| 86 | + |
| 87 | +const ConnectModal = () => { |
| 88 | + const { t, notify } = useGlobalContext(); |
| 89 | + const { providers, connectProvider } = useWeb3Signer(); |
| 90 | + |
| 91 | + const [show, setShow] = createSignal<boolean>(false); |
| 92 | + |
| 93 | + return ( |
| 94 | + <> |
| 95 | + <button |
| 96 | + id="metamask" |
| 97 | + class="btn" |
| 98 | + onClick={() => { |
| 99 | + if (Object.keys(providers()).length > 1) { |
| 100 | + setShow(true); |
| 101 | + } else { |
| 102 | + // Do not show the modal when there is only one option to select |
| 103 | + connect( |
| 104 | + notify, |
| 105 | + connectProvider, |
| 106 | + Object.values(providers())[0].info, |
| 107 | + ).then(); |
| 108 | + } |
| 109 | + }}> |
| 110 | + {t("connect_metamask")} |
| 111 | + </button> |
| 112 | + <Modal show={show} setShow={setShow} /> |
| 113 | + </> |
| 114 | + ); |
| 115 | +}; |
| 116 | + |
| 117 | +const ShowAddress = ({ |
| 118 | + address, |
| 119 | +}: { |
| 120 | + address: Accessor<string | undefined>; |
| 121 | +}) => { |
| 122 | + const { t } = useGlobalContext(); |
| 123 | + const { clearSigner } = useWeb3Signer(); |
| 124 | + |
| 125 | + const [text, setText] = createSignal<string>(address()); |
| 126 | + |
| 127 | + return ( |
| 128 | + <button |
| 129 | + onClick={() => clearSigner()} |
| 130 | + onMouseEnter={() => setText(t("disconnect_address"))} |
| 131 | + onMouseLeave={() => setText(address())} |
| 132 | + class="btn btn-light"> |
| 133 | + {text()} |
| 134 | + </button> |
| 135 | + ); |
| 136 | +}; |
| 137 | + |
| 138 | +const ConnectMetamask = () => { |
| 139 | + const { t } = useGlobalContext(); |
| 140 | + const { providers, signer } = useWeb3Signer(); |
| 141 | + const { setAddressValid, setOnchainAddress } = useCreateContext(); |
| 142 | + |
| 143 | + const address = createMemo(() => signer()?.address); |
21 | 144 |
|
22 | 145 | createEffect(() => {
|
23 | 146 | const addr = address();
|
24 | 147 | setAddressValid(addr !== undefined);
|
25 | 148 | setOnchainAddress(addr || "");
|
26 | 149 | });
|
27 | 150 |
|
28 |
| - const { getSigner, hasMetamask } = useWeb3Signer(); |
29 |
| - |
30 | 151 | return (
|
31 | 152 | <>
|
32 |
| - <Show when={hasMetamask()}> |
33 |
| - <Show when={address() === undefined}> |
34 |
| - <button |
35 |
| - id="metamask" |
36 |
| - class="btn" |
37 |
| - onClick={async () => |
38 |
| - setAddress(await (await getSigner()).getAddress()) |
39 |
| - }> |
40 |
| - {t("connect_metamask")} |
| 153 | + <Show |
| 154 | + when={Object.keys(providers()).length > 0} |
| 155 | + fallback={ |
| 156 | + <button class="btn" disabled> |
| 157 | + {t("no_metamask")} |
41 | 158 | </button>
|
| 159 | + }> |
| 160 | + <Show |
| 161 | + when={address() !== undefined} |
| 162 | + fallback={<ConnectModal />}> |
| 163 | + <ShowAddress address={address} /> |
42 | 164 | </Show>
|
43 |
| - <Show when={address() !== undefined}> |
44 |
| - <Show when={showAddress}> |
45 |
| - <button |
46 |
| - onClick={() => setAddress(undefined)} |
47 |
| - onMouseEnter={() => |
48 |
| - setButtonText(t("disconnect_address")) |
49 |
| - } |
50 |
| - onMouseLeave={() => setButtonTextAddress()} |
51 |
| - class="btn btn-light"> |
52 |
| - {buttonText()} |
53 |
| - </button> |
54 |
| - </Show> |
55 |
| - </Show> |
56 |
| - </Show> |
57 |
| - <Show when={!hasMetamask()}> |
58 |
| - <button class="btn" disabled> |
59 |
| - {t("no_metamask")} |
60 |
| - </button> |
61 | 165 | </Show>
|
62 | 166 | </>
|
63 | 167 | );
|
|
0 commit comments