Skip to content

Commit

Permalink
Add new wallet options (#45)
Browse files Browse the repository at this point in the history
* feat(wallet options): add new wallet options

* fix(callback): update callback type

* fix(wallet connection): fix wallet connection buttons style

* fix(result link): add result link to the success modal

* fix(errors): fix build errors

* fix(error): fix build error

* fix(wallets): fix substrate wallet connections

* clean up

* fix(wallet modal): update wallet connection modal

* fix: chain name display

* fix: asset selection

* fix: alert on which chain

---------

Co-authored-by: JayJay1024 <[email protected]>
  • Loading branch information
hamidroohi92 and JayJay1024 authored Oct 10, 2024
1 parent 8995435 commit 9797d02
Show file tree
Hide file tree
Showing 25 changed files with 8,562 additions and 791 deletions.
8,452 changes: 8,005 additions & 447 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@
"@polkadot/react-identicon": "^3.6.3",
"@rainbow-me/rainbowkit": "^1.1.3",
"@react-spring/web": "^9.5.0",
"@talisman-connect/wallets": "^1.1.3",
"@talismn/connect-wallets": "^1.2.3",
"coinbase-wallet-sdk": "^0.0.1-security",
"ethers": "^6.13.2",
"next": "13.5.4",
"react": "^18",
"react-dom": "^18",
"react-jazzicon": "^1.0.4",
"react-transition-group": "^4.4.5",
"viem": "^1.16.6",
"wagmi": "^1.4.5"
"wagmi": "^1.4.5",
"walletconnect": "^1.7.8"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
9 changes: 9 additions & 0 deletions src/app/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// global.d.ts
interface Window {
ethereum?: {
isMetaMask?: boolean;
request: (args: { method: string; params?: Array<any> }) => Promise<any>;
on: (event: string, callback: (...args: any[]) => void) => void;
removeListener: (event: string, callback: (...args: any[]) => void) => void;
};
}
12 changes: 10 additions & 2 deletions src/components/accountButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default function AccountButton({ setSwitchWallet }: { setSwitchWallet: (x
setActiveSenderWallet(undefined);
setActiveSenderAccount(undefined);
disconnect();
}, [setSender, setActiveSenderWallet, setActiveSenderAccount]);
}, [setSender, setActiveSenderWallet, setActiveSenderAccount, disconnect]);

useEffect(() => {
if (needSwitchNetwork) {
Expand All @@ -78,7 +78,15 @@ export default function AccountButton({ setSwitchWallet }: { setSwitchWallet: (x
setSwitchWallet(true);
});
}
}, [sourceChain, chain, switchNetworkAsync]);
}, [
sourceChain,
chain,
switchNetworkAsync,
handleDisconnect,
setSwitchWallet,
activeSenderWallet,
needSwitchNetwork,
]);

