Skip to content

Commit caedfb2

Browse files
authored
Merge pull request #67 from compolabs/feat/1072-wallets-integration
[1072] Wallets integration
2 parents 580d08d + f58484c commit caedfb2

19 files changed

+18682
-8229
lines changed

package-lock.json

+18,419-7,944
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
"@compolabs/spark-orderbook-ts-sdk": "1.2.4",
99
"@emotion/react": "^11.11.3",
1010
"@emotion/styled": "^11.11.0",
11-
"@fuel-wallet/sdk": "^0.16.1",
11+
"@fuels/connectors": "^0.6.0",
12+
"@fuels/react": "^0.20.0",
1213
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
1314
"@pythnetwork/pyth-evm-js": "^1.33.0",
1415
"@svgr/webpack": "^8.1.0",
1516
"@szhsin/react-accordion": "^1.2.3",
17+
"@tanstack/react-query": "^5.40.1",
1618
"@tanstack/react-table": "^8.13.2",
1719
"@testing-library/jest-dom": "^5.17.0",
1820
"@testing-library/react": "^13.4.0",

src/assets/wallets/fuel.svg

-1
This file was deleted.

src/blockchain/FuelNetwork.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import Spark from "@compolabs/spark-orderbook-ts-sdk";
2-
import { WriteTransactionResponse } from "@compolabs/spark-orderbook-ts-sdk/dist/interface";
32
import { makeObservable } from "mobx";
43
import { Nullable } from "tsdef";
54

@@ -79,8 +78,8 @@ export class FuelNetwork {
7978
return TOKENS_BY_ASSET_ID[assetId.toLowerCase()];
8079
};
8180

