diff --git a/package-lock.json b/package-lock.json
index cc26d7b..5a76858 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"@emotion/server": "^11.11.0",
"@ledgerhq/errors": "^6.16.0",
"@ledgerhq/hw-transport": "^6.30.0",
+ "@ledgerhq/hw-transport-web-ble": "^6.29.4",
"@ledgerhq/hw-transport-webhid": "^6.28.0",
"@mantine/core": "^7.1.5",
"@mantine/form": "^7.2.2",
@@ -3350,32 +3351,44 @@
}
},
"node_modules/@ledgerhq/devices": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.2.2.tgz",
- "integrity": "sha512-SKahGA4p0mZ3ovypOJ2wa5mUvUkArE3HBrwWKYf+cRs+t/Licp3OJfhj+DHIxP3AfyH2xR6CFFWECYHeKwGsDQ==",
+ "version": "8.4.4",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.4.4.tgz",
+ "integrity": "sha512-sz/ryhe/R687RHtevIE9RlKaV8kkKykUV4k29e7GAVwzHX1gqG+O75cu1NCJUHLbp3eABV5FdvZejqRUlLis9A==",
"dependencies": {
- "@ledgerhq/errors": "^6.16.3",
+ "@ledgerhq/errors": "^6.19.1",
"@ledgerhq/logs": "^6.12.0",
"rxjs": "^7.8.1",
"semver": "^7.3.5"
}
},
"node_modules/@ledgerhq/errors": {
- "version": "6.16.3",
- "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.16.3.tgz",
- "integrity": "sha512-3w7/SJVXOPa9mpzyll7VKoKnGwDD3BzWgN1Nom8byR40DiQvOKjHX+kKQausCedTHVNBn9euzPCNsftZ9+mxfw=="
+ "version": "6.19.1",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.19.1.tgz",
+ "integrity": "sha512-75yK7Nnit/Gp7gdrJAz0ipp31CCgncRp+evWt6QawQEtQKYEDfGo10QywgrrBBixeRxwnMy1DP6g2oCWRf1bjw=="
},
"node_modules/@ledgerhq/hw-transport": {
- "version": "6.30.5",
- "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.5.tgz",
- "integrity": "sha512-JMl//7BgPBvWxrWyMu82jj6JEYtsQyOyhYtonWNgtxn6KUZWht3gU4gxmLpeIRr+DiS7e50mW7m3GA+EudZmmA==",
+ "version": "6.31.4",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.31.4.tgz",
+ "integrity": "sha512-6c1ir/cXWJm5dCWdq55NPgCJ3UuKuuxRvf//Xs36Bq9BwkV2YaRQhZITAkads83l07NAdR16hkTWqqpwFMaI6A==",
"dependencies": {
- "@ledgerhq/devices": "^8.2.2",
- "@ledgerhq/errors": "^6.16.3",
+ "@ledgerhq/devices": "^8.4.4",
+ "@ledgerhq/errors": "^6.19.1",
"@ledgerhq/logs": "^6.12.0",
"events": "^3.3.0"
}
},
+ "node_modules/@ledgerhq/hw-transport-web-ble": {
+ "version": "6.29.4",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-6.29.4.tgz",
+ "integrity": "sha512-OJyp6CryvyFlg1L9uifo5hYYdDt+WPw8/0ijBixYhYmGvlRz2W6/F2c5rG/zBQWcNnNydPOLjLJM0vR070RfCw==",
+ "dependencies": {
+ "@ledgerhq/devices": "^8.4.4",
+ "@ledgerhq/errors": "^6.19.1",
+ "@ledgerhq/hw-transport": "^6.31.4",
+ "@ledgerhq/logs": "^6.12.0",
+ "rxjs": "^7.8.1"
+ }
+ },
"node_modules/@ledgerhq/hw-transport-webhid": {
"version": "6.28.0",
"resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.28.0.tgz",
diff --git a/package.json b/package.json
index 422503d..f233ba4 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"@emotion/server": "^11.11.0",
"@ledgerhq/errors": "^6.16.0",
"@ledgerhq/hw-transport": "^6.30.0",
+ "@ledgerhq/hw-transport-web-ble": "^6.29.4",
"@ledgerhq/hw-transport-webhid": "^6.28.0",
"@mantine/core": "^7.1.5",
"@mantine/form": "^7.2.2",
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 81354f5..77d2d37 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -67,6 +67,7 @@ const WHITELIST = [
'preview.kasvault.io',
'privatepreview.kasvault.io',
'kasvault.vercel.app',
+ 'bluetooth.kasvault.io',
];
export default function Home() {
@@ -87,7 +88,10 @@ export default function Home() {
}
}
- setIsShowDemo(window.location.hostname !== 'kasvault.io');
+ setIsShowDemo(
+ window.location.hostname === 'preview.kasvault.io' ||
+ window.location.search.includes('demo'),
+ );
}, []);
const smallStyles = width <= 48 * 16 ? { fontSize: '1rem' } : {};
@@ -107,7 +111,23 @@ export default function Home() {
(Replaced with bluetooth in the future)
- ) : null;
+ ) : (
+ {
+ getAppData(navigate, 'bluetooth');
+ }}
+ align='center'
+ >
+
+
+ Connect with Bluetooth
+ ->
+
+
+ Nano X, Stax and Flex
+
+ );
return (
@@ -138,11 +158,11 @@ export default function Home() {
}}
align='center'
>
-
+
Connect with USB ->
-
+
All Ledger devices
diff --git a/src/app/wallet/page.tsx b/src/app/wallet/page.tsx
index 9b962a5..17b684c 100644
--- a/src/app/wallet/page.tsx
+++ b/src/app/wallet/page.tsx
@@ -6,9 +6,10 @@ import {
fetchAddressDetails,
initTransport,
fetchAddressBalance,
+ isLedgerTransportInitialized,
} from '../../lib/ledger';
import { useState, useEffect } from 'react';
-import { Stack, Tabs, Breadcrumbs, Anchor, Button, Center } from '@mantine/core';
+import { Stack, Tabs, Breadcrumbs, Anchor, Button, Center, Modal, Text } from '@mantine/core';
import Header from '../../components/header';
import AddressesTab from './addresses-tab';
import OverviewTab from './overview-tab';
@@ -279,6 +280,7 @@ export default function Dashboard() {
const [enableGenerate, setEnableGenerate] = useState(false);
const [mempoolEntryToReplace, setMempoolEntryToReplace] = useState(null);
const [pendingTxId, setPendingTxId] = useState(null);
+ const [showConnectModal, setShowConnectModal] = useState(false);
const { ref: containerRef, width: containerWidth, height: containerHeight } = useElementSize();
@@ -376,27 +378,32 @@ export default function Dashboard() {
let unloaded = false;
- initTransport(deviceType)
- .then(() => {
- if (!unloaded) {
- setTransportInitialized(true);
-
- return getXPubFromLedger().then((xpub) =>
- setBIP32Base(new KaspaBIP32(xpub.compressedPublicKey, xpub.chainCode)),
- );
- }
+ if (!isLedgerTransportInitialized()) {
+ setShowConnectModal(true);
+ } else {
+ initTransport(deviceType)
+ .then(() => {
+ if (!unloaded) {
+ setTransportInitialized(true);
+
+ return getXPubFromLedger().then((xpub) =>
+ setBIP32Base(new KaspaBIP32(xpub.compressedPublicKey, xpub.chainCode)),
+ );
+ }
- return null;
- })
- .catch((e) => {
- notifications.show({
- title: 'Error',
- color: 'red',
- message: 'Please make sure your device is unlocked and the Kaspa app is open',
- autoClose: false,
+ return null;
+ })
+ .catch((e) => {
+ notifications.show({
+ title: 'Error',
+ color: 'red',
+ message:
+ 'Please make sure your device is unlocked and the Kaspa app is open',
+ autoClose: false,
+ });
+ console.error(e);
});
- console.error(e);
- });
+ }
return () => {
unloaded = true;
@@ -426,7 +433,7 @@ export default function Dashboard() {
return;
}
- if (deviceType === 'usb') {
+ if (deviceType === 'usb' || deviceType === 'bluetooth') {
loadOrScanAddressBatch(bip32base, setAddresses, setRawAddresses, userSettings).finally(
() => {
setEnableGenerate(true);
@@ -455,6 +462,51 @@ export default function Dashboard() {
{breadcrumbs}
+ setShowConnectModal(false)}
+ title={'Connect Ledger Device via ' + deviceType}
+ >
+
+ Please connect your Ledger device and open the Kaspa app.
+
+
+
+