Skip to content

Commit

Permalink
Implement Centrifuge EVM address support (#4039)
Browse files Browse the repository at this point in the history
* Implement Centrifuge EVM address support

* fix: merge
  • Loading branch information
hyifeng authored Mar 22, 2024
1 parent 8299599 commit b97eb50
Show file tree
Hide file tree
Showing 30 changed files with 187 additions and 72 deletions.
2 changes: 1 addition & 1 deletion packages/next-common/components/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
WalletNova,
} from "@osn/icons/subsquare";
import WalletTypes from "next-common/utils/consts/walletTypes";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

const WalletIcon = ({ wallet }) => {
return (
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/addressCombo.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import IdentityIcon from "./Identity/identityIcon.js";
import {
getAddressHint,
tryConvertToEvmAddress,
} from "next-common/utils/hydradxUtil.js";
} from "next-common/utils/mixedChainUtil";
import { isEthereumAddress } from "@polkadot/util-crypto";

const Wrapper = Relative;
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/addressSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { addressEllipsis } from "../utils";
import PseudoAvatar from "../assets/imgs/pesudoAvatar.svg";
import { useChainSettings } from "../context/chain";
import { normalizeAddress } from "next-common/utils/address.js";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil.js";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

const Wrapper = Relative;

Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useThemeSetting } from "../context/theme";
import makeBlockie from "ethereum-blockies-base64";
import { isEthereumAddress } from "@polkadot/util-crypto";
import { isPolkadotAddress } from "next-common/utils/viewfuncs";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";
import { useAddressAvatarMap } from "next-common/context/avatar";

const StyledIdenticon = styled(Identicon)`
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/linkedAddress.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { isPolkadotAddress } from "next-common/utils/viewfuncs";
import PrimaryButton from "next-common/lib/button/primary";
import { NeutralPanel } from "./styled/containers/neutralPanel";
import { useSignMessage } from "next-common/hooks/useSignMessage";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

const InfoWrapper = styled.div`
background: var(--neutral200);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { NeutralPanel } from "next-common/components/styled/containers/neutralPa
import { isKintsugiChain } from "next-common/utils/chain";
import Link from "next/link";
import useAccountUrl from "next-common/hooks/account/useAccountUrl";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";
import AccountDelegationPrompt from "./components/delegationPrompt";

const DisplayUserAvatar = () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/popup/proxyInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { formatBalance } from "../../utils/viewfuncs";
import Loading from "../loading";
import Tooltip from "../tooltip";
import { GreyPanel } from "../styled/containers/greyPanel";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