useEffect(() => {
window.addEventListener("click", () => {
Expand Down
168 changes: 70 additions & 98 deletions src/components/appBox.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
"use client";

import { ChangeEventHandler, useCallback, useEffect, useMemo, useRef, useState } from "react";
import data from "../data/data.json";
import { ChangeEventHandler, useCallback, useMemo, useRef, useState } from "react";
import Image from "next/image";
import ChainSelectInput, { chainType } from "./chainSelectInput";
import ChainSelectInput from "./chainSelectInput";
import SuccessModal from "./successModal";
import PendingModal from "./pendingModal";
import { formatBalance, getAssetIconSrc, isExceedingCrossChainLimit, isValidAddress, parseCross } from "@/utils";
import {
formatBalance,
getAssetIconSrc,
getAvailableSourceAsset,
getAvailableSourceChain,
getAvailableSourceChainOptions,
getAvailableTargetAsset,
getAvailableTargetChain,
getAvailableTargetChainOptions,
isExceedingCrossChainLimit,
isValidAddress,
} from "@/utils";
import { useTransfer } from "@/hooks";
import { BN, BN_ZERO, bnToBn } from "@polkadot/util";
import { formatUnits, parseUnits } from "viem";
import { WalletID } from "@/types";
import { useAccount, useNetwork, useSwitchNetwork } from "wagmi";
import notification from "@/ui/notification";
import { supportedTokenList } from "@/config/tokens";
import { useTrail, animated, useSpring } from "@react-spring/web";
import WalletSelectionModal from "./walletSelectionModal";
import { assetCategories } from "@/config/asset-categories";

export default function AppBox() {
const [connectModal, setConnectModal] = useState(false);

const { defaultSourceChainOptions, defaultSourceAssetOptions } = parseCross();
const [selectedAsset, setSelectedAsset] = useState(supportedTokenList[0]);
const [allowedChain, setAllowedChain] = useState<any>([]);
// const [sourceAssetOptions, setSourceAssetOptions] = useState(defaultSourceAssetOptions);
const [successModal, setSuccessModal] = useState<boolean>(false);
const [receipt, setReceipt] = useState<boolean | null>(false);

const {
sender,
Expand Down Expand Up @@ -57,20 +63,29 @@ export default function AppBox() {
activeSenderAccount,
feeBalanceOnSourceChain,
sourceNativeBalance,
assetCategory,
setAssetCategory,
} = useTransfer();

const handleCloseSuccessModal = useCallback(() => {
setSuccessModal(false);
setReceipt(null);
setTransferAmount({ valid: true, input: "", amount: BN_ZERO });
updateSourceAssetBalance();
updateTargetAssetBalance();
updateTargetAssetSupply();
updateSourceNativeBalance();
updateTargetNativeBalance();
updateFeeBalanceOnSourceChain();
}, []);

const sourceChainRef = useRef(sourceChain);
const targetChainRef = useRef(targetChain);
}, [
setTransferAmount,
updateFeeBalanceOnSourceChain,
updateSourceAssetBalance,
updateSourceNativeBalance,
updateTargetAssetBalance,
updateTargetAssetSupply,
updateTargetNativeBalance,
]);

const cross = bridgeInstance?.getCrossInfo();
const assetLimit = assetLimitOnTargetChain?.amount;
Expand Down Expand Up @@ -148,15 +163,13 @@ export default function AppBox() {
fee.amount,
feeBalanceOnSourceChain.currency.decimals,
)} ${feeBalanceOnSourceChain.currency.symbol} in your Sender on ${
sourceChainRef.current.name
sourceChain.name
} to cover cross-chain fees.`}</span>
</div>
);
}
return null;
}, [bridgeInstance, feeBalanceOnSourceChain]);

// console.log("fee alert", feeAlert);
}, [bridgeInstance, feeBalanceOnSourceChain, sourceChain]);

const existentialAlertOnSourceChain = useMemo(() => {
if (
Expand Down Expand Up @@ -198,13 +211,13 @@ export default function AppBox() {
existentialDepositOnTargetChain.amount,
existentialDepositOnTargetChain.currency.decimals,
)} ${existentialDepositOnTargetChain.currency.symbol} in your Recipient on ${
targetChainRef.current.name
targetChain.name
} to keep an account open.`}</span>
</div>
);
}
return null;
}, [targetNativeBalance, existentialDepositOnTargetChain]);
}, [targetNativeBalance, existentialDepositOnTargetChain, targetChain]);

