From 2227b096ca0db3b72bd69b9bd05fe41c2a0605f4 Mon Sep 17 00:00:00 2001
From: tomjeatt <40243778+tomjeatt@users.noreply.github.com>
Date: Wed, 26 Feb 2025 10:52:47 +0000
Subject: [PATCH 1/4] App alert banner (#1679)
App alert banner
---
src/components/AppAlert/AppAlert.styles.tsx | 11 ++++++++
src/components/AppAlert/AppAlert.tsx | 29 +++++++++++++++++++++
src/components/AppAlert/index.tsx | 1 +
src/components/Layout/Layout.tsx | 16 +++++++-----
src/hooks/use-local-storage.ts | 4 ++-
5 files changed, 54 insertions(+), 7 deletions(-)
create mode 100644 src/components/AppAlert/AppAlert.styles.tsx
create mode 100644 src/components/AppAlert/AppAlert.tsx
create mode 100644 src/components/AppAlert/index.tsx
diff --git a/src/components/AppAlert/AppAlert.styles.tsx b/src/components/AppAlert/AppAlert.styles.tsx
new file mode 100644
index 0000000000..1eec8563d2
--- /dev/null
+++ b/src/components/AppAlert/AppAlert.styles.tsx
@@ -0,0 +1,11 @@
+import styled from "styled-components";
+
+import { CTA, theme } from "@/component-library";
+
+const StyledCloseCTA = styled(CTA)`
+ position: absolute;
+ right: ${theme.spacing.spacing2};
+ top: 0;
+`;
+
+export { StyledCloseCTA };
diff --git a/src/components/AppAlert/AppAlert.tsx b/src/components/AppAlert/AppAlert.tsx
new file mode 100644
index 0000000000..2cb44f9016
--- /dev/null
+++ b/src/components/AppAlert/AppAlert.tsx
@@ -0,0 +1,29 @@
+import { XMark } from "@/assets/icons";
+import { Alert, Flex, P } from "@/component-library";
+import { LocalStorageKey,useLocalStorage } from "@/hooks/use-local-storage";
+
+import { StyledCloseCTA } from "./AppAlert.styles";
+
+type Props = {
+ alertText: string
+}
+
+const AppAlert = ({ alertText }: Props): JSX.Element => {
+ const [isAlertOpen, setIsAlertOpen] = useLocalStorage(LocalStorageKey.APP_ALERT_BANNER, true);
+
+ return (
+ <>
+ {isAlertOpen && (
+
+
+ {alertText}
+
+ setIsAlertOpen(false)}>
+
+
+
+ )}
+ >
+ );};
+
+export { AppAlert };
diff --git a/src/components/AppAlert/index.tsx b/src/components/AppAlert/index.tsx
new file mode 100644
index 0000000000..3d4f29c994
--- /dev/null
+++ b/src/components/AppAlert/index.tsx
@@ -0,0 +1 @@
+export { AppAlert } from './AppAlert';
diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx
index dc82b1cdb6..a72286a7c8 100644
--- a/src/components/Layout/Layout.tsx
+++ b/src/components/Layout/Layout.tsx
@@ -1,5 +1,6 @@
import Sidebar from '../../legacy-components/Sidebar';
import Topbar from '../../legacy-components/Topbar';
+import { AppAlert } from '../AppAlert';
import { StyledWrapper } from './Layout.styles';
interface Props {
@@ -8,12 +9,15 @@ interface Props {
}
const Layout = ({ className, children }: Props): JSX.Element => (
-
-
-
- {children}
-
-
+ <>
+
+
+
+
+ {children}
+
+
+ >
);
export { Layout };
diff --git a/src/hooks/use-local-storage.ts b/src/hooks/use-local-storage.ts
index 512bff8496..36bd83acc0 100644
--- a/src/hooks/use-local-storage.ts
+++ b/src/hooks/use-local-storage.ts
@@ -2,12 +2,14 @@ import { useLocalStorage as useLibLocalStorage } from 'react-use';
enum LocalStorageKey {
TC_SIGNATURES = 'TC_SIGNATURES',
- WALLET_WELCOME_BANNER = 'WALLET_WELCOME_BANNER'
+ WALLET_WELCOME_BANNER = 'WALLET_WELCOME_BANNER',
+ APP_ALERT_BANNER = 'APP_ALERT_BANNER'
}
type LocalStorageValueTypes = {
[LocalStorageKey.TC_SIGNATURES]: { [account: string]: { version: string; isSigned: boolean } | boolean };
[LocalStorageKey.WALLET_WELCOME_BANNER]: boolean;
+ [LocalStorageKey.APP_ALERT_BANNER]: boolean;
};
type Options =
From b4470736dc6612af74a3fbed65e8d7322228bceb Mon Sep 17 00:00:00 2001
From: tomjeatt <40243778+tomjeatt@users.noreply.github.com>
Date: Wed, 26 Feb 2025 11:26:51 +0000
Subject: [PATCH 2/4] feature: bob x interlay (#1680)
feature: bob x interlay
---
package.json | 1 +
src/App.tsx | 4 +
src/components/Layout/Layout.tsx | 4 +-
src/lib/form/schemas/bob.ts | 20 +++
src/lib/form/schemas/index.ts | 1 +
src/lib/form/validate.ts | 5 +-
src/lib/form/yup.custom.ts | 8 +-
src/pages/BOB/BOB.styles.tsx | 11 ++
src/pages/BOB/BOB.tsx | 202 +++++++++++++++++++++++++++++++
src/pages/BOB/index.tsx | 3 +
src/utils/constants/links.ts | 1 +
yarn.lock | 139 +++++++++++++--------
12 files changed, 342 insertions(+), 57 deletions(-)
create mode 100644 src/lib/form/schemas/bob.ts
create mode 100644 src/pages/BOB/BOB.styles.tsx
create mode 100644 src/pages/BOB/BOB.tsx
create mode 100644 src/pages/BOB/index.tsx
diff --git a/package.json b/package.json
index 11e98093d7..beb7653d2c 100644
--- a/package.json
+++ b/package.json
@@ -81,6 +81,7 @@
"redux": "^4.0.5",
"styled-components": "^5.3.5",
"typescript": "4.3.2",
+ "viem": "^2.21.34",
"web-vitals": "^1.0.1",
"yup": "^0.32.11"
},
diff --git a/src/App.tsx b/src/App.tsx
index 84a8e033ab..02011c9fc1 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -21,6 +21,7 @@ import * as constants from './constants';
import { FeatureFlags, useFeatureFlag } from './hooks/use-feature-flag';
const BTC = React.lazy(() => import(/* webpackChunkName: 'btc' */ '@/pages/BTC'));
+const BOB = React.lazy(() => import(/* webpackChunkName: 'bob' */ '@/pages/BOB'));
const Strategies = React.lazy(() => import(/* webpackChunkName: 'strategies' */ '@/pages/Strategies'));
const Strategy = React.lazy(() => import(/* webpackChunkName: 'strategy' */ '@/pages/Strategies/Strategy'));
const SendAndReceive = React.lazy(() => import(/* webpackChunkName: 'sendAndReceive' */ '@/pages/SendAndReceive'));
@@ -119,6 +120,9 @@ const App = (): JSX.Element => {
+
+
+
{isStrategiesEnabled && (
<>
diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx
index a72286a7c8..b3de158d8d 100644
--- a/src/components/Layout/Layout.tsx
+++ b/src/components/Layout/Layout.tsx
@@ -1,3 +1,5 @@
+import { APP_NAME } from '@/config/relay-chains';
+
import Sidebar from '../../legacy-components/Sidebar';
import Topbar from '../../legacy-components/Topbar';
import { AppAlert } from '../AppAlert';
@@ -10,7 +12,7 @@ interface Props {
const Layout = ({ className, children }: Props): JSX.Element => (
<>
-
+
diff --git a/src/lib/form/schemas/bob.ts b/src/lib/form/schemas/bob.ts
new file mode 100644
index 0000000000..c197b6ffab
--- /dev/null
+++ b/src/lib/form/schemas/bob.ts
@@ -0,0 +1,20 @@
+import i18n from 'i18next';
+
+import yup, { AddressType } from '../yup.custom';
+
+const BOB_RECIPIENT_FIELD = 'bob-destination';
+
+type BobFormData = {
+ [BOB_RECIPIENT_FIELD]?: string;
+};
+
+const bobSchema = (): yup.ObjectSchema =>
+ yup.object().shape({
+ [BOB_RECIPIENT_FIELD]: yup
+ .string()
+ .required(i18n.t('forms.please_enter_your_field', { field: 'recipient' }))
+ .address(AddressType.ETHEREUM)
+ });
+
+export { BOB_RECIPIENT_FIELD, bobSchema };
+export type { BobFormData };
diff --git a/src/lib/form/schemas/index.ts b/src/lib/form/schemas/index.ts
index 06d05adcb3..7965a0b3ad 100644
--- a/src/lib/form/schemas/index.ts
+++ b/src/lib/form/schemas/index.ts
@@ -1,3 +1,4 @@
+export * from './bob';
export * from './btc';
export * from './loans';
export * from './pools';
diff --git a/src/lib/form/validate.ts b/src/lib/form/validate.ts
index 5e1c82adeb..6a523a9aee 100644
--- a/src/lib/form/validate.ts
+++ b/src/lib/form/validate.ts
@@ -1,5 +1,6 @@
import { decodeAddress, encodeAddress } from '@polkadot/keyring';
import { hexToU8a, isHex } from '@polkadot/util';
+import { isAddress } from 'viem';
import { BTC_ADDRESS_REGEX } from '@/constants';
@@ -8,6 +9,8 @@ const btcAddressRegex = new RegExp(BTC_ADDRESS_REGEX);
// TODO: use library instead
const isValidBTCAddress = (address: string): boolean => btcAddressRegex.test(address);
+const isValidEthereumAddress = (address: string): boolean => isAddress(address);
+
const isValidRelayAddress = (address: string): boolean => {
try {
encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address));
@@ -18,4 +21,4 @@ const isValidRelayAddress = (address: string): boolean => {
}
};
-export { isValidBTCAddress, isValidRelayAddress };
+export { isValidBTCAddress, isValidEthereumAddress, isValidRelayAddress };
diff --git a/src/lib/form/yup.custom.ts b/src/lib/form/yup.custom.ts
index b24a1b9af0..649cfd1359 100644
--- a/src/lib/form/yup.custom.ts
+++ b/src/lib/form/yup.custom.ts
@@ -6,7 +6,7 @@ import i18n from 'i18next';
import * as yup from 'yup';
import { AnyObject, Maybe } from 'yup/lib/types';
-import { isValidBTCAddress, isValidRelayAddress } from './validate';
+import { isValidBTCAddress, isValidEthereumAddress, isValidRelayAddress } from './validate';
yup.addMethod(yup.string, 'requiredAmount', function (action: string, customMessage?: string) {
return this.transform((value) => (isNaN(value) ? undefined : value)).test('requiredAmount', (value, ctx) => {
@@ -108,12 +108,14 @@ yup.addMethod(
enum AddressType {
RELAY_CHAIN,
- BTC
+ BTC,
+ ETHEREUM
}
const addressValidationMap = {
[AddressType.RELAY_CHAIN]: isValidRelayAddress,
- [AddressType.BTC]: isValidBTCAddress
+ [AddressType.BTC]: isValidBTCAddress,
+ [AddressType.ETHEREUM]: isValidEthereumAddress
};
yup.addMethod(
diff --git a/src/pages/BOB/BOB.styles.tsx b/src/pages/BOB/BOB.styles.tsx
new file mode 100644
index 0000000000..33efc3bb0a
--- /dev/null
+++ b/src/pages/BOB/BOB.styles.tsx
@@ -0,0 +1,11 @@
+import styled from 'styled-components';
+
+import { Flex } from '@/component-library';
+
+const StyledWrapper = styled(Flex)`
+ max-width: 540px;
+ width: 100%;
+ margin: 0 auto;
+`;
+
+export { StyledWrapper };
diff --git a/src/pages/BOB/BOB.tsx b/src/pages/BOB/BOB.tsx
new file mode 100644
index 0000000000..6c07f092d8
--- /dev/null
+++ b/src/pages/BOB/BOB.tsx
@@ -0,0 +1,202 @@
+import { mergeProps } from '@react-aria/utils';
+import { useEffect, useMemo } from 'react';
+import { useState } from 'react';
+import { withErrorBoundary } from 'react-error-boundary';
+import { useMutation } from 'react-query';
+
+import { Card, Divider, Flex, H1, Input, P, TextLink } from '@/component-library';
+import { AuthCTA, MainContainer } from '@/components';
+import ErrorFallback from '@/legacy-components/ErrorFallback';
+import { useForm } from '@/lib/form';
+import { BOB_RECIPIENT_FIELD, BobFormData, bobSchema } from '@/lib/form/schemas';
+import { KeyringPair, useSubstrateSecureState } from '@/lib/substrate';
+
+import { NotificationToastType, useNotifications } from '../../utils/context/Notifications';
+import { signMessage } from '../../utils/helpers/wallet';
+import { StyledWrapper } from './BOB.styles';
+
+const postSignature = async (account: KeyringPair, ethereumAddress: string) => {
+ const legalText = await fetch(`https://bob-intr-drop.interlay.workers.dev/legaltext`);
+
+ const message = await legalText.text();
+
+ const signerResult = await signMessage(account, message);
+
+ if (!signerResult?.signature) {
+ throw new Error('Failed to sign message');
+ }
+
+ return fetch(`https://bob-intr-drop.interlay.workers.dev/accept`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ accountid: account.address,
+ signature: signerResult?.signature,
+ evmAddress: ethereumAddress
+ })
+ });
+};
+
+const checkAddress = async (address: string) => {
+ // This checks if a given address is eligible for claiming
+ const response = await fetch(`https://bob-intr-drop.interlay.workers.dev/check/${address}`);
+
+ // If an address is not eligible, error code 499 is returned. We check this here
+ // to distinguish address not found from api errors/
+ if (!response.ok && response.status !== 499) {
+ throw new Error('There was an error checking the address');
+ }
+
+ return response.ok;
+};
+
+const BOB = (): JSX.Element => {
+ const [isEligible, setIsEligible] = useState(false);
+
+ const { selectedAccount } = useSubstrateSecureState();
+ const notifications = useNotifications();
+
+ const submitEthereumAddressMutation = useMutation(
+ (variables: { selectedAccount: KeyringPair; ethereumAddress: string }) =>
+ postSignature(variables.selectedAccount, variables.ethereumAddress),
+ {
+ onError: async (_, variables) => {
+ notifications.show(variables.selectedAccount.address, {
+ type: NotificationToastType.STANDARD,
+ props: { variant: 'error', title: 'Something went wrong. Please try again.' }
+ });
+ },
+ onSuccess: async (data, variables) => {
+ // 409 is a success response to indicate that an EVM address has already been
+ // submitted for the signing account so we show the user an error notification.
+ data.status === 409
+ ? notifications.show(variables.selectedAccount.address, {
+ type: NotificationToastType.STANDARD,
+ props: {
+ variant: 'error',
+ title: 'Already submitted',
+ description: 'An EVM address has already been submitted for this account.'
+ }
+ })
+ : notifications.show(variables.selectedAccount.address, {
+ type: NotificationToastType.STANDARD,
+ props: { variant: 'success', title: 'Address submitted' }
+ });
+
+ form.resetForm();
+ }
+ }
+ );
+
+ const initialValues = useMemo(
+ () => ({
+ [BOB_RECIPIENT_FIELD]: ''
+ }),
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ []
+ );
+
+ const handleSubmit = async (values: BobFormData) => {
+ const ethereumAddress = values[BOB_RECIPIENT_FIELD];
+
+ if (!selectedAccount || !ethereumAddress) return;
+
+ submitEthereumAddressMutation.mutate({ selectedAccount, ethereumAddress });
+ };
+
+ const form = useForm({
+ initialValues,
+ validationSchema: bobSchema(),
+ onSubmit: handleSubmit
+ });
+
+ useEffect(() => {
+ if (!selectedAccount?.address) return;
+
+ const setEligibility = async () => {
+ const isAddressValid = await checkAddress(selectedAccount.address);
+
+ setIsEligible(isAddressValid);
+ };
+
+ setEligibility();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [selectedAccount?.address]);
+
+ // Reset mutation on account change
+ useEffect(() => {
+ if (submitEthereumAddressMutation.isLoading && selectedAccount?.address) {
+ submitEthereumAddressMutation.reset();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [selectedAccount?.address]);
+
+ return (
+
+
+
+
+ BOB x Interlay
+
+
+
+ {isEligible ? (
+ <>
+
+
+ Claim your{' '}
+
+ BOB
+ {' '}
+ x Interlay exclusive NFT badge today.
+
+
+ Only original Interlay community members are eligible. Simply submit the EVM address you'd like
+ to receive the NFT and sign the transaction with your Interlay account to prove your community
+ status. We'll let you know in Interlay Discord when the NFT will be available to claim.
+
+ The claim page is only live until [DATE].
+
+
+ >
+ ) : // eslint-disable-next-line no-negated-condition
+ !selectedAccount ? (
+
+ Please connect your wallet
+
+ ) : (
+
+ Sorry, this account is not eligible.
+
+ )}
+
+
+
+
+ );
+};
+
+export default withErrorBoundary(BOB, {
+ FallbackComponent: ErrorFallback,
+ onReset: () => {
+ window.location.reload();
+ }
+});
diff --git a/src/pages/BOB/index.tsx b/src/pages/BOB/index.tsx
new file mode 100644
index 0000000000..d6b5215ce4
--- /dev/null
+++ b/src/pages/BOB/index.tsx
@@ -0,0 +1,3 @@
+import BOB from './BOB';
+
+export default BOB;
diff --git a/src/utils/constants/links.ts b/src/utils/constants/links.ts
index 89a66a3eec..288c7183f3 100644
--- a/src/utils/constants/links.ts
+++ b/src/utils/constants/links.ts
@@ -18,6 +18,7 @@ const URL_PARAMETERS = Object.freeze({
const PAGES = Object.freeze({
HOME: '/',
BTC: '/btc',
+ BOB: '/bob-x-interlay',
STRATEGIES: '/strategies',
STRATEGY: `/strategies/:${URL_PARAMETERS.STRATEGY.TYPE}`,
SEND_AND_RECEIVE: '/send-and-receive',
diff --git a/yarn.lock b/yarn.lock
index db31c24b69..d831ecf47c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -128,6 +128,11 @@
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63"
integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==
+"@adraffy/ens-normalize@^1.10.1":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33"
+ integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==
+
"@ampproject/remapping@^2.2.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
@@ -2603,6 +2608,13 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
+"@noble/curves@1.8.1", "@noble/curves@^1.6.0", "@noble/curves@~1.8.1":
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.1.tgz#19bc3970e205c99e4bdb1c64a4785706bce497ff"
+ integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==
+ dependencies:
+ "@noble/hashes" "1.7.1"
+
"@noble/curves@^1.3.0":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9"
@@ -2625,6 +2637,11 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426"
integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==
+"@noble/hashes@1.7.1", "@noble/hashes@^1.5.0", "@noble/hashes@~1.7.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f"
+ integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==
+
"@noble/secp256k1@1.5.5":
version "1.5.5"
resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.5.5.tgz#315ab5745509d1a8c8e90d0bdf59823ccf9bcfc3"
@@ -6166,6 +6183,28 @@
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1"
integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==
+"@scure/base@~1.2.2", "@scure/base@~1.2.4":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.4.tgz#002eb571a35d69bdb4c214d0995dff76a8dcd2a9"
+ integrity sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==
+
+"@scure/bip32@1.6.2", "@scure/bip32@^1.5.0":
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.2.tgz#093caa94961619927659ed0e711a6e4bf35bffd0"
+ integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==
+ dependencies:
+ "@noble/curves" "~1.8.1"
+ "@noble/hashes" "~1.7.1"
+ "@scure/base" "~1.2.2"
+
+"@scure/bip39@1.5.4", "@scure/bip39@^1.4.0":
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.4.tgz#07fd920423aa671be4540d59bdd344cc1461db51"
+ integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==
+ dependencies:
+ "@noble/hashes" "~1.7.1"
+ "@scure/base" "~1.2.4"
+
"@sinclair/typebox@^0.27.8":
version "0.27.8"
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
@@ -7331,7 +7370,7 @@
dependencies:
mini-svg-data-uri "^1.2.3"
-"@tailwindcss/postcss7-compat@^2.0.3":
+"@tailwindcss/postcss7-compat@^2.0.3", "tailwindcss@npm:@tailwindcss/postcss7-compat":
version "2.2.17"
resolved "https://registry.yarnpkg.com/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz#dc78f3880a2af84163150ff426a39e42b9ae8922"
integrity sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==
@@ -8407,6 +8446,11 @@ abab@^2.0.3, abab@^2.0.5:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
+abitype@1.0.8, abitype@^1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba"
+ integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==
+
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
@@ -12603,16 +12647,16 @@ event-emitter@^0.3.5:
d "1"
es5-ext "~0.10.14"
+eventemitter3@5.0.1, eventemitter3@^5.0.0, eventemitter3@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
+ integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+
eventemitter3@^4.0.0, eventemitter3@^4.0.7:
version "4.0.7"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
-eventemitter3@^5.0.0, eventemitter3@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
- integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
-
events@^3.0.0, events@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
@@ -15120,6 +15164,11 @@ isomorphic-unfetch@^3.1.0:
node-fetch "^2.6.1"
unfetch "^4.2.0"
+isows@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7"
+ integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==
+
issue-parser@6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/issue-parser/-/issue-parser-6.0.0.tgz#b1edd06315d4f2044a9755daf85fdafde9b4014a"
@@ -17477,6 +17526,19 @@ os-tmpdir@~1.0.2:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
+ox@0.6.7:
+ version "0.6.7"
+ resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832"
+ integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==
+ dependencies:
+ "@adraffy/ens-normalize" "^1.10.1"
+ "@noble/curves" "^1.6.0"
+ "@noble/hashes" "^1.5.0"
+ "@scure/bip32" "^1.5.0"
+ "@scure/bip39" "^1.4.0"
+ abitype "^1.0.6"
+ eventemitter3 "5.0.1"
+
p-all@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0"
@@ -21508,47 +21570,6 @@ tailwindcss-pseudo-elements@^1.5.1:
resolved "https://registry.yarnpkg.com/tailwindcss-pseudo-elements/-/tailwindcss-pseudo-elements-1.5.1.tgz#81603ddd96670d0d18bc85dc26c742b2cfe2aa8a"
integrity sha512-B7ABn5MeXWH1aXYSXui+MenSjv8bCd2PVIJEXue/sVKGuPYo3FKfpKzkcNXUUe/wgFTLbpVArlU0rCD6rZYkPg==
-"tailwindcss@npm:@tailwindcss/postcss7-compat":
- version "2.2.17"
- resolved "https://registry.yarnpkg.com/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz#dc78f3880a2af84163150ff426a39e42b9ae8922"
- integrity sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==
- dependencies:
- arg "^5.0.1"
- autoprefixer "^9"
- bytes "^3.0.0"
- chalk "^4.1.2"
- chokidar "^3.5.2"
- color "^4.0.1"
- cosmiconfig "^7.0.1"
- detective "^5.2.0"
- didyoumean "^1.2.2"
- dlv "^1.1.3"
- fast-glob "^3.2.7"
- fs-extra "^10.0.0"
- glob-parent "^6.0.1"
- html-tags "^3.1.0"
- is-color-stop "^1.1.0"
- is-glob "^4.0.1"
- lodash "^4.17.21"
- lodash.topath "^4.5.2"
- modern-normalize "^1.1.0"
- node-emoji "^1.11.0"
- normalize-path "^3.0.0"
- object-hash "^2.2.0"
- postcss "^7"
- postcss-functions "^3"
- postcss-js "^2"
- postcss-load-config "^3.1.0"
- postcss-nested "^4"
- postcss-selector-parser "^6.0.6"
- postcss-value-parser "^4.1.0"
- pretty-hrtime "^1.0.3"
- purgecss "^4.0.3"
- quick-lru "^5.1.1"
- reduce-css-calc "^2.1.8"
- resolve "^1.20.0"
- tmp "^0.2.1"
-
tapable@^1.0.0, tapable@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
@@ -22618,6 +22639,20 @@ vfile@^4.0.0:
unist-util-stringify-position "^2.0.0"
vfile-message "^2.0.0"
+viem@^2.21.34:
+ version "2.23.5"
+ resolved "https://registry.yarnpkg.com/viem/-/viem-2.23.5.tgz#50fb9ea0701d58e6a7a1714ecaa5edfa100bb391"
+ integrity sha512-cUfBHdFQHmBlPW0loFXda0uZcoU+uJw3NRYQRwYgkrpH6PgovH8iuVqDn6t1jZk82zny4wQL54c9dCX2W9kLMg==
+ dependencies:
+ "@noble/curves" "1.8.1"
+ "@noble/hashes" "1.7.1"
+ "@scure/bip32" "1.6.2"
+ "@scure/bip39" "1.5.4"
+ abitype "1.0.8"
+ isows "1.0.6"
+ ox "0.6.7"
+ ws "8.18.0"
+
vm-browserify@^1.0.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
@@ -23344,6 +23379,11 @@ ws@7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
+ws@8.18.0, ws@^8.15.1, ws@^8.16.0, ws@^8.2.3, ws@^8.8.1:
+ version "8.18.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
+ integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
+
ws@^6.2.1:
version "6.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee"
@@ -23356,11 +23396,6 @@ ws@^7.3.1, ws@^7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
-ws@^8.15.1, ws@^8.16.0, ws@^8.2.3, ws@^8.8.1:
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
- integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
-
x-default-browser@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/x-default-browser/-/x-default-browser-0.4.0.tgz#70cf0da85da7c0ab5cb0f15a897f2322a6bdd481"
From 6bb64489b0c3b2ce19b30d2c240c00263952e081 Mon Sep 17 00:00:00 2001
From: Tom Jeatt
Date: Wed, 26 Feb 2025 11:28:13 +0000
Subject: [PATCH 3/4] chore: release v2.41.16
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index beb7653d2c..1fe9fda819 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "interbtc-ui",
- "version": "2.41.15",
+ "version": "2.41.16",
"private": true,
"dependencies": {
"@acala-network/sdk-core": "^4.1.5",
From 0b520a3dd014cd8615e2ec16f8a86c7764bf11f9 Mon Sep 17 00:00:00 2001
From: tomjeatt <40243778+tomjeatt@users.noreply.github.com>
Date: Wed, 26 Feb 2025 11:46:34 +0000
Subject: [PATCH 4/4] Feature flag (#1683)
* chore: feature flag
* chore: copy change
---
src/App.tsx | 9 ++++++---
src/hooks/use-feature-flag.ts | 6 ++++--
src/pages/BOB/BOB.tsx | 11 +++++++----
3 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 02011c9fc1..e3602976d8 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -47,6 +47,7 @@ const App = (): JSX.Element => {
const dispatch = useDispatch();
const isStrategiesEnabled = useFeatureFlag(FeatureFlags.STRATEGIES);
const isOnboardingEnabled = useFeatureFlag(FeatureFlags.ONBOARDING);
+ const isBobXInterlayEnabled = useFeatureFlag(FeatureFlags.BOB_X_INTERLAY);
// Detects if the connected account is a vault operator
const { error: vaultsError } = useQuery, Error>(
@@ -120,9 +121,11 @@ const App = (): JSX.Element => {
-
-
-
+ {isBobXInterlayEnabled && (
+
+
+
+ )}
{isStrategiesEnabled && (
<>
diff --git a/src/hooks/use-feature-flag.ts b/src/hooks/use-feature-flag.ts
index c5d356ac2c..b5702b2617 100644
--- a/src/hooks/use-feature-flag.ts
+++ b/src/hooks/use-feature-flag.ts
@@ -1,13 +1,15 @@
enum FeatureFlags {
STRATEGIES = 'strategies',
GEOBLOCK = 'geoblock',
- ONBOARDING = 'onboarding'
+ ONBOARDING = 'onboarding',
+ BOB_X_INTERLAY = 'bob-x-interlay'
}
const featureFlags: Record = {
[FeatureFlags.STRATEGIES]: process.env.REACT_APP_FEATURE_FLAG_STRATEGIES,
[FeatureFlags.GEOBLOCK]: process.env.REACT_APP_FEATURE_FLAG_GEOBLOCK,
- [FeatureFlags.ONBOARDING]: process.env.REACT_APP_FEATURE_FLAG_ONBOARDING
+ [FeatureFlags.ONBOARDING]: process.env.REACT_APP_FEATURE_FLAG_ONBOARDING,
+ [FeatureFlags.BOB_X_INTERLAY]: process.env.REACT_APP_FEATURE_FLAG_BOB_X_INTERLAY
};
const useFeatureFlag = (feature: FeatureFlags): boolean => featureFlags[feature] === 'enabled';
diff --git a/src/pages/BOB/BOB.tsx b/src/pages/BOB/BOB.tsx
index 6c07f092d8..f390ac68be 100644
--- a/src/pages/BOB/BOB.tsx
+++ b/src/pages/BOB/BOB.tsx
@@ -150,14 +150,17 @@ const BOB = (): JSX.Element => {
BOB
{' '}
- x Interlay exclusive NFT badge today.
+ x Interlay exclusive NFT badge.
Only original Interlay community members are eligible. Simply submit the EVM address you'd like
to receive the NFT and sign the transaction with your Interlay account to prove your community
- status. We'll let you know in Interlay Discord when the NFT will be available to claim.
+ status.
+
+
+ Submit your Ethereum address below to register. We'll let you know in Interlay Discord when the NFT
+ is available to claim.
- The claim page is only live until [DATE].