export default function ProxyInfo({ address, balance, isLoading, symbol }) {
const noBalance = isNil(balance) && isNil(isLoading);
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/profile/bio.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import KintAssetInfo from "./assetInfo/kint";
import Chains from "next-common/utils/consts/chains";
import AddressUser from "../user/addressUser";
import { usePageProps } from "next-common/context/page";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

const Wrapper = styled.div`
padding: 24px 0;
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/profile/breadcrumbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import BreadcrumbWrapper from "next-common/components/detail/common/BreadcrumbWrapper";
import Breadcrumb from "next-common/components/_Breadcrumb";
import { addressEllipsis } from "next-common/utils";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";
import { usePageProps } from "next-common/context/page";

export default function ProfileBreadcrumbs() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import useProfileAddress from "../useProfileAddress";
import { useRouter } from "next/router";
import { useEffect } from "react";
import PageUrlTabs from "next-common/components/pageTabs/pageUrlTabs";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

export default function ListTabs() {
const address = useProfileAddress();
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/profile/posted/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import List from "./list";
import Categories from "./categories";
import isMoonChain from "next-common/utils/isMoonChain";
import { usePageProps } from "next-common/context/page";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

const getCategoryByRoute = (route, categories = []) => {
let category;
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/profile/tabs/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import ProfileTransfers from "../transfers";
import ProfileIdentityTimeline from "../identityTimeline";
import { usePathname } from "next/navigation";
import { usePageProps } from "next-common/context/page";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

export default function useProfileTabContent() {
const { id } = usePageProps();
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/profile/tabs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useSelector } from "react-redux";
import { profileActiveMultisigsCountSelector } from "next-common/store/reducers/profile/multisig";
import useDepositsCount from "next-common/hooks/profile/deposit/useDepositsCount";
import { usePageProps } from "next-common/context/page";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

export default function useProfileTabs() {
const { id } = usePageProps();
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/setting/proxyAddress.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import styled from "styled-components";
import PrimaryButton from "next-common/lib/button/primary";
import { useEnsureLogin } from "next-common/hooks/useEnsureLogin";
import { normalizeAddress } from "next-common/utils/address";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";
import { useContextApi } from "next-common/context/api";

const CustomErrorMessage = styled(ErrorMessage)`
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/setting/web3Address.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { addressEllipsis } from "../../utils";
import Avatar from "../avatar";
import useIdentityInfo from "next-common/hooks/useIdentityInfo";
import Identity from "../Identity";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

const AddressWrapper = styled.div`
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/user/addressUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import AddressDisplay from "./addressDisplay";
import useIdentityInfo from "next-common/hooks/useIdentityInfo";
import { useWidth } from "./util";
import DeletedAccount from "./deletedAccount";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

export function AddressUserImpl({
className = "",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/user/systemUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Avatar from "../avatar";
import Gravatar from "../gravatar";
import useIdentityInfo from "next-common/hooks/useIdentityInfo";
import { useWidth } from "./util";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

function SystemUser({
user,
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/components/user/userDisplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import { addressEllipsis, isKeyRegisteredUser } from "../../utils";
import Tooltip from "../tooltip";
import Username from "./username";
import { tryConvertToEvmAddress } from "next-common/utils/hydradxUtil";
import { tryConvertToEvmAddress } from "next-common/utils/mixedChainUtil";

export default function UserDisplay({
user,
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/hooks/useSignMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import useInjectedWeb3 from "next-common/components/wallet/useInjectedWeb3";
import {
getEvmSignerAddress,
tryConvertToEvmAddress,
} from "next-common/utils/hydradxUtil";
} from "next-common/utils/mixedChainUtil";

export function useSignMessage() {
const { injectedWeb3 } = useInjectedWeb3();
Expand Down
9 changes: 7 additions & 2 deletions packages/next-common/utils/address.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { decodeAddress } from "@polkadot/util-crypto";
import { encodeAddressToChain } from "next-common/services/address";
import { isEthereumAddress } from "@polkadot/util-crypto";
import { evmToSubstrateAddress } from "./hydradxUtil";
import { evmToSubstrateAddress as hydradxEvmToSubstrateAddress } from "./hydradxUtil";
import { evmToSubstrateAddress as centrifugeEvmToSubstrateAddress } from "./centrifugeUtil";
import isHydradx from "./isHydradx";
import isCentrifuge from "./isCentrifuge";

export function addressToPublicKey(address) {
return Buffer.from(decodeAddress(address)).toString("hex");
Expand All @@ -15,7 +17,10 @@ export function normalizeAddress(address) {

if (isEthereumAddress(address)) {
if (isHydradx()) {
return evmToSubstrateAddress(address);
return hydradxEvmToSubstrateAddress(address);
}
if (isCentrifuge()) {
return centrifugeEvmToSubstrateAddress(address);
}
return address;
}
Expand Down
64 changes: 64 additions & 0 deletions packages/next-common/utils/centrifugeUtil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Buffer } from "buffer";
import { encodeAddress, decodeAddress } from "@polkadot/util-crypto";
import { getAddress as getEvmAddress } from "ethers";
import { isPolkadotAddress } from "./viewfuncs";
import { isEthereumAddress } from "@polkadot/util-crypto";
import isCentrifuge from "./isCentrifuge";

const CENTRIFUGE_ADDRESS_PREFIX = 36;
const zeroBytes = Buffer.alloc(6);
const chainId = Buffer.from("07ef", "hex");
const evmTagBytes = Buffer.from("EVM\0");
const suffixBytes = Buffer.concat([zeroBytes, chainId, evmTagBytes]);

export function safeConvertAddressH160(value) {
try {
return getEvmAddress(value?.toLowerCase());
} catch {
return null;
}
}

export function evmToSubstrateAddress(address) {
if (!address) {
return;
}
if (isPolkadotAddress(address)) {
return address;
}
const addressBytes = Buffer.from(address.slice(2), "hex");
const publicKey = Buffer.concat([addressBytes, suffixBytes]);
return encodeAddress(new Uint8Array(publicKey), CENTRIFUGE_ADDRESS_PREFIX);
}

export function substrateToEvmAddress(address) {
if (!address) {
return;
}
if (isEthereumAddress(address)) {
return address;
}
const decodedBytes = decodeAddress(address);
const addressBytes = decodedBytes.slice(0, -suffixBytes.length);
return (
safeConvertAddressH160(Buffer.from(addressBytes).toString("hex")) ?? ""
);
}

export function checkIfShouldConvertToEvmAddress(address) {
if (!isCentrifuge() || !isPolkadotAddress(address)) {
return false;
}

try {
const decodedBytes = decodeAddress(address);
const addressHex = Buffer.from(decodedBytes).toString("hex");
if (addressHex.endsWith(suffixBytes.toString("hex"))) {
return true;
}
} catch (e) {
// ignore
}

return false;
}
14 changes: 14 additions & 0 deletions packages/next-common/utils/consts/settings/centrifuge.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ProjectLogoCentrifugeDark,
ProjectLogoCentrifugeLight,
} from "@osn/icons/subsquare";
import ChainTypes from "../chainTypes";

const name = Chains.centrifuge;

Expand Down Expand Up @@ -47,6 +48,17 @@ const links = [
},
];

const ethereumNetwork = {
chainId: "0x7ef",
chainName: "Centrifuge",
rpcUrls: ["https://fullnode.parachain.centrifuge.io/"],
blockExplorerUrls: ["https://centrifuge.subscan.io/"],
nativeCurrency: {
symbol: "CFG",
decimals: 18,
},
};

const centrifuge = {
value: name,
name: capitalize(name),
Expand Down Expand Up @@ -95,6 +107,8 @@ const centrifuge = {
navigationActive: "rgba(38,41,56,1)",
navigationBorder: "var(--neutral300)",
},
chainType: ChainTypes.MIXED,
ethereumNetwork,
};

export default centrifuge;
2 changes: 1 addition & 1 deletion packages/next-common/utils/hooks/useMentionList.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { uniqBy } from "lodash-es";
import { useUser } from "../../context/user";
import { useChain } from "../../context/chain";
import { addressEllipsis, isKeyRegisteredUser } from "..";
import { tryConvertToEvmAddress } from "../hydradxUtil";
import { tryConvertToEvmAddress } from "../mixedChainUtil";

export default function useMentionList(post, comments) {
const chain = useChain();
Expand Down
46 changes: 0 additions & 46 deletions packages/next-common/utils/hydradxUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getAddress as getEvmAddress } from "ethers";
import { isPolkadotAddress } from "./viewfuncs";
import { isEthereumAddress } from "@polkadot/util-crypto";
import isHydradx from "./isHydradx";
import { addressEllipsis } from ".";

const HYDRA_ADDRESS_PREFIX = 63;
const prefixBytes = Buffer.from("ETH\0");
Expand Down Expand Up @@ -69,48 +68,3 @@ export function checkIfShouldConvertToEvmAddress(address) {

return false;
}

export function tryConvertToEvmAddress(address) {
if (!address) {
return address;
}
if (checkIfShouldConvertToEvmAddress(address)) {
return substrateToEvmAddress(address);
}
return address;
}

export function tryConvertToSubstrateAddress(address) {
if (!address) {
return address;
}
if (isEthereumAddress(address)) {
if (isHydradx()) {
return evmToSubstrateAddress(address);
}
return getEvmAddress(address);
}
return address;
}

export function getEvmSignerAddress(address) {
if (isHydradx() && !isEthereumAddress(address)) {
return substrateToEvmAddress(address);
}
return address;
}

export function getAddressHint(address) {
let addressHint = "--";

if (address) {
const maybeEvmAddress = tryConvertToEvmAddress(address);

addressHint = addressEllipsis(maybeEvmAddress);
if (maybeEvmAddress !== address) {
addressHint += ` (${addressEllipsis(address)})`;
}
}

return addressHint;
}
5 changes: 5 additions & 0 deletions packages/next-common/utils/isCentrifuge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Chains from "./consts/chains";

export default function isCentrifuge() {
return Chains.centrifuge === process.env.NEXT_PUBLIC_CHAIN;
}
Loading

0 comments on commit b97eb50

Please sign in to comment.