82-
connectWallet = async (): Promise<void> => {
83-
await this.walletManager.connect();
81+
setWallet = async (account: string, wallet?: any): Promise<void> => {
82+
await this.walletManager.setWallet(account, wallet);
8483
this.sdk.setActiveWallet(this.walletManager.wallet ?? undefined);
8584
};
8685

@@ -98,7 +97,7 @@ export class FuelNetwork {
9897
await this.walletManager.addAsset(assetId);
9998
};
10099

101-
createSpotOrder = async (assetAddress: string, size: string, price: string): Promise<WriteTransactionResponse> => {
100+
createSpotOrder = async (assetAddress: string, size: string, price: string): Promise<any> => {
102101
const baseToken = this.getTokenByAssetId(assetAddress);
103102
const baseAsset = this.getAssetFromToken(baseToken);
104103
const quoteToken = this.getTokenBySymbol("USDC");

src/blockchain/WalletManager.ts

+16-46
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import { toast } from "react-toastify";
2-
import { Fuel, FuelWalletConnector } from "@fuel-wallet/sdk";
3-
import { Provider, Wallet, WalletLocked, WalletUnlocked } from "fuels";
1+
import { FuelWalletConnector } from "@fuels/connectors";
2+
import { Account, Fuel, Provider, Wallet, WalletLocked, WalletUnlocked } from "fuels";
43
import { makeAutoObservable } from "mobx";
54
import { Nullable } from "tsdef";
65

7-
import { createToast } from "@src/components/Toast";
8-
96
import { TOKENS_BY_ASSET_ID } from "./constants";
107
import { NETWORK_ERROR, NetworkError } from "./NetworkError";
118

@@ -20,34 +17,26 @@ export class WalletManager {
2017

2118
constructor() {
2219
makeAutoObservable(this);
23-
24-
this.fuel.on(this.fuel.events.currentAccount, this.onCurrentAccountChange);
2520
}
2621

27-
connect = async (): Promise<void> => {
28-
const hasConnector = await this.fuel.hasConnector();
29-
30-
if (!hasConnector) {
31-
throw new NetworkError(NETWORK_ERROR.NOT_CONNECTED);
32-
}
33-
const isApproved = await this.fuel.connect();
34-
35-
if (!isApproved) {
36-
return;
37-
}
38-
39-
let account = null;
22+
setWallet = async (account: string, wallet?: Account | null) => {
23+
let currentAccount: string | null = null;
4024
try {
41-
account = await this.fuel.currentAccount();
25+
currentAccount = await this.fuel.currentAccount();
4226
} catch (error) {
43-
console.error("Not authorized");
27+
console.error("Not authorized for fuel");
4428
}
45-
46-
if (!account) {
47-
throw new NetworkError(NETWORK_ERROR.UNKNOWN_ACCOUNT);
29+
if (currentAccount) {
30+
try {
31+
const fuelWallet = await this.fuel.getWallet(account);
32+
this.wallet = fuelWallet as any;
33+
} catch (err) {
34+
console.error("There is no wallet for this account");
35+
}
36+
} else {
37+
// for ethereum wallets should be another logic to connect
38+
this.wallet = wallet as any;
4839
}
49-
50-
this.wallet = await this.fuel.getWallet(account);
5140
this.address = account;
5241
};
5342

@@ -108,23 +97,4 @@ export class WalletManager {
10897

10998
void this.fuel.disconnect();
11099
};
111-
112-
private onCurrentAccountChange = async (account: Nullable<string>) => {
113-
if (account === null) {
114-
try {
115-
await this.connect();
116-
} catch (error) {
117-
if (error instanceof NetworkError) {
118-
if (error.code === NETWORK_ERROR.UNKNOWN_ACCOUNT) {
119-
toast(createToast({ text: "Please authorize the wallet account when connecting." }), { type: "info" });
120-
return;
121-
}
122-
}
123-
}
124-
return;
125-
}
126-
127-
this.wallet = await this.fuel.getWallet(account);
128-
this.address = account;
129-
};
130100
}

src/blockchain/constants.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { OrderbookContracts } from "@compolabs/spark-orderbook-ts-sdk/dist/interface";
1+
// import { OrderbookContracts } from "@compolabs/spark-orderbook-ts-sdk/dist/interface";
2+
// TODO: add types from sdk after fixed export
23

34
import TOKEN_LOGOS from "@src/constants/tokenLogos";
45
import { Token } from "@src/entity/Token";
56

67
import TOKENS_JSON from "./tokens.json";
78

8-
export const CONTRACT_ADDRESSES: OrderbookContracts = {
9+
export const CONTRACT_ADDRESSES: any = {
910
spotMarket: "0x4a2ce054e3e94155f7092f7365b212f7f45105b74819c623744ebcc5d065c6ac",
1011
tokenFactory: "0x3141a3f11e3f784364d57860e3a4dcf9b73d42e23fd49038773cefb09c633348",
1112
pyth: "0x3cd5005f23321c8ae0ccfa98fb07d9a5ff325c483f21d2d9540d6897007600c9",

src/components/Header/ConnectedWallet.tsx

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState } from "react";
22
import styled from "@emotion/styled";
3+
import { useDisconnect } from "@fuels/react";
34
import copy from "copy-to-clipboard";
45
import { observer } from "mobx-react";
56

@@ -11,6 +12,7 @@ import copyIcon from "@src/assets/icons/copy.svg";
1112
import linkIcon from "@src/assets/icons/link.svg";
1213
import logoutIcon from "@src/assets/icons/logout.svg";
1314
import { FuelNetwork } from "@src/blockchain";
15+
import { useWallet } from "@src/hooks/useWallet";
1416
import BN from "@src/utils/BN";
1517
import { getExplorerLinkByAddress } from "@src/utils/getExplorerLink";
1618
import { useStores } from "@stores";
@@ -21,6 +23,9 @@ import ConnectedWalletButton from "./ConnectedWalletButton";
2123

2224
const ConnectedWallet: React.FC = observer(() => {
2325
const { accountStore, notificationStore, balanceStore } = useStores();
26+
const { address } = useWallet();
27+
const { disconnect } = useDisconnect();
28+
2429
const [isFocused, setIsFocused] = useState(false);
2530

2631
const bcNetwork = FuelNetwork.getInstance();
@@ -31,10 +36,15 @@ const ConnectedWallet: React.FC = observer(() => {
3136
)?.toFormat(4);
3237

3338
const handleAddressCopy = () => {
34-
accountStore.address && copy(accountStore.address);
39+
address && copy(address);
3540
notificationStore.toast(createToast({ text: "Your address was copied" }), { type: "info" });
3641
};
3742

43+
const disconnectWallet = () => {
44+
disconnect();
45+
accountStore.disconnect();
46+
};
47+
3848
const actions = [
3949
{
4050
icon: copyIcon,
@@ -44,13 +54,13 @@ const ConnectedWallet: React.FC = observer(() => {
4454
},
4555
{
4656
icon: linkIcon,
47-
action: () => window.open(getExplorerLinkByAddress(accountStore.address!)),
57+
action: () => window.open(getExplorerLinkByAddress(address)),
4858
title: "View in Explorer",
4959
active: true,
5060
},
5161
{
5262
icon: logoutIcon,
53-
action: () => accountStore.disconnect(),
63+
action: () => disconnect(),
5464
title: "Disconnect",
5565
active: true,
5666
},

src/components/Header/ConnectedWalletButton.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ interface Props {
1515
onClick?: () => void;
1616
}
1717

18+
// TODO: if user is connected with PK shows different address
19+
1820
const ConnectedWalletButton: React.FC<Props> = observer(({ isFocused, className, onClick }) => {
1921
const { accountStore } = useStores();
2022

src/components/Header/Header.tsx

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react";
1+
import React, { useEffect } from "react";
22
import { Link, useLocation } from "react-router-dom";
33
import styled from "@emotion/styled";
44
import { observer } from "mobx-react";
@@ -9,9 +9,11 @@ import Tab from "@components/Tab";
99
import { TEXT_TYPES } from "@components/Text";
1010
import { ReactComponent as Logo } from "@src/assets/icons/logo.svg";
1111
import { ReactComponent as Menu } from "@src/assets/icons/menu.svg";
12+
import { FuelNetwork } from "@src/blockchain";
1213
import { MENU_ITEMS } from "@src/constants";
1314
import useFlag from "@src/hooks/useFlag";
1415
import { useMedia } from "@src/hooks/useMedia";
16+
import { useWallet } from "@src/hooks/useWallet";
1517
import ConnectWalletDialog from "@src/screens/ConnectWallet";
1618
import { MODAL_TYPE } from "@src/stores/ModalStore";
1719
import { media } from "@src/themes/breakpoints";
@@ -26,14 +28,23 @@ import DepositWithdrawModal from "./DepositWithdrawModal";
2628
import MobileMenu from "./MobileMenu";
2729

2830
const Header: React.FC = observer(() => {
29-
const { tradeStore, accountStore, modalStore } = useStores();
31+
const { tradeStore, modalStore, accountStore } = useStores();
32+
const { address, wallet } = useWallet();
3033
const location = useLocation();
3134
const media = useMedia();
3235

3336
const [isMobileMenuOpen, openMobileMenu, closeMobileMenu] = useFlag();
3437
const [isConnectDialogVisible, openConnectDialog, closeConnectDialog] = useFlag();
3538
const [isAccountInfoSheetOpen, openAccountInfo, closeAccountInfo] = useFlag();
3639

40+
useEffect(() => {
41+
accountStore.setAddress(address);
42+
if (address && wallet) {
43+
const bcNetwork = FuelNetwork.getInstance();
44+
bcNetwork.setWallet(address, wallet);
45+
}
46+
}, [address, wallet?.address]);
47+
3748
const toggleMenu = () => {
3849
window.scrollTo({ top: 0, behavior: "smooth" });
3950

@@ -45,7 +56,7 @@ const Header: React.FC = observer(() => {
4556
};
4657

4758
const renderWallet = () => {
48-
if (!accountStore.address) {
59+
if (!address) {
4960
return (
5061
<WalletContainer>
5162
<Button fitContent green onClick={openConnectDialog}>
@@ -157,7 +168,9 @@ const Header: React.FC = observer(() => {
157168
onDepositWithdrawClick={() => modalStore.open(MODAL_TYPE.DEPOSIT_WITHDRAW_MODAL)}
158169
onWalletConnect={openConnectDialog}
159170
/>
160-
<ConnectWalletDialog visible={isConnectDialogVisible} onClose={closeConnectDialog} />
171+
{isConnectDialogVisible ? (
172+
<ConnectWalletDialog visible={isConnectDialogVisible} onClose={closeConnectDialog} />
173+
) : null}
161174
<AccountInfoSheet isOpen={isAccountInfoSheetOpen} onClose={closeAccountInfo} />
162175
<DepositWithdrawModal visible={modalStore.isOpen(MODAL_TYPE.DEPOSIT_WITHDRAW_MODAL)} onClose={modalStore.close} />
163176
</Root>

src/components/Modal/AccountInfoSheet.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import React from "react";
22
import styled from "@emotion/styled";
3+
import { useDisconnect } from "@fuels/react";
34
import copy from "copy-to-clipboard";
45

56
import copyIcon from "@src/assets/icons/copy.svg";
67
import linkIcon from "@src/assets/icons/link.svg";
78
import logoutIcon from "@src/assets/icons/logout.svg";
89
import { FuelNetwork } from "@src/blockchain";
10+
import { useWallet } from "@src/hooks/useWallet";
911
import { useStores } from "@src/stores";
1012
import BN from "@src/utils/BN";
1113
import { getExplorerLinkByAddress } from "@src/utils/getExplorerLink";
@@ -23,6 +25,8 @@ interface Props {
2325

2426
const AccountInfoSheet: React.FC<Props> = ({ isOpen, onClose }) => {
2527
const { accountStore, notificationStore, balanceStore } = useStores();
28+
const { balance } = useWallet();
29+
const { disconnect } = useDisconnect();
2630

2731
const bcNetwork = FuelNetwork.getInstance();
2832

@@ -39,6 +43,7 @@ const AccountInfoSheet: React.FC<Props> = ({ isOpen, onClose }) => {
3943

4044
const handleDisconnect = () => {
4145
accountStore.disconnect();
46+
disconnect();
4247
onClose();
4348
};
4449

src/components/Toast.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ interface IProps {
1010
linkText?: string;
1111
hash?: string;
1212
address?: string;
13+
url?: string;
1314
}
1415

15-
const Toast: React.FC<IProps> = ({ text, linkText = "Open In Explorer", hash, address }) => {
16-
const link = hash ? getExplorerLinkByHash(hash) : address ? getExplorerLinkByAddress(address) : undefined;
16+
const Toast: React.FC<IProps> = ({ text, linkText = "Open In Explorer", hash, address, url }) => {
17+
let link = url;
18+
if (hash) {
19+
link = getExplorerLinkByHash(hash);
20+
} else if (address) {
21+
link = getExplorerLinkByAddress(address);
22+
}
1723

1824
return (
1925
<SmartFlex gap="8px" column>

src/constants/index.ts

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { FueletWalletConnector, FuelWalletConnector } from "@fuels/connectors";
2+
13
export const ROUTES = {
24
ROOT: "/",
35
TRADE: "/:marketId",
@@ -25,3 +27,15 @@ export const MENU_ITEMS: Array<TMenuItem> = [
2527
{ title: "GITHUB", link: "https://github.com/compolabs/spark" },
2628
{ title: "TWITTER", link: "https://twitter.com/Sprkfi" },
2729
];
30+
31+
export const FUEL_CONFIG = {
32+
connectors: [
33+
new FuelWalletConnector(),
34+
new FueletWalletConnector(),
35+
// new WalletConnectConnector({
36+
// wagmiConfig,
37+
// projectId: WC_PROJECT_ID,
38+
// }),
39+
// new FuelWalletDevelopmentConnector(),
40+
],
41+
};

0 commit comments

Comments
 (0)