diff --git a/dapp/.env b/dapp/.env
index 79f9dc9d6..fdb71b35d 100644
--- a/dapp/.env
+++ b/dapp/.env
@@ -26,4 +26,5 @@ VITE_FEATURE_FLAG_XVERSE_WALLET_ENABLED="false"
VITE_FEATURE_FLAG_ACRE_POINTS_ENABLED="true"
VITE_FEATURE_FLAG_TVL_ENABLED="true"
VITE_FEATURE_GATING_DAPP_ENABLED="true"
+VITE_FEATURE_MOBILE_MODE_ENABLED="true"
diff --git a/dapp/index.html b/dapp/index.html
index 606a95c29..b3e328177 100644
--- a/dapp/index.html
+++ b/dapp/index.html
@@ -1,13 +1,33 @@
-
-
-
-
- ACRE
-
-
-
-
-
+
+
+ Acre App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dapp/manifests/ledger-live/ledger-live-manifest-development.json b/dapp/manifests/ledger-live/ledger-live-manifest-development.json
index 649115b55..bffaf7026 100644
--- a/dapp/manifests/ledger-live/ledger-live-manifest-development.json
+++ b/dapp/manifests/ledger-live/ledger-live-manifest-development.json
@@ -2,9 +2,9 @@
"id": "acre-dev",
"name": "Acre [dev]",
"url": "http://localhost:5173/?embed=ledger-live",
- "homepageUrl": "https:/acre.fi/",
+ "homepageUrl": "https://acre.fi/",
"icon": "http://localhost:5173/acre.svg",
- "platforms": "desktop",
+ "platforms": "all",
"apiVersion": "^2.0.0",
"manifestVersion": "2",
"branch": "stable",
@@ -12,10 +12,10 @@
"currencies": ["bitcoin", "bitcoin_testnet"],
"content": {
"shortDescription": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
},
"description": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
}
},
"permissions": [
@@ -23,10 +23,10 @@
"account.list",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
+ "bitcoin.getXPub",
"transaction.signAndBroadcast",
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
- "domains": ["http://*"],
- "type": "walletApp"
+ "domains": ["https://"]
}
diff --git a/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json b/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json
index a24319deb..22f74bbc5 100644
--- a/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json
+++ b/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json
@@ -2,9 +2,9 @@
"id": "acre",
"name": "Acre",
"url": "https://bitcoin.acre.fi/?embed=ledger-live",
- "homepageUrl": "https:/acre.fi/",
+ "homepageUrl": "https://acre.fi/",
"icon": "https://bitcoin.acre.fi/acre.svg",
- "platforms": "desktop",
+ "platforms": "all",
"apiVersion": "^2.0.0",
"manifestVersion": "2",
"branch": "stable",
@@ -12,10 +12,10 @@
"currencies": ["bitcoin", "bitcoin_testnet"],
"content": {
"shortDescription": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
},
"description": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
}
},
"permissions": [
@@ -23,10 +23,10 @@
"account.list",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
+ "bitcoin.getXPub",
"transaction.signAndBroadcast",
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
- "domains": ["http://*"],
- "type": "walletApp"
+ "domains": ["https://"]
}
diff --git a/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json b/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json
index 06dc73564..a6ea2019c 100644
--- a/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json
+++ b/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json
@@ -2,9 +2,9 @@
"id": "acre-testnet",
"name": "Acre [testnet]",
"url": "https://bitcoin.test.acre.fi/?embed=ledger-live",
- "homepageUrl": "https:/acre.fi/",
+ "homepageUrl": "https://acre.fi/",
"icon": "https://bitcoin.test.acre.fi/acre.svg",
- "platforms": "desktop",
+ "platforms": "all",
"apiVersion": "^2.0.0",
"manifestVersion": "2",
"branch": "stable",
@@ -12,10 +12,10 @@
"currencies": ["bitcoin", "bitcoin_testnet"],
"content": {
"shortDescription": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
},
"description": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
}
},
"permissions": [
@@ -23,10 +23,10 @@
"account.list",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
+ "bitcoin.getXPub",
"transaction.signAndBroadcast",
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
- "domains": ["http://*"],
- "type": "walletApp"
+ "domains": ["https://"]
}
diff --git a/dapp/manifests/ledger-live/ledger-manifest-template.json b/dapp/manifests/ledger-live/ledger-manifest-template.json
index 6a4bc80ee..980c407d2 100644
--- a/dapp/manifests/ledger-live/ledger-manifest-template.json
+++ b/dapp/manifests/ledger-live/ledger-manifest-template.json
@@ -2,9 +2,9 @@
"id": "{{id}}",
"name": "{{name}}",
"url": "{{{url}}}?embed=ledger-live",
- "homepageUrl": "https:/acre.fi/",
+ "homepageUrl": "https://acre.fi/",
"icon": "{{{url}}}acre.svg",
- "platforms": "desktop",
+ "platforms": "all",
"apiVersion": "^2.0.0",
"manifestVersion": "2",
"branch": "stable",
@@ -12,10 +12,10 @@
"currencies": ["bitcoin", "bitcoin_testnet"],
"content": {
"shortDescription": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
},
"description": {
- "en": "Bitcoin Liquid Staking"
+ "en": "Bitcoin Rewards Done Right"
}
},
"permissions": [
@@ -23,10 +23,10 @@
"account.list",
"bitcoin.getAddress",
"bitcoin.getPublicKey",
+ "bitcoin.getXPub",
"transaction.signAndBroadcast",
"custom.acre.messageSign",
"custom.acre.transactionSignAndBroadcast"
],
- "domains": ["http://*"],
- "type": "walletApp"
+ "domains": ["https://"]
}
diff --git a/dapp/package.json b/dapp/package.json
index 97601a1a3..b384d7b43 100644
--- a/dapp/package.json
+++ b/dapp/package.json
@@ -23,7 +23,7 @@
"@emotion/styled": "^11.11.0",
"@ledgerhq/wallet-api-acre-module": "0.1.0",
"@ledgerhq/wallet-api-client": "1.6.0",
- "@orangekit/react": "1.0.0-beta.33",
+ "@orangekit/react": "1.0.0-beta.34",
"@orangekit/sign-in-with-wallet": "1.0.0-beta.6",
"@reduxjs/toolkit": "^2.2.0",
"@rehooks/local-storage": "^2.4.5",
diff --git a/dapp/public/meta-image.png b/dapp/public/meta-image.png
new file mode 100644
index 000000000..f2ebebc8e
Binary files /dev/null and b/dapp/public/meta-image.png differ
diff --git a/dapp/src/components/AcrePointsClaimModal.tsx b/dapp/src/components/AcrePointsClaimModal.tsx
index 6efa97ee0..bc3f045af 100644
--- a/dapp/src/components/AcrePointsClaimModal.tsx
+++ b/dapp/src/components/AcrePointsClaimModal.tsx
@@ -162,7 +162,7 @@ function AcrePointsClaimModalBase({
{children}
+ {children}
) : (
children
)
diff --git a/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx b/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx
index 0747fdc8e..8b12b6236 100644
--- a/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx
+++ b/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx
@@ -129,6 +129,11 @@ export default function ConnectWalletButton({
},
onError: (error: OrangeKitError) => {
const errorData = orangeKit.parseOrangeKitConnectionError(error)
+
+ if (errorData === CONNECTION_ERRORS.DEFAULT) {
+ console.error("Failed to connect", error)
+ }
+
setConnectionError(errorData)
},
})
diff --git a/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx b/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx
index e7439d8e4..2e97b59ea 100644
--- a/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx
+++ b/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx
@@ -39,7 +39,7 @@ export default function ConnectWalletErrorAlert(
- {title}
+ {title}
{description}
diff --git a/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx b/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx
index 5f89720f8..ec1a0e651 100644
--- a/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx
+++ b/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx
@@ -46,12 +46,12 @@ export default function ConnectWalletStatusLabel({
return (
-
+
{icon}
{label}
{isError && (
-
+
Rejected by user
diff --git a/dapp/src/components/Footer.tsx b/dapp/src/components/Footer.tsx
index 7a907a5c5..d80161d7f 100644
--- a/dapp/src/components/Footer.tsx
+++ b/dapp/src/components/Footer.tsx
@@ -11,6 +11,7 @@ import {
} from "@chakra-ui/react"
import { EXTERNAL_HREF } from "#/constants"
import { AcreSignIcon, ArrowUpRight } from "#/assets/icons"
+import { useMobileMode } from "#/hooks"
type FooterListItem = Pick
@@ -74,6 +75,9 @@ const getItemsList = (
export default function Footer() {
const styles = useMultiStyleConfig("Footer")
+ const isMobileMode = useMobileMode()
+
+ if (isMobileMode) return null
return (
diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx
index e3424ed1d..fad9aa380 100644
--- a/dapp/src/components/Header/ConnectWallet.tsx
+++ b/dapp/src/components/Header/ConnectWallet.tsx
@@ -5,12 +5,15 @@ import {
HStack,
Icon,
IconButton,
+ Menu,
+ MenuButton,
+ MenuItem,
+ MenuList,
StackDivider,
- Tooltip,
useClipboard,
useMultiStyleConfig,
} from "@chakra-ui/react"
-import { useIsEmbed, useModal, useWallet } from "#/hooks"
+import { useIsEmbed, useMobileMode, useModal, useWallet } from "#/hooks"
import { CurrencyBalance } from "#/components/shared/CurrencyBalance"
import { TextMd } from "#/components/shared/Typography"
import { BitcoinIcon } from "#/assets/icons"
@@ -22,8 +25,11 @@ import {
IconLogout,
IconWallet,
IconUserCode,
+ IconChevronDown,
+ IconChevronUp,
} from "@tabler/icons-react"
import { useMatch } from "react-router-dom"
+import Tooltip from "../shared/Tooltip"
function isChangeAccountFeatureSupported(embeddedApp: string | undefined) {
return referralProgram.isEmbedApp(embeddedApp)
@@ -39,6 +45,7 @@ export default function ConnectWallet() {
size: "lg",
})
const isDashboardPage = useMatch("/dashboard")
+ const isMobile = useMobileMode()
const handleConnectWallet = (isReconnecting: boolean = false) => {
openModal(MODAL_TYPES.CONNECT_WALLET, { isReconnecting })
@@ -62,8 +69,65 @@ export default function ConnectWallet() {
)
}
+ const options = [
+ {
+ id: "Copy",
+ icon: IconCopy,
+ label: hasCopied ? "Address copied" : "Copy Address",
+ onClick: onCopy,
+ isSupported: true,
+ closeOnSelect: false,
+ },
+ {
+ id: "Change account",
+ icon: IconUserCode,
+ label: "Change account",
+ onClick: () => handleConnectWallet(true),
+ isSupported: isChangeAccountFeatureSupported(embeddedApp),
+ closeOnSelect: true,
+ },
+ {
+ id: "Disconnect",
+ icon: IconLogout,
+ label: "Disconnect",
+ onClick: onDisconnect,
+ closeOnSelect: true,
+ isSupported: true,
+ },
+ ]
- return (
+ return isMobile ? (
+
+ {({ isOpen }) => (
+ <>
+ }
+ rightIcon={isOpen ? : }
+ >
+ {truncateAddress(address)}
+
+
+ {options.map(
+ (option) =>
+ option.isSupported && (
+ }
+ onClick={option.onClick}
+ >
+ {option.label}
+
+ ),
+ )}
+
+ >
+ )}
+
+ ) : (
@@ -100,44 +164,26 @@ export default function ConnectWallet() {
spacing={1}
divider={ }
>
-
- }
- px={2}
- boxSize={5}
- onClick={onCopy}
- />
-
-
- {isChangeAccountFeatureSupported(embeddedApp) && (
-
- }
- px={2}
- boxSize={5}
- onClick={() => handleConnectWallet(true)}
- />
-
+ {options.map(
+ (option) =>
+ option.isSupported && (
+
+ }
+ px={2}
+ boxSize={5}
+ onClick={option.onClick}
+ />
+
+ ),
)}
-
-
- }
- px={2}
- boxSize={5}
- onClick={onDisconnect}
- />
-
diff --git a/dapp/src/components/Header/index.tsx b/dapp/src/components/Header/index.tsx
index 8ac5e7ab5..25a48ab7f 100644
--- a/dapp/src/components/Header/index.tsx
+++ b/dapp/src/components/Header/index.tsx
@@ -13,9 +13,9 @@ export default function Header() {
mx="auto"
justify="space-between"
zIndex="header"
- pt={12}
+ pt={{ base: 4, md: 12 }}
pb={{ base: 4, xl: 12 }}
- px={{ base: 10, xl: 30 }}
+ px={{ base: 4, md: "2.5rem", xl: 30 }}
>
diff --git a/dapp/src/components/Layout.tsx b/dapp/src/components/Layout.tsx
index ea34096aa..42bc526a7 100644
--- a/dapp/src/components/Layout.tsx
+++ b/dapp/src/components/Layout.tsx
@@ -10,7 +10,11 @@ import Sidebar from "./Sidebar"
import MobileModeBanner from "./MobileModeBanner"
import Footer from "./Footer"
-const PADDING = "2.5rem" // 40px
+// The padding update should also be done in the Header component and Footer theme as well
+const PADDING = {
+ base: 4,
+ md: "2.5rem", // 40px
+}
const PAGE_MAX_WIDTH: Record = {
standalone: "63rem", // 1008px
"ledger-live": "63rem", // 1008px
@@ -18,9 +22,9 @@ const PAGE_MAX_WIDTH: Record = {
function Layout() {
const isMobileMode = useMobileMode()
- const { embeddedApp } = useIsEmbed()
+ const { isEmbed, embeddedApp } = useIsEmbed()
- if (isMobileMode) return
+ if (!isEmbed && isMobileMode) return
const maxWidth = embeddedApp
? PAGE_MAX_WIDTH[embeddedApp]
@@ -33,10 +37,11 @@ function Layout() {
diff --git a/dapp/src/components/MezoBeehiveModal.tsx b/dapp/src/components/MezoBeehiveModal.tsx
index ccc88a5e0..18ca145d8 100644
--- a/dapp/src/components/MezoBeehiveModal.tsx
+++ b/dapp/src/components/MezoBeehiveModal.tsx
@@ -42,7 +42,7 @@ function MezoBeehiveModalBase() {
-
+
{data && (
diff --git a/dapp/src/components/MobileModeBanner/index.tsx b/dapp/src/components/MobileModeBanner/index.tsx
index e8a0028b4..aefba45dd 100644
--- a/dapp/src/components/MobileModeBanner/index.tsx
+++ b/dapp/src/components/MobileModeBanner/index.tsx
@@ -46,7 +46,7 @@ function MobileModeBanner(props: MobileModeBannerProps) {
>
- Staking is on
+ Acre App is on
desktop!
@@ -92,7 +92,7 @@ function MobileModeBanner(props: MobileModeBannerProps) {
- Staking is live only on desktop for now. We're working with
+ Acre App live only on desktop for now. We're working with
partners to bring it to mobile soon.
diff --git a/dapp/src/components/TransactionModal/ActionFormModal.tsx b/dapp/src/components/TransactionModal/ActionFormModal.tsx
index 53ab0e42b..8c50be64e 100644
--- a/dapp/src/components/TransactionModal/ActionFormModal.tsx
+++ b/dapp/src/components/TransactionModal/ActionFormModal.tsx
@@ -107,7 +107,7 @@ function ActionFormModal({ type }: { type: ActionFlowType }) {
<>
{!isLoading && }
{heading}
-
+
diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx
index c6b6f81af..84c3069b3 100644
--- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx
+++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx
@@ -16,10 +16,10 @@ export default function BuildTransactionModal({
return (
<>
- Building transaction data...
+ Preparing withdrawal transaction...
- We are building your withdrawal data.
+ This may take a few minutes.
Cancel
diff --git a/dapp/src/components/TransactionModal/ResumeModal.tsx b/dapp/src/components/TransactionModal/ResumeModal.tsx
index 16cb45999..3547673dc 100644
--- a/dapp/src/components/TransactionModal/ResumeModal.tsx
+++ b/dapp/src/components/TransactionModal/ResumeModal.tsx
@@ -22,7 +22,7 @@ export default function ResumeModal({ closeModal }: BaseModalProps) {
return (
<>
-
+
Paused
diff --git a/dapp/src/components/TransactionModal/SuccessModal.tsx b/dapp/src/components/TransactionModal/SuccessModal.tsx
index e03d49658..7fa7f8d31 100644
--- a/dapp/src/components/TransactionModal/SuccessModal.tsx
+++ b/dapp/src/components/TransactionModal/SuccessModal.tsx
@@ -32,7 +32,7 @@ export default function SuccessModal({ type }: SuccessModalProps) {
return (
<>
-
+
{ACTION_FLOW_TYPES.UNSTAKE === type
? "Withdrawal initiated!"
: "Deposit received!"}
diff --git a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx
index 4eeb6e702..8c3926d1f 100644
--- a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx
+++ b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx
@@ -10,8 +10,8 @@ import {
ProgressProps,
} from "@chakra-ui/react"
import { AcreSignIcon } from "#/assets/icons"
-import { useActionFlowType, useConnector } from "#/hooks"
-import { ACTION_FLOW_TYPES } from "#/types"
+import { useActionFlowType, useConnector, useIsEmbed } from "#/hooks"
+import { ACTION_FLOW_TYPES, DappMode } from "#/types"
import { Alert, AlertIcon } from "../shared/Alert"
import { TextMd } from "../shared/Typography"
@@ -22,11 +22,16 @@ const ICON_STYLES = {
type WalletInteractionStep = "opening-wallet" | "awaiting-transaction"
+const CONTENT_BY_DAPP_MODE: Record = {
+ standalone: "wallet",
+ "ledger-live": "Ledger Device",
+}
+
const DATA: Record<
WalletInteractionStep,
{
header: string
- description: (action: string) => string
+ description: (action: string, mode: DappMode) => string
progressProps?: ProgressProps
}
> = {
@@ -37,7 +42,8 @@ const DATA: Record<
},
"awaiting-transaction": {
header: "Awaiting signature confirmation",
- description: () => "Waiting for your wallet to confirm the transaction.",
+ description: (_, mode: DappMode) =>
+ `Communicating with your ${CONTENT_BY_DAPP_MODE[mode]}...`,
progressProps: { transform: "scaleX(-1)" },
},
}
@@ -52,11 +58,12 @@ export default function WalletInteractionModal({
const actionType = useActionFlowType()
const connector = useConnector()
const { header, description, progressProps } = DATA[step]
+ const { embeddedApp } = useIsEmbed()
return (
<>
{step === "opening-wallet" && }
-
+
{header}
@@ -80,6 +87,7 @@ export default function WalletInteractionModal({
{description(
actionType === ACTION_FLOW_TYPES.STAKE ? "deposit" : "withdraw",
+ embeddedApp ?? "standalone",
)}
{step === "awaiting-transaction" && (
@@ -87,7 +95,6 @@ export default function WalletInteractionModal({
This may take up to a minute.
- Don't close this window.
)}
diff --git a/dapp/src/components/TransactionModal/index.tsx b/dapp/src/components/TransactionModal/index.tsx
index 68add35cc..dd30a73ad 100644
--- a/dapp/src/components/TransactionModal/index.tsx
+++ b/dapp/src/components/TransactionModal/index.tsx
@@ -4,7 +4,6 @@ import {
useAppDispatch,
useFetchActivities,
useIsSignedMessage,
- useSidebar,
useTransactionModal,
} from "#/hooks"
import { ActionFlowType, BaseModalProps } from "#/types"
@@ -18,7 +17,6 @@ import { ConnectWalletModalBase } from "../ConnectWalletModal"
type TransactionModalProps = { type: ActionFlowType } & BaseModalProps
function TransactionModalBase({ type, closeModal }: TransactionModalProps) {
- const { onOpen: openSideBar, onClose: closeSidebar } = useSidebar()
const dispatch = useAppDispatch()
const fetchActivities = useFetchActivities()
@@ -34,11 +32,6 @@ function TransactionModalBase({ type, closeModal }: TransactionModalProps) {
}
}, [dispatch, fetchActivities])
- useEffect(() => {
- openSideBar()
- return () => closeSidebar()
- }, [closeSidebar, openSideBar])
-
return (
diff --git a/dapp/src/components/WelcomeModal.tsx b/dapp/src/components/WelcomeModal.tsx
index d40d0bc75..b68a6ce75 100644
--- a/dapp/src/components/WelcomeModal.tsx
+++ b/dapp/src/components/WelcomeModal.tsx
@@ -17,7 +17,7 @@ import {
import { H3, TextSm } from "#/components/shared/Typography"
import { BaseModalProps, DappMode } from "#/types"
import { EmbedApp } from "#/utils/referralProgram"
-import { useIsEmbed } from "#/hooks"
+import { useIsEmbed, useMobileMode } from "#/hooks"
import withBaseModal from "./ModalRoot/withBaseModal"
import step1Video from "../assets/videos/welcome-steps/welcome-step-1.mp4"
import step2Video from "../assets/videos/welcome-steps/welcome-step-2.mp4"
@@ -122,6 +122,7 @@ function WelcomeModalBase({ closeModal }: BaseModalProps) {
count: steps.length,
}) as UseStepsReturn & { goToNext: () => void }
const { embeddedApp } = useIsEmbed()
+ const isMobileMode = useMobileMode()
const isLastStep = activeStep + 1 === steps.length
const activeStepData = steps[activeStep]
@@ -130,19 +131,19 @@ function WelcomeModalBase({ closeModal }: BaseModalProps) {
-
+
Welcome to Acre,
{activeStepData.title}
-
+
{activeStepData.content(embeddedApp)}
{steps.map((step) => (
@@ -159,19 +160,21 @@ function WelcomeModalBase({ closeModal }: BaseModalProps) {
-
+ {!isMobileMode && (
+
+ )}
)
}
diff --git a/dapp/src/components/shared/CurrencyBalance/index.tsx b/dapp/src/components/shared/CurrencyBalance/index.tsx
index 87dede894..bf7f65750 100644
--- a/dapp/src/components/shared/CurrencyBalance/index.tsx
+++ b/dapp/src/components/shared/CurrencyBalance/index.tsx
@@ -4,7 +4,6 @@ import {
useMultiStyleConfig,
TextProps,
ResponsiveValue,
- Tooltip,
} from "@chakra-ui/react"
import {
fixedPointNumberToString,
@@ -13,6 +12,7 @@ import {
numberToLocaleString,
} from "#/utils"
import { CurrencyType, AmountType } from "#/types"
+import Tooltip from "../Tooltip"
export type CurrencyBalanceProps = {
currency: CurrencyType
diff --git a/dapp/src/components/shared/InfoTooltip.tsx b/dapp/src/components/shared/InfoTooltip.tsx
index 2f7731fa6..a9394b460 100644
--- a/dapp/src/components/shared/InfoTooltip.tsx
+++ b/dapp/src/components/shared/InfoTooltip.tsx
@@ -1,6 +1,7 @@
import React from "react"
import { IconInfoCircleFilled } from "@tabler/icons-react"
-import { Icon, Tooltip, TooltipProps } from "@chakra-ui/react"
+import { Icon, TooltipProps } from "@chakra-ui/react"
+import Tooltip from "./Tooltip"
// TODO: Define in the new color palette
const ICON_COLOR = "#3A3328"
diff --git a/dapp/src/components/shared/TokenAmountForm/TokenAmountFormBase.tsx b/dapp/src/components/shared/TokenAmountForm/TokenAmountFormBase.tsx
index 959d38ae0..5f3b10b25 100644
--- a/dapp/src/components/shared/TokenAmountForm/TokenAmountFormBase.tsx
+++ b/dapp/src/components/shared/TokenAmountForm/TokenAmountFormBase.tsx
@@ -42,6 +42,7 @@ export default function TokenAmountFormBase({
withMaxButton={withMaxButton}
defaultAmount={defaultAmount}
autoFocus
+ autoComplete="off"
/>
{children}
diff --git a/dapp/src/components/shared/TokenAmountForm/index.tsx b/dapp/src/components/shared/TokenAmountForm/index.tsx
index b3b157fec..a1360ed8e 100644
--- a/dapp/src/components/shared/TokenAmountForm/index.tsx
+++ b/dapp/src/components/shared/TokenAmountForm/index.tsx
@@ -36,7 +36,7 @@ const TokenAmountForm = withFormik(
handleSubmit: (values, { props }) => {
props.onSubmitForm(values)
},
- validateOnBlur: true,
+ validateOnBlur: false,
validateOnChange: false,
},
)(TokenAmountFormBase)
diff --git a/dapp/src/components/shared/Tooltip.tsx b/dapp/src/components/shared/Tooltip.tsx
new file mode 100644
index 000000000..924e0e950
--- /dev/null
+++ b/dapp/src/components/shared/Tooltip.tsx
@@ -0,0 +1,19 @@
+import React, { useState } from "react"
+import { Box, Tooltip as ChakraTooltip, TooltipProps } from "@chakra-ui/react"
+
+export default function Tooltip(props: TooltipProps) {
+ const { children, ...restProps } = props
+ const [isOpen, setIsOpen] = useState(false)
+
+ return (
+
+ setIsOpen(true)}
+ onMouseLeave={() => setIsOpen(false)}
+ onClick={() => setIsOpen(true)}
+ >
+ {children}
+
+
+ )
+}
diff --git a/dapp/src/constants/featureFlags.ts b/dapp/src/constants/featureFlags.ts
index 2d2062a9e..ddc1ef2ee 100644
--- a/dapp/src/constants/featureFlags.ts
+++ b/dapp/src/constants/featureFlags.ts
@@ -18,6 +18,9 @@ const TVL_ENABLED = import.meta.env.VITE_FEATURE_FLAG_TVL_ENABLED === "true"
const GATING_DAPP_ENABLED =
import.meta.env.VITE_FEATURE_GATING_DAPP_ENABLED === "true"
+const MOBILE_MODE_ENABLED =
+ import.meta.env.VITE_FEATURE_MOBILE_MODE_ENABLED === "true"
+
const featureFlags = {
GAMIFICATION_ENABLED,
OKX_WALLET_ENABLED,
@@ -26,6 +29,7 @@ const featureFlags = {
ACRE_POINTS_ENABLED,
TVL_ENABLED,
GATING_DAPP_ENABLED,
+ MOBILE_MODE_ENABLED,
}
export default featureFlags
diff --git a/dapp/src/constants/screen.ts b/dapp/src/constants/screen.ts
index 70538bd61..c57950789 100644
--- a/dapp/src/constants/screen.ts
+++ b/dapp/src/constants/screen.ts
@@ -1,3 +1,3 @@
-const MAX_MOBILE_SCREEN_WIDTH = "1023px"
+const MAX_MOBILE_SCREEN_WIDTH = "600px"
export default { MAX_MOBILE_SCREEN_WIDTH }
diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts
index 0f3213d35..db36d2455 100644
--- a/dapp/src/hooks/index.ts
+++ b/dapp/src/hooks/index.ts
@@ -27,7 +27,6 @@ export { default as useMobileMode } from "./useMobileMode"
export { default as useBitcoinRecoveryAddress } from "./useBitcoinRecoveryAddress"
export { default as useIsFetchedWalletData } from "./useIsFetchedWalletData"
export { default as useLocalStorage } from "./useLocalStorage"
-export { default as useDetectReferral } from "./useDetectReferral"
export { default as useReferral } from "./useReferral"
export { default as useMats } from "./useMats"
export { default as useIsEmbed } from "./useIsEmbed"
diff --git a/dapp/src/hooks/useDetectReferral.ts b/dapp/src/hooks/useDetectReferral.ts
deleted file mode 100644
index e32a457b6..000000000
--- a/dapp/src/hooks/useDetectReferral.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { useEffect } from "react"
-import useReferral from "./useReferral"
-
-export default function useDetectReferral() {
- const { detectReferral } = useReferral()
-
- useEffect(() => {
- detectReferral()
- }, [detectReferral])
-}
diff --git a/dapp/src/hooks/useInitApp.ts b/dapp/src/hooks/useInitApp.ts
index e87e8955a..caf792595 100644
--- a/dapp/src/hooks/useInitApp.ts
+++ b/dapp/src/hooks/useInitApp.ts
@@ -4,7 +4,6 @@ import { useAccountsChangedOKX } from "./orangeKit/useAccountsChangedOKX"
import { useInitDataFromSdk, useInitializeAcreSdk } from "./sdk"
import { useSentry } from "./sentry"
import useDetectEmbed from "./useDetectEmbed"
-import useDetectReferral from "./useDetectReferral"
import { useDisconnectWallet } from "./useDisconnectWallet"
import { useFetchBTCPriceUSD } from "./useFetchBTCPriceUSD"
@@ -13,7 +12,6 @@ export function useInitApp() {
// useDetectThemeMode()
useSentry()
useDetectEmbed()
- useDetectReferral()
useInitializeAcreSdk()
useInitDataFromSdk()
useFetchBTCPriceUSD()
diff --git a/dapp/src/hooks/useLocalStorage.ts b/dapp/src/hooks/useLocalStorage.ts
index d3d03e990..73272cecd 100644
--- a/dapp/src/hooks/useLocalStorage.ts
+++ b/dapp/src/hooks/useLocalStorage.ts
@@ -1,4 +1,7 @@
-import { useLocalStorage as useRehooksLocalStorage } from "@rehooks/local-storage"
+import {
+ useLocalStorage as useRehooksLocalStorage,
+ writeStorage,
+} from "@rehooks/local-storage"
export const parseLocalStorageValue = (value: string | null | undefined) => {
if (
@@ -12,6 +15,8 @@ export const parseLocalStorageValue = (value: string | null | undefined) => {
return value
}
+export { writeStorage }
+
export const getLocalStorageItem = (key: string): string | undefined => {
const value = localStorage.getItem(key)
return parseLocalStorageValue(value)
diff --git a/dapp/src/hooks/useMobileMode.ts b/dapp/src/hooks/useMobileMode.ts
index 25a491c1d..07e7de6a1 100644
--- a/dapp/src/hooks/useMobileMode.ts
+++ b/dapp/src/hooks/useMobileMode.ts
@@ -2,13 +2,11 @@ import { screen } from "#/constants"
import { userAgent as userAgentUtils } from "#/utils"
import { useMediaQuery } from "@chakra-ui/react"
import { useMemo } from "react"
-import useIsEmbed from "./useIsEmbed"
const { MAX_MOBILE_SCREEN_WIDTH } = screen
const { getDeviceDetect } = userAgentUtils
const useMobileMode = () => {
- const { isEmbed } = useIsEmbed()
const [isMobileScreen] = useMediaQuery(
`(max-width: ${MAX_MOBILE_SCREEN_WIDTH})`,
)
@@ -30,7 +28,7 @@ const useMobileMode = () => {
return isMobileDevice()
}, [isMobileScreen])
- return !isEmbed && isMobile
+ return isMobile
}
export default useMobileMode
diff --git a/dapp/src/hooks/useReferral.ts b/dapp/src/hooks/useReferral.ts
index d919850e9..4e6f7566c 100644
--- a/dapp/src/hooks/useReferral.ts
+++ b/dapp/src/hooks/useReferral.ts
@@ -1,52 +1,23 @@
import { env } from "#/constants"
-import { referralProgram } from "#/utils"
-
import { useCallback, useMemo } from "react"
-import { MODAL_TYPES } from "#/types"
-import useIsEmbed from "./useIsEmbed"
-import useLocalStorage from "./useLocalStorage"
-import { useModal } from "./useModal"
+import useLocalStorage, { writeStorage } from "./useLocalStorage"
type UseReferralReturn = {
referral: number | null
- detectReferral: () => void
resetReferral: () => void
}
+const LOCAL_STORAGE_KEY = "acre.referral"
+
+export const writeReferral = (value: string) => {
+ writeStorage(LOCAL_STORAGE_KEY, value)
+}
+
export default function useReferral(): UseReferralReturn {
const [referral, setReferral] = useLocalStorage(
- "acre.referral",
+ LOCAL_STORAGE_KEY,
env.REFERRAL,
)
- const { openModal } = useModal()
- const { isEmbed, embeddedApp } = useIsEmbed()
-
- const detectReferral = useCallback(() => {
- const param = referralProgram.getReferralFromURL()
-
- if (isEmbed && embeddedApp) {
- setReferral(referralProgram.getReferralByEmbeddedApp(embeddedApp))
- return
- }
-
- if (param === null) {
- setReferral(env.REFERRAL)
- return
- }
-
- const convertedReferral = Number(param)
-
- if (referralProgram.isValidReferral(convertedReferral)) {
- setReferral(convertedReferral)
- } else {
- console.error("Incorrect referral")
- setReferral(null)
- openModal(MODAL_TYPES.UNEXPECTED_ERROR, {
- withCloseButton: false,
- closeOnEsc: false,
- })
- }
- }, [isEmbed, embeddedApp, openModal, setReferral])
const resetReferral = useCallback(() => {
setReferral(env.REFERRAL)
@@ -54,10 +25,9 @@ export default function useReferral(): UseReferralReturn {
return useMemo(
() => ({
- detectReferral,
resetReferral,
referral,
}),
- [detectReferral, resetReferral, referral],
+ [resetReferral, referral],
)
}
diff --git a/dapp/src/hooks/useWallet.ts b/dapp/src/hooks/useWallet.ts
index 2786a4472..504b0a453 100644
--- a/dapp/src/hooks/useWallet.ts
+++ b/dapp/src/hooks/useWallet.ts
@@ -8,6 +8,7 @@ import {
useDisconnect,
} from "wagmi"
import { orangeKit } from "#/utils"
+import sentry from "#/sentry"
import {
OnErrorCallback,
OrangeKitConnector,
@@ -75,6 +76,7 @@ export function useWallet(): UseWalletReturn {
dispatch(setAddress(bitcoinAddress))
setAddressInLocalStorage(bitcoinAddress)
+ sentry.setUser(bitcoinAddress)
},
},
})
@@ -86,6 +88,7 @@ export function useWallet(): UseWalletReturn {
dispatch(setAddress(undefined))
removeAddressFromLocalStorage()
resetWalletState()
+ sentry.setUser(undefined)
},
},
})
@@ -124,6 +127,7 @@ export function useWallet(): UseWalletReturn {
dispatch(setAddress(bitcoinAddress))
setAddressInLocalStorage(bitcoinAddress)
+ sentry.setUser(bitcoinAddress)
},
},
queryClient,
diff --git a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx
index d9b8078ab..51c645153 100644
--- a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx
+++ b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx
@@ -33,7 +33,7 @@ export function AcreTVLProgress(props: AcreTVLProgressProps) {
return (
-
+
@@ -59,7 +59,7 @@ export function AcreTVLProgress(props: AcreTVLProgressProps) {
2} />
-
+
)
}
diff --git a/dapp/src/pages/DashboardPage/BeehiveCard.tsx b/dapp/src/pages/DashboardPage/BeehiveCard.tsx
index bba103729..9168d0b5b 100644
--- a/dapp/src/pages/DashboardPage/BeehiveCard.tsx
+++ b/dapp/src/pages/DashboardPage/BeehiveCard.tsx
@@ -42,14 +42,16 @@ export default function BeehiveCard(props: CardProps) {
-
-
-
- Total collected mats from Mezo
-
-
-
-
+
+
+ Total collected mats from Mezo
+
+
+
{data && (
{numberToLocaleString(data.totalMats)}
diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx
index c05c6163a..f5b2e30b4 100644
--- a/dapp/src/pages/DashboardPage/PositionDetails.tsx
+++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx
@@ -6,6 +6,7 @@ import {
useTransactionModal,
useStatistics,
useWallet,
+ useMobileMode,
} from "#/hooks"
import { ACTION_FLOW_TYPES } from "#/types"
import {
@@ -27,7 +28,7 @@ const isWithdrawalFlowEnabled = featureFlags.WITHDRAWALS_ENABLED
const buttonStyles: ButtonProps = {
size: "lg",
flex: 1,
- w: { base: "auto", lg: 40 },
+ w: 40,
fontWeight: "bold",
lineHeight: 6,
px: 7,
@@ -41,17 +42,21 @@ export default function PositionDetails() {
const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE)
const openWithdrawModal = useTransactionModal(ACTION_FLOW_TYPES.UNSTAKE)
const activitiesCount = useAllActivitiesCount()
+ const isMobileMode = useMobileMode()
const { tvl } = useStatistics()
const { isConnected } = useWallet()
+ const isDisabledForMobileMode =
+ isMobileMode && !featureFlags.MOBILE_MODE_ENABLED
+
return (
{/* TODO: Component should be moved to `CardHeader` */}
- Your deposit
+ Your balance
{/* TODO: Uncomment when position will be implemented */}
{/* {positionPercentage && (
-
- Deposit
-
+
+ Deposit
+
+
{isConnected && activitiesCount > 0 && (
-
+
Withdraw
diff --git a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx
index a29242694..b6ed02c49 100644
--- a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx
+++ b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx
@@ -13,7 +13,7 @@ import { displayBlockTimestamp, getActivityTimestamp } from "#/utils"
import { Activity } from "#/types"
import BlockExplorerLink from "#/components/shared/BlockExplorerLink"
import { IconArrowUpRight } from "@tabler/icons-react"
-import { useActivities } from "#/hooks"
+import { useActivities, useMobileMode } from "#/hooks"
import { semanticTokens } from "#/theme/utils"
import EstimatedDuration from "./EstimatedDuration"
@@ -21,9 +21,10 @@ const BLOCK_EXPLORER_CELL_MIN_WIDTH = 16
export default function TransactionTable() {
const activities = useActivities()
+ const isMobileMode = useMobileMode()
return (
-
+
{(pageData: Activity[]) =>
pageData.map((activity) => (
diff --git a/dapp/src/pages/DashboardPage/index.tsx b/dapp/src/pages/DashboardPage/index.tsx
index 6f28092ec..e0fb11bc2 100644
--- a/dapp/src/pages/DashboardPage/index.tsx
+++ b/dapp/src/pages/DashboardPage/index.tsx
@@ -9,28 +9,44 @@ import AcrePointsTemplateCard from "./AcrePointsTemplateCard"
import BeehiveCard from "./BeehiveCard"
import { AcreTVLProgress } from "./AcreTVLProgress"
-const TEMPLATE_AREAS = `
- ${featureFlags.TVL_ENABLED ? '"tvl tvl"' : ""}
- "dashboard acre-points"
- "dashboard beehive"
- "dashboard useful-links"
-`
-
-const GRID_TEMPLATE_ROWS = `${featureFlags.TVL_ENABLED ? "auto" : ""} auto auto 1fr`
-
export default function DashboardPage() {
useTriggerConnectWalletModal()
return (
{featureFlags.TVL_ENABLED && }
@@ -40,12 +56,12 @@ export default function DashboardPage() {
{/* */}
{featureFlags.ACRE_POINTS_ENABLED ? (
-
+
) : (
-
+
)}
-
+
)
}
diff --git a/dapp/src/router/index.tsx b/dapp/src/router/index.tsx
index 9d6a42b0f..351a8504e 100644
--- a/dapp/src/router/index.tsx
+++ b/dapp/src/router/index.tsx
@@ -12,6 +12,8 @@ import AccessPage from "#/pages/AccessPage"
import WelcomePage from "#/pages/WelcomePage"
import welcomePageLoader from "#/pages/WelcomePage/loader"
import accessPageLoader from "#/pages/AccessPage/loader"
+import { writeReferral } from "#/hooks/useReferral"
+import { env } from "#/constants"
import { routerPath } from "./path"
const mainLayoutLoader: LoaderFunction = ({ request }) => {
@@ -32,6 +34,24 @@ export const router = createBrowserRouter([
{
path: "/",
element: ,
+ loader: ({ request }) => {
+ // TODO: display the error page/modal when the referral is invalid.
+ const referralCodeFromUrl = referralProgram.getReferralFromURL()
+
+ const referralCode = referralProgram.isValidReferral(referralCodeFromUrl)
+ ? referralCodeFromUrl!
+ : env.REFERRAL
+
+ writeReferral(referralCode.toString())
+
+ const embedApp = referralProgram.getEmbeddedApp(request.url)
+ if (referralProgram.isEmbedApp(embedApp)) {
+ writeReferral(
+ referralProgram.getReferralByEmbeddedApp(embedApp).toString(),
+ )
+ }
+ return null
+ },
children: [
{
index: true,
diff --git a/dapp/src/sentry.test.ts b/dapp/src/sentry.test.ts
new file mode 100644
index 000000000..7543d8d1d
--- /dev/null
+++ b/dapp/src/sentry.test.ts
@@ -0,0 +1,38 @@
+import { describe, expect, it, vi } from "vitest"
+import * as Sentry from "@sentry/react"
+import sentry from "./sentry"
+
+describe("sentry", () => {
+ describe("setUser", () => {
+ vi.mock("@sentry/react")
+
+ const testCases = [
+ { bitcoinAddress: undefined, expectedResult: null },
+ { bitcoinAddress: "", expectedResult: null },
+ { bitcoinAddress: " ", expectedResult: null },
+ {
+ bitcoinAddress: "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem",
+ expectedResult: { id: "1f520a9757" },
+ },
+ {
+ bitcoinAddress: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
+ expectedResult: { id: "6cd42dab02" },
+ },
+ {
+ bitcoinAddress: "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
+ expectedResult: { id: "6cd42dab02" },
+ },
+ ]
+
+ describe.each(testCases)(
+ "when address is $bitcoinAddress",
+ ({ bitcoinAddress, expectedResult }) => {
+ it("should set expected user in Sentry", () => {
+ sentry.setUser(bitcoinAddress)
+
+ expect(Sentry.setUser).toHaveBeenCalledWith(expectedResult)
+ })
+ },
+ )
+ })
+})
diff --git a/dapp/src/sentry.ts b/dapp/src/sentry.ts
new file mode 100644
index 000000000..f3707ede4
--- /dev/null
+++ b/dapp/src/sentry.ts
@@ -0,0 +1,50 @@
+import * as Sentry from "@sentry/react"
+import { sha256, toUtf8Bytes } from "ethers"
+
+const initialize = (dsn: string) => {
+ Sentry.init({
+ dsn,
+ integrations: [
+ Sentry.browserTracingIntegration(),
+ Sentry.captureConsoleIntegration({ levels: ["error"] }),
+ Sentry.extraErrorDataIntegration(),
+ Sentry.httpClientIntegration(),
+ ],
+ // Attach stacktrace to errors logged by `console.error`. This is useful for
+ // the `captureConsoleIntegration` integration.
+ attachStacktrace: true,
+ // Performance Monitoring
+ tracesSampleRate: 0.1,
+ })
+}
+
+/**
+ * Sets the user in Sentry with an ID from hashed Bitcoin address.
+ * The Bitcoin address is first converted to lowercase and then hashed using SHA-256.
+ * The resulting hash is then converted to a hexadecimal string and the first 10
+ * characters are set as the user ID.
+ *
+ * @param bitcoinAddress - The Bitcoin address of the user. If undefined, the user
+ * is set to null in Sentry.
+ */
+const setUser = (bitcoinAddress: string | undefined) => {
+ if (!bitcoinAddress) {
+ Sentry.setUser(null)
+ return
+ }
+
+ const hashedBitcoinAddress = sha256(toUtf8Bytes(bitcoinAddress.toLowerCase()))
+ // Remove the 0x prefix and take the first 10 characters.
+ const id = hashedBitcoinAddress.slice(2, 12)
+
+ Sentry.setUser({ id })
+}
+
+const captureException = (exception: unknown) =>
+ Sentry.captureException(exception)
+
+export default {
+ initialize,
+ setUser,
+ captureException,
+}
diff --git a/dapp/src/sentry/index.ts b/dapp/src/sentry/index.ts
deleted file mode 100644
index 0bb08159d..000000000
--- a/dapp/src/sentry/index.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as Sentry from "@sentry/react"
-
-const initialize = (dsn: string) => {
- Sentry.init({
- dsn,
- integrations: [
- Sentry.browserTracingIntegration(),
- Sentry.captureConsoleIntegration({ levels: ["error"] }),
- ],
- // Attach stacktrace to errors logged by `console.error`. This is useful for
- // the `captureConsoleIntegration` integration.
- attachStacktrace: true,
- // Performance Monitoring
- tracesSampleRate: 0.1,
- })
-}
-
-const captureException = (exception: unknown) =>
- Sentry.captureException(exception)
-
-export default {
- initialize,
- captureException,
-}
diff --git a/dapp/src/theme/AcreTVLProgress.ts b/dapp/src/theme/AcreTVLProgress.ts
index 622b34263..16d5524bc 100644
--- a/dapp/src/theme/AcreTVLProgress.ts
+++ b/dapp/src/theme/AcreTVLProgress.ts
@@ -27,7 +27,9 @@ const containerStyles = defineStyle({
const wrapperStyles = defineStyle({
px: 5,
py: 6,
- gap: "6.875rem", // 110px
+ display: "flex",
+ flexDirection: { base: "column", sm: "row" },
+ gap: { base: 5, md: "6.875rem" }, // 110px
})
const contentWrapperStyles = defineStyle({
gridAutoFlow: "column",
diff --git a/dapp/src/theme/Footer.ts b/dapp/src/theme/Footer.ts
index 8cf4f3229..3aced57fe 100644
--- a/dapp/src/theme/Footer.ts
+++ b/dapp/src/theme/Footer.ts
@@ -19,7 +19,7 @@ const wrapperStyles = defineStyle({
gap: { base: 4, xl: 10 },
maxW: "120rem", // 1920px
py: 3,
- px: { base: 10, xl: 30 },
+ px: { base: 4, md: "2.5rem", xl: 30 },
mx: "auto",
})
diff --git a/dapp/src/theme/Modal.ts b/dapp/src/theme/Modal.ts
index 7e6f1fc66..bab2047b2 100644
--- a/dapp/src/theme/Modal.ts
+++ b/dapp/src/theme/Modal.ts
@@ -2,23 +2,24 @@ import { modalAnatomy as parts } from "@chakra-ui/anatomy"
import { createMultiStyleConfigHelpers, defineStyle } from "@chakra-ui/react"
const baseStyleContainer = defineStyle({
- px: 8,
+ px: { base: 3, sm: 8 },
})
const baseStyleDialog = defineStyle({
- marginTop: "var(--chakra-space-modal_shift)",
+ marginTop: { base: 12, sm: "var(--chakra-space-modal_shift)" },
marginBottom: 8,
boxShadow: "none",
borderRadius: "xl",
+ p: { base: 5, sm: 0 },
bg: "gold.100",
border: "none",
})
const baseCloseButton = defineStyle({
- top: -7,
- right: -7,
- boxSize: 7,
- rounded: "100%",
+ top: { base: 3, sm: -7 },
+ right: { base: 3, sm: -7 },
+ boxSize: { sm: 7 },
+ rounded: { sm: "100%" },
bg: "opacity.white.5",
_hover: {
@@ -37,8 +38,8 @@ const baseStyleHeader = defineStyle({
fontSize: "xl",
lineHeight: "xl",
fontWeight: "bold",
- pt: 10,
- px: 10,
+ pt: { sm: 10 },
+ px: { sm: 10 },
pb: 8,
})
@@ -50,15 +51,15 @@ const baseStyleBody = defineStyle({
alignItems: "center",
gap: 6,
pt: 0,
- px: 8,
- pb: 10,
+ px: { base: 0, sm: 10 },
+ pb: { base: 0, sm: 10 },
})
const baseStyleFooter = defineStyle({
flexDirection: "column",
gap: 6,
- px: 8,
- pb: 10,
+ px: { base: 0, sm: 8 },
+ pb: { base: 0, sm: 10 },
})
const multiStyleConfig = createMultiStyleConfigHelpers(parts.keys)
diff --git a/dapp/src/utils/activities.ts b/dapp/src/utils/activities.ts
index 7349a985b..a6d1716da 100644
--- a/dapp/src/utils/activities.ts
+++ b/dapp/src/utils/activities.ts
@@ -21,12 +21,31 @@ export function getEstimatedDuration(
amount: bigint,
type: ActivityType,
): string {
+ // Withdrawal duration is related to the tBTC redemption process, which takes
+ // approximately 5 - 7 hours. We use the average value of 6 hours.
if (isWithdrawType(type)) return "6 hours"
- if (amount < MIN_LIMIT_VALUE_DURATION) return "1 hour"
-
- if (amount >= MIN_LIMIT_VALUE_DURATION && amount < MAX_LIMIT_VALUE_DURATION)
- return "2 hours"
-
+ // Deposit duration is related to the tBTC minting process, which varies based
+ // on the amount of BTC deposited.
+ // Each threshold requires a different number of Bitcoin transaction confirmations:
+ // <0.1 BTC: 1 Bitcoin block confirmation (~10 minutes),
+ // >=0.1 BTC and <1 BTC: 3 Bitcoin block confirmations (~30 minutes),
+ // >=1 BTC: 6 Bitcoin block confirmations (~60 minutes).
+ // The duration of the transaction minting process depends on the Bitcoin network
+ // congestion, and the fee paid by the user.
+ //
+ // After the required number of Bitcoin block confirmations, the tBTC optimistic
+ // minting process starts. The optimistic minting process takes approximately
+ // 1 hour to complete.
+ // After optimistic minting is completed, the Acre bots will finalize the deposit
+ // in no more than 10 minutes.
+ //
+ // We round the estimated duration up to the nearest hour.
+ //
+ // For <0.1 BTC estimated duration is around 1 hour 20 minutes.
+ if (amount < MIN_LIMIT_VALUE_DURATION) return "2 hours"
+ // For <1 BTC estimated duration is around 1 hours 40 minutes.
+ if (amount < MAX_LIMIT_VALUE_DURATION) return "2 hours"
+ // For >=1 BTC estimated duration is around 2 hours 10 minutes.
return "3 hours"
}
diff --git a/dapp/src/utils/orangekit/index.ts b/dapp/src/utils/orangekit/index.ts
index 18f355df4..af5317b7c 100644
--- a/dapp/src/utils/orangekit/index.ts
+++ b/dapp/src/utils/orangekit/index.ts
@@ -107,6 +107,33 @@ async function verifySignInWithWalletMessage(
return result.data
}
+/**
+ * Finds the extended public key (xpub) of the user's account from URL. Users
+ * can be redirected to the exact app in the Ledger Live application. One of the
+ * parameters passed via URL is `accountId` - the ID of the user's account in
+ * Ledger Live.
+ * @see https://developers.ledger.com/docs/ledger-live/exchange/earn/liveapp#url-parameters-for-direct-navigation
+ *
+ * @param {string} url Request url
+ * @returns The extended public key (xpub) of the user's account if the search
+ * parameter `accountId` exists in the URL. Otherwise `undefined`.
+ */
+function findXpubFromUrl(url: string): string | undefined {
+ const parsedUrl = new URL(url)
+
+ const accountId = parsedUrl.searchParams.get("accountId")
+
+ if (!accountId) return undefined
+
+ // The fourth value separated by `:` is extended public key. See the
+ // account ID template: `js:2:bitcoin_testnet::`.
+ const xpubFromAccountId = accountId.split(":")[3]
+
+ if (!xpubFromAccountId) return undefined
+
+ return xpubFromAccountId
+}
+
export default {
getWalletInfo,
isWalletInstalled,
@@ -119,4 +146,5 @@ export default {
isWalletConnectionRejectedError,
verifySignInWithWalletMessage,
getOrangeKitLedgerLiveConnector,
+ findXpubFromUrl,
}
diff --git a/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts b/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts
index 7dab9c5ad..316e628a4 100644
--- a/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts
+++ b/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts
@@ -58,9 +58,12 @@ function numberToValidHexString(value: number): string {
return `0x${hex}`
}
-export type AcreLedgerLiveBitcoinProviderOptions = {
- tryConnectToAddress: string | undefined
-}
+export type AcreLedgerLiveBitcoinProviderOptions =
+ | {
+ tryConnectToAddress?: string
+ tryConnectToAccountByXpub?: never
+ }
+ | { tryConnectToAddress?: never; tryConnectToAccountByXpub?: string }
/**
* Ledger Live Wallet API Bitcoin Provider.
@@ -90,6 +93,7 @@ export default class AcreLedgerLiveBitcoinProvider
network: BitcoinNetwork,
options: AcreLedgerLiveBitcoinProviderOptions = {
tryConnectToAddress: undefined,
+ tryConnectToAccountByXpub: undefined,
},
) {
const windowMessageTransport = new WindowMessageTransport()
@@ -115,6 +119,7 @@ export default class AcreLedgerLiveBitcoinProvider
walletApiClient: WalletAPIClient,
options: AcreLedgerLiveBitcoinProviderOptions = {
tryConnectToAddress: undefined,
+ tryConnectToAccountByXpub: undefined,
},
) {
this.#network = network
@@ -140,12 +145,24 @@ export default class AcreLedgerLiveBitcoinProvider
currencyIds,
})
- if (this.#options.tryConnectToAddress) {
+ if (
+ this.#options.tryConnectToAddress ||
+ this.#options.tryConnectToAccountByXpub
+ ) {
for (let i = 0; i < accounts.length; i += 1) {
const acc = accounts[i]
+ if (
+ this.#options.tryConnectToAccountByXpub &&
+ // eslint-disable-next-line no-await-in-loop
+ (await this.#walletApiClient.bitcoin.getXPub(acc.id)) ===
+ this.#options.tryConnectToAccountByXpub
+ ) {
+ this.#account = acc
+ break
+ }
+
// eslint-disable-next-line no-await-in-loop
const address = await this.#getAddress(acc.id)
-
if (address === this.#options.tryConnectToAddress) {
this.#account = acc
break
diff --git a/dapp/src/utils/referralProgram.ts b/dapp/src/utils/referralProgram.ts
index 36f48b9a3..82a3bfbc5 100644
--- a/dapp/src/utils/referralProgram.ts
+++ b/dapp/src/utils/referralProgram.ts
@@ -9,9 +9,23 @@ const EMBEDDED_APP_TO_REFERRAL: Record = {
"ledger-live": 2083,
}
-const isValidReferral = (value: number) => {
- const isInteger = Number.isInteger(value)
- return isInteger && value >= 0 && value <= MAX_UINT16
+const isValidReferral = (value: unknown) => {
+ let valueAsNumber: number | undefined
+
+ if (typeof value === "string") {
+ // Only digits w/o leading zeros.
+ const isNumber = /^(?:[1-9][0-9]*|0)$/.test(value)
+ valueAsNumber = isNumber ? Number(value) : undefined
+ } else if (typeof value === "number") {
+ valueAsNumber = value
+ }
+
+ return (
+ !!valueAsNumber &&
+ Number.isInteger(valueAsNumber) &&
+ valueAsNumber >= 0 &&
+ valueAsNumber <= MAX_UINT16
+ )
}
const getReferralFromURL = () =>
diff --git a/dapp/src/utils/tests/activities.test.ts b/dapp/src/utils/tests/activities.test.ts
new file mode 100644
index 000000000..fcafa84a7
--- /dev/null
+++ b/dapp/src/utils/tests/activities.test.ts
@@ -0,0 +1,52 @@
+import { describe, expect, it } from "vitest"
+import { getEstimatedDuration } from "../activities"
+
+describe("Utils functions for activities", () => {
+ describe("getEstimatedDuration", () => {
+ describe("withdraw", () => {
+ describe.each([
+ // 0.01 BTC
+ { value: 0.01, expectedResult: "6 hours" },
+ // 0.1 BTC
+ { value: 0.1, expectedResult: "6 hours" },
+ // 1 BTC
+ { value: 1, expectedResult: "6 hours" },
+ // 10 BTC
+ { value: 10, expectedResult: "6 hours" },
+ ])("when it is $value BTC", ({ value, expectedResult }) => {
+ it(`should return ${expectedResult}`, () => {
+ expect(getEstimatedDuration(BigInt(value * 1e8), "withdraw")).toEqual(
+ expectedResult,
+ )
+ })
+ })
+ })
+
+ describe("deposit", () => {
+ describe.each([
+ // 0.0001 BTC
+ { value: 0.0001, expectedResult: "2 hours" },
+ // 0.001 BTC
+ { value: 0.001, expectedResult: "2 hours" },
+ // 0.01 BTC
+ { value: 0.01, expectedResult: "2 hours" },
+ // 0.09 BTC
+ { value: 0.09, expectedResult: "2 hours" },
+ // 0.1 BTC
+ { value: 0.1, expectedResult: "2 hours" },
+ // 0.9 BTC
+ { value: 0.9, expectedResult: "2 hours" },
+ // 1 BTC
+ { value: 1, expectedResult: "3 hours" },
+ // 10 BTC
+ { value: 10, expectedResult: "3 hours" },
+ ])("when it is $value BTC", ({ value, expectedResult }) => {
+ it(`should return ${expectedResult}`, () => {
+ expect(getEstimatedDuration(BigInt(value * 1e8), "deposit")).toEqual(
+ expectedResult,
+ )
+ })
+ })
+ })
+ })
+})
diff --git a/dapp/src/vite-env.d.ts b/dapp/src/vite-env.d.ts
index 53f7175b8..564bf6a80 100644
--- a/dapp/src/vite-env.d.ts
+++ b/dapp/src/vite-env.d.ts
@@ -17,6 +17,7 @@ interface ImportMetaEnv {
readonly VITE_SUBGRAPH_API_KEY: string
readonly VITE_LATEST_COMMIT_HASH: string
readonly VITE_ACRE_API_ENDPOINT: string
+ readonly VITE_FEATURE_MOBILE_MODE_ENABLED: string
}
interface ImportMeta {
diff --git a/dapp/src/wagmiConfig.ts b/dapp/src/wagmiConfig.ts
index 19d1cf4e4..972a38fda 100644
--- a/dapp/src/wagmiConfig.ts
+++ b/dapp/src/wagmiConfig.ts
@@ -5,6 +5,7 @@ import { env } from "./constants"
import { getLastUsedBtcAddress } from "./hooks/useLastUsedBtcAddress"
import referralProgram, { EmbedApp } from "./utils/referralProgram"
import { orangeKit } from "./utils"
+import { AcreLedgerLiveBitcoinProviderOptions } from "./utils/orangekit/ledger-live/bitcoin-provider"
const isTestnet = env.USE_TESTNET
const CHAIN_ID = isTestnet ? sepolia.id : mainnet.id
@@ -34,12 +35,19 @@ async function getWagmiConfig() {
let createEmbedConnectorFn
const embeddedApp = referralProgram.getEmbeddedApp()
if (referralProgram.isEmbedApp(embeddedApp)) {
+ const lastUsedBtcAddress = getLastUsedBtcAddress()
+ const xpub = orangeKit.findXpubFromUrl(window.location.href)
+ const ledgerLiveConnectorOptions: AcreLedgerLiveBitcoinProviderOptions =
+ xpub
+ ? { tryConnectToAccountByXpub: xpub }
+ : {
+ tryConnectToAddress: lastUsedBtcAddress,
+ }
+
const orangeKitLedgerLiveConnector =
orangeKit.getOrangeKitLedgerLiveConnector({
...connectorConfig,
- options: {
- tryConnectToAddress: getLastUsedBtcAddress(),
- },
+ options: ledgerLiveConnectorOptions,
})
const embedConnectorsMap: Record<
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cf2c53ac6..53c684f24 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -39,8 +39,8 @@ importers:
specifier: 1.6.0
version: 1.6.0
'@orangekit/react':
- specifier: 1.0.0-beta.33
- version: 1.0.0-beta.33(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
+ specifier: 1.0.0-beta.34
+ version: 1.0.0-beta.34(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
'@orangekit/sign-in-with-wallet':
specifier: 1.0.0-beta.6
version: 1.0.0-beta.6(bech32@2.0.0)(ethers@6.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
@@ -172,8 +172,8 @@ importers:
specifier: 2.5.0-dev.3
version: 2.5.0-dev.3(@keep-network/keep-core@1.8.1-dev.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
'@orangekit/sdk':
- specifier: 1.0.0-beta.18
- version: 1.0.0-beta.18(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
+ specifier: 1.0.0-beta.19
+ version: 1.0.0-beta.19(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
ethers:
specifier: 6.10.0
version: 6.10.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)
@@ -2692,11 +2692,11 @@ packages:
'@orangekit/contracts@1.0.0-beta.3':
resolution: {integrity: sha512-xP1Oz/JzuHypg5DcsHayINhFSL5M/tCmRP/stmNAvjeebXhrKuALKAHWn98H0Mo3QfYYrz8UcltQPeH6+68n6A==}
- '@orangekit/react@1.0.0-beta.33':
- resolution: {integrity: sha512-b5VMFB2tZad86FNdtylwsKaXlXlrSjY9cIMsaJMUh7EEWEoVvtndbCsHrISKbspm7y+S5nNmGlE3WcQvR8RWWw==}
+ '@orangekit/react@1.0.0-beta.34':
+ resolution: {integrity: sha512-/PTfYcu/BU4ssltIuy+AKqbaGzue+MEJHwd7+4aZhXhwJ+/xrYo3mJ1tSwj6K8lAJCl/N25vq7zNJgVgjLK1WQ==}
- '@orangekit/sdk@1.0.0-beta.18':
- resolution: {integrity: sha512-031JkI0F8gdGzj/7sKbJ52k0Xj/E4uwp/O0SWFDCXyZC0vwtjlw3ItAaZz+nIj820b6dSM6pjL+P7um3m9AK3Q==}
+ '@orangekit/sdk@1.0.0-beta.19':
+ resolution: {integrity: sha512-sIqzu3QTb0WkB4Ir4zHX4tP7hf+uZBXX60q/ww6UzwPjoqGL3dOdui59lTZSNygdMbydLE3y9FSNZPNkQvm+gA==}
'@orangekit/sign-in-with-wallet-parser@1.0.0-beta.6':
resolution: {integrity: sha512-Yi6ohSJV4/Ovrq5c7jD+kPE8pZxLhWtFbZjKRwUW8JL60P/tcyT5o0etul0reqcY2iBlIo5aoC2Hh0noRGl86w==}
@@ -3113,6 +3113,10 @@ packages:
peerDependencies:
ethers: 5.4.0
+ '@safe-global/safe-core-sdk-types@4.1.1':
+ resolution: {integrity: sha512-5NIWG7OjV+C5iquux0yPcu8SHUzg1qJXJ/jAQcPwXGTC7ZVsFawnR43/l2Vg9zEwf0RF0xTm3W8DXkaBYORiEQ==}
+ deprecated: 'WARNING: This project has been renamed to @safe-global/types-kit. Please, migrate from @safe-global/safe-core-sdk-types@5.1.0 to @safe-global/types-kit@1.0.0.'
+
'@safe-global/safe-core-sdk-types@5.0.1':
resolution: {integrity: sha512-xIlHZ9kaAIwEhR0OY0i2scdcQyrc0tDJ+eZZ04lhvg81cgYLY1Z5wfJQqazR2plPT1Hz0A9C79jYdUVvzoF/tw==}
@@ -14831,9 +14835,9 @@ snapshots:
transitivePeerDependencies:
- ethers
- '@orangekit/react@1.0.0-beta.33(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)':
+ '@orangekit/react@1.0.0-beta.34(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)':
dependencies:
- '@orangekit/sdk': 1.0.0-beta.18(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
+ '@orangekit/sdk': 1.0.0-beta.19(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
'@rainbow-me/rainbowkit': 2.0.2(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.8.16(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.5.12(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.8.16(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))
ethers: 6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)
react: 18.3.1
@@ -14870,13 +14874,14 @@ snapshots:
- utf-8-validate
- zod
- '@orangekit/sdk@1.0.0-beta.18(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)':
+ '@orangekit/sdk@1.0.0-beta.19(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)':
dependencies:
'@gelatonetwork/relay-sdk': 5.5.6(bufferutil@4.0.8)(utf-8-validate@5.0.10)
'@noble/curves': 1.4.0
'@noble/hashes': 1.4.0
'@orangekit/contracts': 1.0.0-beta.3(ethers@6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))
'@safe-global/protocol-kit': 3.1.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
+ '@safe-global/safe-core-sdk-types': 4.1.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
bitcoinjs-lib: 6.1.5
ethers: 6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)
transitivePeerDependencies:
@@ -15492,6 +15497,18 @@ snapshots:
dependencies:
ethers: 6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)
+ '@safe-global/safe-core-sdk-types@4.1.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)':
+ dependencies:
+ '@safe-global/safe-deployments': 1.37.0
+ ethers: 6.10.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)
+ web3-core: 1.10.4(encoding@0.1.13)
+ web3-utils: 1.10.4
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - supports-color
+ - utf-8-validate
+
'@safe-global/safe-core-sdk-types@5.0.1(typescript@5.4.5)(zod@3.23.8)':
dependencies:
abitype: 1.0.2(typescript@5.4.5)(zod@3.23.8)
diff --git a/sdk/package.json b/sdk/package.json
index 2a79b6f5d..9a67628dc 100644
--- a/sdk/package.json
+++ b/sdk/package.json
@@ -27,7 +27,7 @@
"dependencies": {
"@acre-btc/contracts": "workspace:*",
"@keep-network/tbtc-v2.ts": "2.5.0-dev.3",
- "@orangekit/sdk": "1.0.0-beta.18",
+ "@orangekit/sdk": "1.0.0-beta.19",
"ethers": "6.10.0",
"ethers-v5": "npm:ethers@^5.5.2"
}
diff --git a/sdk/src/acre.ts b/sdk/src/acre.ts
index d1a84eabd..652dc5a25 100644
--- a/sdk/src/acre.ts
+++ b/sdk/src/acre.ts
@@ -85,7 +85,9 @@ class Acre {
const orangeKit = await OrangeKitSdk.init(
Number(ethereumChainId),
ethereumRpcUrl,
- new GelatoTransactionSender(gelatoApiKey),
+ new GelatoTransactionSender(gelatoApiKey, {
+ backoffRetrier: { retries: 7, backoffStepMs: 3000 },
+ }),
)
const contracts = await getEthereumContracts(