diff --git a/package.json b/package.json
index 5310e2a..fc863ac 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,7 @@
"@vueform/toggle": "^2.1.4",
"@vueuse/core": "^14.2.1",
"@walletconnect/core": "^2.23.5",
- "cashconnect": "^0.0.20",
+ "cashconnect": "0.0.25",
"chota": "^0.9.2",
"electron-store": "^11.0.2",
"mainnet-js": "^3.1.6",
diff --git a/src/components/cashconnect/CCSessions.vue b/src/components/cashconnect/CCSessions.vue
index 17bc344..3af5978 100644
--- a/src/components/cashconnect/CCSessions.vue
+++ b/src/components/cashconnect/CCSessions.vue
@@ -58,7 +58,7 @@
{{ t('addWallet.createNew.hint') }}
diff --git a/src/components/walletOnboarding.vue b/src/components/walletOnboarding.vue
index c556c4b..6ee2601 100644
--- a/src/components/walletOnboarding.vue
+++ b/src/components/walletOnboarding.vue
@@ -175,9 +175,6 @@
{{ walletType === 'hd' ? t('onboarding.walletType.hdDescription') : t('onboarding.walletType.singleDescription') }}
-
- {{ t('onboarding.walletType.hdNote') }}
-
{{ t('onboarding.create.seedPhraseNote') }}
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index 52b1c95..9409f83 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -98,8 +98,7 @@
"single": "Single address",
"hdDescription": "Uses a new address for each transaction. Better privacy, but requires selecting an address when connecting to dApps.",
"singleDescription": "Uses one fixed address for all transactions. All assets in one place, but less private.",
- "singleAddressNote": "Note: Only the first address from your seed phrase will be used. If you've used this seed with other wallets, funds on other addresses won't appear.",
- "hdNote": "Note: CashConnect is currently not supported with HD wallets."
+ "singleAddressNote": "Note: Only the first address from your seed phrase will be used. If you've used this seed with other wallets, funds on other addresses won't appear."
},
"derivationPath": {
"label": "Derivation path:",
@@ -349,8 +348,7 @@
"connectButton": "Connect New dApp",
"errors": {
"invalidUri": "Invalid WalletConnect or CashConnect URI",
- "notValidUri": "Not a valid WalletConnect or CashConnect URI",
- "cashConnectNotSupported": "CashConnect is currently not supported with HD wallets"
+ "notValidUri": "Not a valid WalletConnect or CashConnect URI"
}
},
"history": {
@@ -473,7 +471,6 @@
"bitcoindotcom": "Bitcoin.com wallet"
},
"singleAddressNote": "Note: Only the first address from your seed phrase will be used. If you've used this seed with other wallets, funds on other addresses won't appear.",
- "hdNote": "Note: CashConnect is currently not supported with HD wallets.",
"importButton": "Import"
},
"walletsOverview": {
@@ -716,7 +713,13 @@
"notifications": {
"sessionApproved": "Session approved",
"successfullySignedTransaction": "Successfully signed transaction",
- "networkMismatch": "This Dapp requires wallet to be on {network}. Please navigate to settings and change network to use this Dapp."
+ "networkMismatch": "This Dapp requires wallet to be on {network}. Please navigate to settings and change network to use this Dapp.",
+ "notStarted": "CashConnect is not started.",
+ "privateKeyNotFound": "Private key could not be found for address: {address}",
+ "failedToConvertCashAddr": "Failed to convert CashAddr to Locking Bytecode",
+ "invalidDerivationPath": "Invalid derivation path for CashConnect: expected at least 4 components, got {length}.",
+ "failedToDeriveHdNode": "Failed to derive HDNode from seed",
+ "walletTypeNotSupported": "WalletType not supported: Must be a Single Address (WIF) Wallet or HDWallet."
}
},
"walletConnect": {
diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json
index b3d5122..1e48b0b 100644
--- a/src/i18n/locales/es.json
+++ b/src/i18n/locales/es.json
@@ -98,8 +98,7 @@
"single": "Dirección única",
"hdDescription": "Usa una nueva dirección para cada transacción. Mayor privacidad, pero requiere seleccionar una dirección al conectarse a dApps.",
"singleDescription": "Usa una dirección fija para todas las transacciones. Todos los activos en un solo lugar, pero menos privado.",
- "singleAddressNote": "Nota: Solo se usará la primera dirección de tu frase semilla. Si has usado esta semilla con otras billeteras, los fondos en otras direcciones no aparecerán.",
- "hdNote": "Nota: CashConnect actualmente no es compatible con billeteras HD."
+ "singleAddressNote": "Nota: Solo se usará la primera dirección de tu frase semilla. Si has usado esta semilla con otras billeteras, los fondos en otras direcciones no aparecerán."
},
"derivationPath": {
"label": "Ruta de derivación:",
@@ -349,8 +348,7 @@
"connectButton": "Conectar nueva dApp",
"errors": {
"invalidUri": "URI de WalletConnect o CashConnect inválida",
- "notValidUri": "No es una URI válida de WalletConnect o CashConnect",
- "cashConnectNotSupported": "CashConnect actualmente no es compatible con billeteras HD"
+ "notValidUri": "No es una URI válida de WalletConnect o CashConnect"
}
},
"history": {
@@ -473,7 +471,6 @@
"bitcoindotcom": "Billetera Bitcoin.com"
},
"singleAddressNote": "Nota: Solo se usará la primera dirección de tu frase semilla. Si has usado esta semilla con otras billeteras, los fondos en otras direcciones no aparecerán.",
- "hdNote": "Nota: CashConnect actualmente no es compatible con billeteras HD.",
"importButton": "Importar"
},
"walletsOverview": {
@@ -716,7 +713,13 @@
"notifications": {
"sessionApproved": "Sesión aprobada",
"successfullySignedTransaction": "Transacción firmada exitosamente",
- "networkMismatch": "Esta dApp requiere que la billetera esté en {network}. Por favor navega a configuración y cambia la red para usar esta dApp."
+ "networkMismatch": "Esta dApp requiere que la billetera esté en {network}. Por favor navega a configuración y cambia la red para usar esta dApp.",
+ "notStarted": "CashConnect no está iniciado.",
+ "privateKeyNotFound": "No se pudo encontrar la clave privada para la dirección: {address}",
+ "failedToConvertCashAddr": "Error al convertir CashAddr a Locking Bytecode",
+ "invalidDerivationPath": "Ruta de derivación inválida para CashConnect: se esperaban al menos 4 componentes, se recibieron {length}.",
+ "failedToDeriveHdNode": "Error al derivar el HDNode a partir de la semilla",
+ "walletTypeNotSupported": "Tipo de billetera no compatible: debe ser una billetera de dirección única (WIF) o una HDWallet."
}
},
"walletConnect": {
diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json
index ba975bd..03c5913 100644
--- a/src/i18n/locales/fr.json
+++ b/src/i18n/locales/fr.json
@@ -98,8 +98,7 @@
"single": "Adresse unique",
"hdDescription": "Utilise une nouvelle adresse pour chaque transaction. Meilleure confidentialité, mais nécessite de sélectionner une adresse lors de la connexion aux dApps.",
"singleDescription": "Utilise une seule adresse fixe pour toutes les transactions. Tous les actifs au même endroit, mais moins privé.",
- "singleAddressNote": "Remarque : Seule la première adresse de votre phrase de récupération sera utilisée. Si vous avez utilisé cette phrase avec d'autres portefeuilles, les fonds sur d'autres adresses n'apparaîtront pas.",
- "hdNote": "Remarque : CashConnect n'est actuellement pas pris en charge avec les portefeuilles HD."
+ "singleAddressNote": "Remarque : Seule la première adresse de votre phrase de récupération sera utilisée. Si vous avez utilisé cette phrase avec d'autres portefeuilles, les fonds sur d'autres adresses n'apparaîtront pas."
},
"derivationPath": {
"label": "Chemin de dérivation :",
@@ -349,8 +348,7 @@
"connectButton": "Connecter nouvelle dApp",
"errors": {
"invalidUri": "URI WalletConnect ou CashConnect invalide",
- "notValidUri": "Ce n'est pas une URI WalletConnect ou CashConnect valide",
- "cashConnectNotSupported": "CashConnect n'est actuellement pas pris en charge avec les portefeuilles HD"
+ "notValidUri": "Ce n'est pas une URI WalletConnect ou CashConnect valide"
}
},
"history": {
@@ -473,7 +471,6 @@
"bitcoindotcom": "Portefeuille Bitcoin.com"
},
"singleAddressNote": "Remarque : Seule la première adresse de votre phrase de récupération sera utilisée. Si vous avez utilisé cette phrase avec d'autres portefeuilles, les fonds sur d'autres adresses n'apparaîtront pas.",
- "hdNote": "Remarque : CashConnect n'est actuellement pas pris en charge avec les portefeuilles HD.",
"importButton": "Importer"
},
"walletsOverview": {
@@ -716,7 +713,13 @@
"notifications": {
"sessionApproved": "Session approuvée",
"successfullySignedTransaction": "Transaction signée avec succès",
- "networkMismatch": "Cette dApp nécessite que le portefeuille soit sur {network}. Veuillez aller dans les paramètres et changer de réseau pour utiliser cette dApp."
+ "networkMismatch": "Cette dApp nécessite que le portefeuille soit sur {network}. Veuillez aller dans les paramètres et changer de réseau pour utiliser cette dApp.",
+ "notStarted": "CashConnect n'est pas démarré.",
+ "privateKeyNotFound": "La clé privée est introuvable pour l'adresse : {address}",
+ "failedToConvertCashAddr": "Échec de la conversion de CashAddr en Locking Bytecode",
+ "invalidDerivationPath": "Chemin de dérivation invalide pour CashConnect : au moins 4 composants attendus, {length} reçu(s).",
+ "failedToDeriveHdNode": "Échec de la dérivation du HDNode à partir de la seed",
+ "walletTypeNotSupported": "Type de portefeuille non pris en charge : doit être un portefeuille à adresse unique (WIF) ou un HDWallet."
}
},
"walletConnect": {
diff --git a/src/stores/cashconnectStore.ts b/src/stores/cashconnectStore.ts
index 0f1d3e9..d7cd5e4 100644
--- a/src/stores/cashconnectStore.ts
+++ b/src/stores/cashconnectStore.ts
@@ -8,7 +8,7 @@ import CCSignTransactionDialogVue from "src/components/cashconnect/CCSignTransac
import CCErrorDialogVue from "src/components/cashconnect/CCErrorDialog.vue";
// Import MainnetJs and CashConnect
-import { convert, type Wallet } from "mainnet-js";
+import { convert } from "mainnet-js";
import type { WalletType } from "src/interfaces/interfaces"
import { i18n } from 'src/boot/i18n'
const { t } = i18n.global
@@ -27,6 +27,9 @@ import {
binToHex,
hexToBin,
cashAddressToLockingBytecode,
+ deriveHdPath,
+ deriveSeedFromBip39Mnemonic,
+ deriveHdPrivateNodeFromSeed,
walletTemplateP2pkhNonHd,
} from "@bitauth/libauth";
import { useSettingsStore } from 'src/stores/settingsStore';
@@ -39,10 +42,6 @@ const settingsStore = useSettingsStore()
// Passing in a Ref so it remains reactive (like when changing wallets)
export const useCashconnectStore = (wallet: Ref) => {
const store = defineStore("cashconnectStore", () => {
-
- // Store a state variable to make sure we don't call "start" more than once.
- const isStarted = ref(false);
-
// Auto-approve the following RPC methods.
// NOTE: We hard-code these for now, but they could be customized on a per-Dapp basis in the future.
const autoApprovedMethods = [
@@ -57,10 +56,22 @@ export const useCashconnectStore = (wallet: Ref) => {
const sessions = ref>({});
// The CashConnect Wallet instance.
- const cashConnectWallet = ref(
- new CashConnectWallet(
- // The master private key.
- (wallet.value as Wallet).privateKey,
+ const cashConnectWallet = ref();
+
+ async function start() {
+ // Make sure we don't start CC more than once.
+ // Otherwise, we'll register multiple handlers and end up with multiple dialogs.
+ if (cashConnectWallet.value) {
+ return;
+ }
+
+ // Get the Master Private Key to use for CashConnect.
+ const masterPrivateKey = getMasterPrivateKeyForWallet(wallet.value);
+
+ // Instantiate CashConnect.
+ cashConnectWallet.value = new CashConnectWallet(
+ // The master private key for use with CashConnect.
+ masterPrivateKey,
// Project ID.
walletConnectProjectId,
// Metadata.
@@ -86,21 +97,36 @@ export const useCashconnectStore = (wallet: Ref) => {
},
}
)
- );
-
- async function start() {
- // Make sure we don't start CC more than once.
- // Otherwise, we'll register multiple handlers and end up with multiple dialogs.
- if (isStarted.value) return;
// Start CashConnect (WC Core) service.
await cashConnectWallet.value.start();
+ }
- // Set our state variable so we don't start it again when switching wallets.
- isStarted.value = true;
+ async function stop() {
+ // If already stopped, do nothing.
+ if(!cashConnectWallet.value) {
+ return;
+ }
+
+ // NOTE: This is a bit of a work-around.
+ // When Cashonize resets wallet state, it does a fire-and-forget.
+ // This causes a race-condition whereby CashConnect hasn't finished closing connections yet.
+ // And the `start()` call thinks that the existing instance still exists.
+ const cashConnectPrevInstance = cashConnectWallet.value;
+ cashConnectWallet.value = undefined;
+
+ // Stop the previous instance.
+ await cashConnectPrevInstance.stop();
+
+ // Disconnect all sessions and stop the previous instance.
+ await cashConnectPrevInstance.disconnectAllSessions();
}
async function pair(wcUri: string) {
+ if(!cashConnectWallet.value) {
+ throw new Error(t('cashConnect.notifications.notStarted'));
+ }
+
try {
// Pair with the service.
await cashConnectWallet.value.pair(wcUri);
@@ -109,12 +135,19 @@ export const useCashconnectStore = (wallet: Ref) => {
}
}
+ async function disconnectSession(topicId: string) {
+ if(!cashConnectWallet.value) {
+ return;
+ }
+
+ await cashConnectWallet.value.disconnectSession(topicId);
+ }
+
//-----------------------------------------------------------------------------
// Session Hooks
//-----------------------------------------------------------------------------
- // eslint-disable-next-line @typescript-eslint/require-await
- async function onSessionsUpdated(
+ function onSessionsUpdated(
updatedSessions: Record
) {
sessions.value = updatedSessions;
@@ -165,8 +198,7 @@ export const useCashconnectStore = (wallet: Ref) => {
});
}
- // eslint-disable-next-line @typescript-eslint/require-await
- async function onSessionDelete() {
+ function onSessionDelete() {
console.log("Session deleted");
}
@@ -270,17 +302,30 @@ export const useCashconnectStore = (wallet: Ref) => {
console.error('Failed to reconnect:', error);
}
}
-
- const utxos = await wallet.value.getUtxos();
- const lockingBytecode = cashAddressToLockingBytecode(wallet.value.getDepositAddress());
- if (typeof lockingBytecode === "string") {
- throw new Error("Failed to convert CashAddr to Locking Bytecode");
- }
+ // Get the UTXOs from the wallet.
+ // NOTE: For Mainnet, we need to marry them up with their Private Key later using the wallet's "walletCache".
+ const utxos = await wallet.value.getUtxos();
const transformed = utxos.map((utxo) => {
- let token: Output["token"] | undefined = undefined;
+ // Get the Wallet's Internal Information about this address (we need the Private Key for signing).
+ const walletUTXO = wallet.value.walletCache.get(utxo.address);
+
+ // If the Private Key cannot be retrieved, throw an error.
+ if(!walletUTXO || !('privateKey' in walletUTXO)) {
+ throw new Error(
+ t('cashConnect.notifications.privateKeyNotFound', { address: utxo.address })
+ );
+ }
+
+ // Convert the Address of this UTXO to Locking Bytecode.
+ const lockingBytecode = cashAddressToLockingBytecode(utxo.address);
+ if (typeof lockingBytecode === "string") {
+ throw new Error(t('cashConnect.notifications.failedToConvertCashAddr'));
+ }
+ // If this UTXO has a token, include it.
+ let token: Output["token"] | undefined = undefined;
if (utxo.token) {
token = {
amount: BigInt(utxo.token.amount),
@@ -295,6 +340,7 @@ export const useCashconnectStore = (wallet: Ref) => {
}
}
+ // Return the LibAuth Template.
return {
outpointTransactionHash: hexToBin(utxo.txid),
outpointIndex: utxo.vout,
@@ -307,7 +353,7 @@ export const useCashconnectStore = (wallet: Ref) => {
data: {
keys: {
privateKeys: {
- key: (wallet.value as Wallet).privateKey,
+ key: walletUTXO.privateKey,
},
},
},
@@ -319,20 +365,85 @@ export const useCashconnectStore = (wallet: Ref) => {
return transformed;
}
- // eslint-disable-next-line @typescript-eslint/require-await
- async function getChangeTemplate() {
+ function getChangeTemplate() {
+ // Get the latest deposit address.
+ const changeAddress = wallet.value.getChangeAddress();
+
+ // Get the Private Key for this Change Address.
+ const walletUTXO = wallet.value.walletCache.get(changeAddress);
+
+ // If the Private Key cannot be retrieved, throw an error.
+ if(!walletUTXO || !walletUTXO.privateKey) {
+ throw new Error(
+ t('cashConnect.notifications.privateKeyNotFound', { address: changeAddress })
+ );
+ }
+
+ // Return the Libauth Change Template.
return {
template: walletTemplateP2pkhNonHd,
data: {
keys: {
privateKeys: {
- key: (wallet.value as Wallet).privateKey,
+ key: walletUTXO.privateKey,
},
},
},
};
}
+ //-----------------------------------------------------------------------------
+ // Utils
+ //-----------------------------------------------------------------------------
+
+ function derivationPathToCashConnectPath(derivationPath: string, purpose = 5001) {
+ // Replace the "purpose" in the derivation path with "5001" (CashConnect).
+ const parts = derivationPath.split('/');
+ if (parts.length < 4) {
+ throw new Error(
+ t('cashConnect.notifications.invalidDerivationPath', { length: parts.length })
+ )
+ }
+ parts[1] = `${purpose}'`;
+ return parts.join('/');
+ }
+
+ function getMasterPrivateKeyForWallet(wallet: WalletType) {
+ // If this is a single address (WIF) wallet, we just use the WIF's Private Key.
+ if('privateKey' in wallet) {
+ return wallet.privateKey;
+ }
+
+ // If this is a HD Wallet, we use the Wallet's Derivation Path, but replace the purpose with 5001 (CashConnect).
+ if('mnemonic' in wallet) {
+ // Derive the seed and HDNode from the Wallet's mnemonic.
+ const seed = deriveSeedFromBip39Mnemonic(wallet.mnemonic);
+ const hdNode = deriveHdPrivateNodeFromSeed(seed);
+ if(!hdNode) {
+ throw new Error(
+ t('cashConnect.notifications.failedToDeriveHdNode')
+ );
+ }
+
+ // Take the existing derivation, but set the 'purpose' to 5001 (CashConnectV1).
+ // NOTE: We put CashConnect on its own derivation to improve security and keep it detached from other Wallet UTXOs.
+ // I.e. We deliberately keep CashConnect in the dark about the top-level mnemonic to enhance security.
+ // NOTE: It is important we don't make assumptions (i.e. hard-code the path) here:
+ // If we do this, we could get conflicting CashConnect instances due to the "account" part of the standard derivation paths.
+ const cashConnectPath = derivationPathToCashConnectPath(wallet.derivation);
+
+ // Derive the master key for CashConnect.
+ const masterKeyNode = deriveHdPath(hdNode, cashConnectPath);
+
+ // Return the master private key.
+ return masterKeyNode.privateKey;
+ }
+
+ throw new Error(
+ t('cashConnect.notifications.walletTypeNotSupported')
+ );
+ }
+
//-----------------------------------------------------------------------------
// Expose
//-----------------------------------------------------------------------------
@@ -340,7 +451,9 @@ export const useCashconnectStore = (wallet: Ref) => {
return {
// Methods
start,
+ stop,
pair,
+ disconnectSession,
// Properties
cashConnectWallet,
diff --git a/src/stores/store.ts b/src/stores/store.ts
index 483d31e..d0bc5d5 100644
--- a/src/stores/store.ts
+++ b/src/stores/store.ts
@@ -87,7 +87,7 @@ export const useStore = defineStore('store', () => {
const latestGithubRelease = ref(undefined as undefined | string);
// Computed properties
- const network = computed(() => wallet.value.network == NetworkType.Mainnet ? "mainnet" : "chipnet")
+ const network = computed(() => wallet.value.network == NetworkType.Mainnet ? "mainnet" : "chipnet")
const explorerUrl = computed(() => network.value == "mainnet" ? settingsStore.explorerMainnet : settingsStore.explorerChipnet);
// The wallet computed property, throws if it were to be accessed when _wallet is null
@@ -172,7 +172,7 @@ export const useStore = defineStore('store', () => {
}
// Note: browser forward button won't work correctly with this implementation.
- // popstate can't distinguish back from forward, so forward acts as another back.
+ // popstate can't distinguish back from forward, so forward acts as another back.
addEventListener('popstate', () => {
if (viewStack.length <= 1) return;
viewStack.pop();
@@ -191,12 +191,12 @@ export const useStore = defineStore('store', () => {
if(newWallet.network == NetworkType.Mainnet){
const connectionMainnet = new Connection("mainnet", `wss://${settingsStore.electrumServerMainnet}:50004`)
// @ts-ignore currently no other way to set a specific provider
- newWallet.provider = connectionMainnet.networkProvider as ElectrumNetworkProvider
+ newWallet.provider = connectionMainnet.networkProvider as ElectrumNetworkProvider
}
- if(newWallet.network == NetworkType.Testnet){
+ if(newWallet.network == NetworkType.Testnet){
const connectionChipnet = new Connection("testnet", `wss://${settingsStore.electrumServerChipnet}:50004`)
// @ts-ignore currently no other way to set a specific provider
- newWallet.provider = connectionChipnet.networkProvider as ElectrumNetworkProvider
+ newWallet.provider = connectionChipnet.networkProvider as ElectrumNetworkProvider
}
_wallet.value?.stop().catch(() => {});
_wallet.value = newWallet;
@@ -301,7 +301,7 @@ export const useStore = defineStore('store', () => {
}
} catch (error) {
displayAndLogError(error);
- }
+ }
}
async function setUpWalletSubscriptions(){
@@ -440,7 +440,7 @@ export const useStore = defineStore('store', () => {
// TODO: investigate if disconnecting session this way is properly working
// Call disconnects as fire-and-forget promises
networkChangeCallbacks.forEach((callback) => void callback());
- // clear the networkChangeCallbacks before initialising newWallet
+ // clear the networkChangeCallbacks before initialising newWallet
networkChangeCallbacks = []
// cancel active listeners
@@ -577,12 +577,6 @@ export const useStore = defineStore('store', () => {
}
async function initializeCashConnect() {
- // CashConnect requires a single-address wallet with a private key
- const walletPrivateKey = (_wallet.value as Wallet | null)?.privateKey;
- if (settingsStore.getWalletType(activeWalletName.value) === 'hd' || !walletPrivateKey) {
- isCcInitialized.value = true;
- return;
- }
try{
// Initialize CashConnect.
const cashconnectWallet = useCashconnectStore(_wallet as Ref);
@@ -594,7 +588,7 @@ export const useStore = defineStore('store', () => {
// Setup network change callback to disconnect all sessions.
// NOTE: This must be wrapped, otherwise we don't have the appropriate context.
networkChangeCallbacks.push(async () => {
- await cashconnectWallet.cashConnectWallet.disconnectAllSessions();
+ await cashconnectWallet.stop();
});
// Monitor the wallet for balance changes and notify CashConnect to refresh wallet state.
@@ -604,7 +598,9 @@ export const useStore = defineStore('store', () => {
// Invoke wallet state has changed so that CashConnect can retrieve fresh UTXOs (and token balances).
// fire-and-forget promise
- void cashconnectWallet.cashConnectWallet.walletStateHasChanged(chainIdFormatted);
+ if(cashconnectWallet.cashConnectWallet) {
+ void cashconnectWallet.cashConnectWallet.walletStateHasChanged(chainIdFormatted);
+ }
});
} catch (error) {
console.error("Error initializing CashConnect:", error);
@@ -729,7 +725,7 @@ export const useStore = defineStore('store', () => {
const registries = await fetchNftMetadataFromIndexer(category, commitment, bcmrIndexer.value, bcmrRegistries.value);
bcmrRegistries.value = registries;
}
-
+
function parseNftCommitment(
categoryId: string,
@@ -817,7 +813,7 @@ export const useStore = defineStore('store', () => {
try {
const response = await fetch('https://api.github.com/repos/cashonize/cashonize-wallet/releases/latest');
if (!response.ok) throw new Error('Network response was not ok');
-
+
const releaseData = await response.json();
// Extract the version tag (e.g. 'v0.2.4')
latestGithubRelease.value = releaseData.tag_name;
diff --git a/yarn.lock b/yarn.lock
index 9c53656..959f3f2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2834,10 +2834,10 @@ caniuse-lite@^1.0.30001766:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz#0279c498e862efb067938bba0a0aabafe8d0b730"
integrity sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==
-cashconnect@^0.0.20:
- version "0.0.20"
- resolved "https://registry.yarnpkg.com/cashconnect/-/cashconnect-0.0.20.tgz#067c6ac36ff9da1f0598326faef9e0b641f71180"
- integrity sha512-tdyp+YHuR3qRAt7QzcprB4a7wsZH2alvYDJ5Z4e6IhJaAOteJ5jcIWfB79ZeLLoKNS1WWmRc2shdKuy3ilf96w==
+cashconnect@0.0.25:
+ version "0.0.25"
+ resolved "https://registry.yarnpkg.com/cashconnect/-/cashconnect-0.0.25.tgz#d11a494b3415a9614c33f5893a4a97a3b94e6db1"
+ integrity sha512-D/LIo89iNysaMprGr/vWTciDdWny4F6euhbDLb87QLbUFkDWZOjI5YJ2a62hu0gEmexH9/11AR5ZBvyl5eQD6g==
dependencies:
"@bitauth/libauth" "^3.1.0-next.2"
"@reown/walletkit" "^1.2.10"