const disabledSend =
!sender?.address ||
Expand All @@ -217,25 +230,13 @@ export default function AppBox() {
!!existentialAlertOnSourceChain ||
!!existentialAlertOnTargetChain;

// console.log(
// "check this now",
// sender?.address,
// sender?.valid,
// recipient?.address,
// recipient?.valid,
// transferAmount.input,
// transferAmount.valid,
// feeAlert,
// existentialAlertOnSourceChain,
// existentialAlertOnTargetChain,
// );

const handleSend = useCallback(async () => {
if (needSwitchNetwork) {
switchNetwork?.(sourceChain.id);
} else if (bridgeInstance && recipient) {
const callback = {
successCb: () => {
successCb: (receipt: any) => {
setReceipt(receipt);
setBusy(false);
setSuccessModal(true);
},
Expand All @@ -262,69 +263,14 @@ export default function AppBox() {
needSwitchNetwork,
recipient,
sender?.address,
setTransferAmount,
sourceChain.id,
switchNetwork,
transfer,
transferAmount.amount,
transferAmount.input,
updateFeeBalanceOnSourceChain,
updateSourceAssetBalance,
updateTargetAssetBalance,
updateTargetAssetSupply,
updateSourceNativeBalance,
updateTargetNativeBalance,
]);

useEffect(() => {
console.log("defaultSourceAssetOptions", sourceChain.assets);
let sourceChainOptions: any = [];
for (const item of selectedAsset.allowedSource) {
for (const chain of defaultSourceChainOptions) {
if (chain.name === item) {
sourceChainOptions.push(chain);
}
}
}
let selectedSourceAsset;
for (const item of sourceChainOptions[0].assets) {
if (selectedAsset.icon === item.icon) {
selectedSourceAsset = item;
}
}
setAllowedChain([...sourceChainOptions]);
setSourceChain(sourceChainOptions[0]);
setSourceAsset(selectedSourceAsset);
setTargetChain(sourceChainOptions[1]);
}, [selectedAsset]);

useEffect(() => {
console.log(allowedChain);
if (allowedChain.length > 0) {
if (sourceChain.name === allowedChain[0].name && targetChain.name === allowedChain[0].name) {
setTargetChain(allowedChain[1]);
} else if (sourceChain.name === allowedChain[1].name && targetChain.name === allowedChain[1].name) {
setTargetChain(allowedChain[0]);
}
}
for (const asset of sourceChain.assets) {
if (selectedAsset.name === asset.name) setSourceAsset(asset);
}
}, [sourceChain]);

useEffect(() => {
if (allowedChain.length > 0) {
if (targetChain.name === allowedChain[0].name && sourceChain.name == allowedChain[0].name) {
setSourceChain(allowedChain[1]);
} else if (targetChain.name === allowedChain[1].name && sourceChain.name === allowedChain[1].name) {
setSourceChain(allowedChain[0]);
}
}
for (const asset of targetChain.assets) {
if (selectedAsset.name === asset.name) setTargetAsset(asset);
}
}, [targetChain]);

const trails = useTrail(5, {
from: { transform: "translateX(-100%)", opacity: 0 },
to: { opacity: 1, transform: "translateX(0)" },
Expand All @@ -335,8 +281,6 @@ export default function AppBox() {
to: { opacity: 1, transform: "translateY(0)" },
});

// console.log("check this.................", sender, needSwitchNetwork, disabledSend);

return (
<>
<animated.section
Expand All @@ -351,16 +295,24 @@ export default function AppBox() {
<p className="text-[12px] leading-[15.22px] text-[#12161980]">Token</p>
</div>
<div className="flex items-center gap-[10px]">
{supportedTokenList.map((item: any) => (
{assetCategories.map((item) => (
<div
className="flex items-center gap-[10px] duration-500"
key={item.name}
style={{
maxWidth: selectedAsset.name === item.name ? "100px" : "30px",
transitionDelay: selectedAsset.name === item.name ? "0.4s" : "0s",
maxWidth: assetCategory === item.category ? "100px" : "30px",
transitionDelay: assetCategory === item.category ? "0.4s" : "0s",
}}
onClick={() => {
setSelectedAsset(item);
setAssetCategory(item.category);
const _sourceChain = getAvailableSourceChain(getAvailableSourceChainOptions(item.category));
const _sourceAsset = getAvailableSourceAsset(_sourceChain, item.category);
const _targetChain = getAvailableTargetChain(getAvailableTargetChainOptions(_sourceAsset));
const _targetAsset = getAvailableTargetAsset(_targetChain, item.category);
setSourceChain(_sourceChain);
setSourceAsset(_sourceAsset);
setTargetChain(_targetChain);
setTargetAsset(_targetAsset);
}}
>
<Image
Expand All @@ -381,7 +333,19 @@ export default function AppBox() {
>
<div className="flex h-[30px] items-center justify-between">
<p className="text-[12px] leading-[15.22px] text-[#12161980]">Sender</p>
<ChainSelectInput options={allowedChain} who="sender" />
<ChainSelectInput
value={sourceChain}
options={getAvailableSourceChainOptions(assetCategory)}
onSelect={(chain) => {
setSourceChain(chain);
const _sourceAsset = getAvailableSourceAsset(chain, assetCategory);
const _targetChain = getAvailableTargetChain(getAvailableTargetChainOptions(_sourceAsset));
const _targetAsset = getAvailableTargetAsset(_targetChain, assetCategory);
setSourceAsset(_sourceAsset);
setTargetChain(_targetChain);
setTargetAsset(_targetAsset);
}}
/>
</div>
{sender ? (
<input
Expand Down Expand Up @@ -409,7 +373,15 @@ export default function AppBox() {
>
<div className="flex h-[30px] items-center justify-between">
<p className="text-[12px] leading-[15.22px] text-[#12161980]">Recipient</p>
<ChainSelectInput options={allowedChain} who="target" />
<ChainSelectInput
value={targetChain}
options={getAvailableTargetChainOptions(sourceAsset)}
onSelect={(chain) => {
setTargetChain(chain);
const _targetAsset = getAvailableTargetAsset(chain, assetCategory);
setTargetAsset(_targetAsset);
}}
/>
</div>
<input
type="text"
Expand Down Expand Up @@ -495,7 +467,7 @@ export default function AppBox() {
</animated.div>
</animated.section>

<SuccessModal visible={successModal} onClose={handleCloseSuccessModal} />
<SuccessModal visible={successModal} onClose={handleCloseSuccessModal} receipt={receipt} />
<PendingModal visible={busy} />
<WalletSelectionModal
visible={connectModal}
Expand Down
Loading

0 comments on commit 9797d02

Please sign in to comment.