-
Your Seed Phrase
+
Your Seed Phrase
Store your seed phrase in a password manager or write it down on paper.
It is the only way to recover your wallet if you lose access to this
@@ -14,7 +14,7 @@
outlined
readonly
autogrow
- class="q-mt-md q-pa-md"
+ class="q-mt-md q-pa-md seed-phrase"
label="Seed Phrase"
dense
>
@@ -26,9 +26,9 @@
outline
rounded
color="primary "
- class="q-mt-md"
+ class="q-mt-lg"
@click="proceed"
- style="font-size: large"
+ style="font-size: 1rem"
>
diff --git a/src/pages/welcome/WelcomeSlide4.vue b/src/pages/welcome/WelcomeSlide4.vue
index 0636402c..1e6fb87e 100644
--- a/src/pages/welcome/WelcomeSlide4.vue
+++ b/src/pages/welcome/WelcomeSlide4.vue
@@ -2,8 +2,8 @@
-
-
Terms and Conditions
+
+
Terms and Conditions
From 3eb9cef53a159b571ba64f3a8083fc9a70c6609c Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 15:14:53 +0100
Subject: [PATCH 03/21] design
---
src/pages/WelcomePage.vue | 60 ++++++++++++++++-------------
src/pages/welcome/WelcomeSlide1.vue | 44 +++++++++++++++++----
src/pages/welcome/WelcomeSlide2.vue | 8 ++--
src/pages/welcome/WelcomeSlide3.vue | 21 +++-------
src/pages/welcome/WelcomeSlide4.vue | 19 ++++-----
src/router/routes.js | 2 +-
6 files changed, 88 insertions(+), 66 deletions(-)
diff --git a/src/pages/WelcomePage.vue b/src/pages/WelcomePage.vue
index fd935ddf..cc46435c 100644
--- a/src/pages/WelcomePage.vue
+++ b/src/pages/WelcomePage.vue
@@ -12,13 +12,7 @@
v-model="welcomeStore.currentSlide"
animated
control-color="primary"
- navigation-visible
- arrows
- prev-icon="arrow_left"
- :next-icon="welcomeStore.canProceed ? 'arrow_right' : 'none'"
- style="height: 100%; width: 100%"
- padding
- @before="onBeforeSlide"
+ class="flex-1"
>
@@ -33,6 +27,23 @@
+
+
+
+
+
@@ -60,27 +71,8 @@ export default {
welcomeStore.initializeWelcome();
});
- const onBeforeSlide = (newSlide, oldSlide) => {
- // Determine the direction of the slide transition
- const isMovingForward = newSlide > oldSlide;
- const isMovingBackward = newSlide < oldSlide;
-
- if (isMovingForward && !welcomeStore.canProceed) {
- // Notify the user that they cannot proceed yet
- $q.notify({
- type: "negative",
- message: "Please complete the current step before proceeding.",
- });
- return false; // Prevent the transition
- }
-
- // Allow the transition
- return true;
- };
-
return {
welcomeStore,
- onBeforeSlide,
};
},
};
@@ -92,4 +84,20 @@ export default {
width: 100%;
margin: 0; /* Align dialog to cover the entire viewport */
}
+
+.q-card {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
+.q-carousel {
+ flex: 1;
+}
+
+.custom-navigation {
+ display: flex;
+ justify-content: space-between;
+ padding: 16px;
+}
diff --git a/src/pages/welcome/WelcomeSlide1.vue b/src/pages/welcome/WelcomeSlide1.vue
index 21f199e6..81409c7d 100644
--- a/src/pages/welcome/WelcomeSlide1.vue
+++ b/src/pages/welcome/WelcomeSlide1.vue
@@ -2,17 +2,45 @@
-
-
Welcome to Cashu
+

+
+
Welcome to Cashu
- Cashu is a simple and secure Bitcoin wallet that uses Ecash technology
- to keep your funds secure and private.
-
-
- To use this wallet, you need to connect to one or more Ecash mints.
- Only use mints that you trust.
+ Cashu.me is a simple and secure Bitcoin wallet that uses Ecash
+ technology to keep your funds secure and private.
+
+
+ This wallet is not affiliated with any mint. To use this wallet, you
+ need to connect to one or more Ecash mints that you trust.
+
+
+ This wallet stores ecash that only you have access to. If you delete
+ your browser data without a seed phrase backup, you will lose your
+ tokens.
+
+
+ This wallet stores ecash that only you have access to. If you delete
+ your browser data without a seed phrase backup, you will lose your
+ tokens.
+
+
+ This wallet is in beta. We hold no responsibility for people losing
+ access to funds. Use at your own risk! This code is open-source and
+ licensed under the MIT license.
+
+
diff --git a/src/pages/welcome/WelcomeSlide2.vue b/src/pages/welcome/WelcomeSlide2.vue
index e034b9aa..14a6797a 100644
--- a/src/pages/welcome/WelcomeSlide2.vue
+++ b/src/pages/welcome/WelcomeSlide2.vue
@@ -2,8 +2,8 @@
-
-
Install PWA
+
+
Install PWA
For the best experience, use this wallet with your device's native web
@@ -12,13 +12,13 @@
Android (Chrome)
1.
- Tap the menu on the top right
+ Tap the menu (top right)
2. Press Add to Home screen
iOS (Safari)
1.
- Tap the share button
+ Tap share (bottom)
2. Press Add to Home screen
diff --git a/src/pages/welcome/WelcomeSlide3.vue b/src/pages/welcome/WelcomeSlide3.vue
index ac1215ed..521c1c1c 100644
--- a/src/pages/welcome/WelcomeSlide3.vue
+++ b/src/pages/welcome/WelcomeSlide3.vue
@@ -3,7 +3,7 @@
-
Your Seed Phrase
+
Your Seed Phrase
Store your seed phrase in a password manager or write it down on paper.
It is the only way to recover your wallet if you lose access to this
@@ -22,21 +22,12 @@
-
-
- I have written it down
-
+ />
diff --git a/src/pages/welcome/WelcomeSlide4.vue b/src/pages/welcome/WelcomeSlide4.vue
index 1e6fb87e..4a6ed2d4 100644
--- a/src/pages/welcome/WelcomeSlide4.vue
+++ b/src/pages/welcome/WelcomeSlide4.vue
@@ -7,7 +7,7 @@
-
@@ -106,4 +96,9 @@ export default {
h2 {
font-weight: bold;
}
+p {
+ font-size: 0.82rem;
+ /* color grey */
+ color: #c6c6c6;
+}
diff --git a/src/router/routes.js b/src/router/routes.js
index c5304147..5760ea7d 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -34,7 +34,7 @@ const routes = [
// Always leave this as last one,
// but you can also remove it
{
- path: "/:catchAll(.*)*",
+ path: "/:pathMatch(.*)*",
component: () => import("src/pages/ErrorNotFound.vue"),
},
];
From 49fee7a076254618a2c7dd3a446eea6844c0659b Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 17:42:58 +0100
Subject: [PATCH 04/21] animations
---
src/components/BalanceView.vue | 8 ++++++++
src/components/SettingsView.vue | 21 ++++++++++++++++++++-
src/css/app.scss | 10 ++++++++++
src/pages/WalletPage.vue | 26 ++++++++++++++------------
src/pages/welcome/WelcomeSlide1.vue | 29 +++++++++++++++--------------
src/pages/welcome/WelcomeSlide2.vue | 18 +++++++++++-------
src/pages/welcome/WelcomeSlide3.vue | 11 +++++++----
src/pages/welcome/WelcomeSlide4.vue | 8 ++++----
8 files changed, 89 insertions(+), 42 deletions(-)
diff --git a/src/components/BalanceView.vue b/src/components/BalanceView.vue
index 1518d9c1..7bc2bb1f 100644
--- a/src/components/BalanceView.vue
+++ b/src/components/BalanceView.vue
@@ -242,3 +242,11 @@ export default defineComponent({
},
});
+
diff --git a/src/components/SettingsView.vue b/src/components/SettingsView.vue
index 6793a7dd..1b6ff706 100644
--- a/src/components/SettingsView.vue
+++ b/src/components/SettingsView.vue
@@ -1072,6 +1072,19 @@
+
+
+
+
+ Show onboarding
+
+ Show the onboarding screen again.
+
+
+
+
@@ -1174,6 +1187,7 @@ import { useProofsStore } from "src/stores/proofs";
import { usePRStore } from "../stores/payment-request";
import { useRestoreStore } from "src/stores/restore";
import { useReceiveTokensStore } from "../stores/receiveTokensStore";
+import { useWelcomeStore } from "src/stores/welcome";
export default defineComponent({
name: "SettingsView",
@@ -1449,6 +1463,11 @@ export default defineComponent({
await this.resetNip46Signer();
await this.generateNPCConnection();
},
+ showOnboarding: function () {
+ const welcomeStore = useWelcomeStore();
+ welcomeStore.resetWelcome();
+ this.$router.push("/welcome");
+ },
nukeWallet: async function () {
// create a backup just in case
await this.getLocalstorageToFile();
@@ -1479,7 +1498,7 @@ export default defineComponent({
});
diff --git a/src/pages/WalletPage.vue b/src/pages/WalletPage.vue
index 52dc3a92..45dc3797 100644
--- a/src/pages/WalletPage.vue
+++ b/src/pages/WalletPage.vue
@@ -545,7 +545,7 @@ export default {
if (event.data.type == "new_tab_opened") {
channel.postMessage({ type: "already_running", senderId: tabId });
} else if (event.data.type == "already_running") {
- window.location.href = "/already-running";
+ this.$router.push("/already-running");
}
};
},
diff --git a/src/pages/WelcomePage.vue b/src/pages/WelcomePage.vue
index cc46435c..63f7aee8 100644
--- a/src/pages/WelcomePage.vue
+++ b/src/pages/WelcomePage.vue
@@ -4,8 +4,10 @@
v-model="welcomeStore.showWelcome"
persistent
transition-show="slide-up"
- transition-hide="slide-down"
+ transition-hide="fadeOut"
full-screen
+ @drop.prevent="dragFile"
+ @dragover.prevent
>
+
+
diff --git a/src/pages/WalletPage.vue b/src/pages/WalletPage.vue
index 45dc3797..7bc2b2e1 100644
--- a/src/pages/WalletPage.vue
+++ b/src/pages/WalletPage.vue
@@ -443,6 +443,9 @@ export default {
this.focusInput("parseDialogInput");
},
showWelcomePage: function () {
+ if (!useWelcomeStore().termsAccepted) {
+ useWelcomeStore().showWelcome = true;
+ }
if (useWelcomeStore().showWelcome) {
this.$router.push("/welcome");
}
diff --git a/src/pages/welcome/WelcomeSlide4.vue b/src/pages/welcome/WelcomeSlide4.vue
index 4a2b8b40..3447802e 100644
--- a/src/pages/welcome/WelcomeSlide4.vue
+++ b/src/pages/welcome/WelcomeSlide4.vue
@@ -13,52 +13,194 @@
margin: 0 auto;
"
>
+ Last Updated: 17.12.2024
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam
- scelerisque aliquam odio et faucibus. Nulla rhoncus feugiat eros quis
- consectetur. Morbi neque ex, condimentum dapibus congue et, vulputate
- ut ligula. Vestibulum sit amet urna turpis. Praesent sit amet
- tristique urna. Nulla facilisi. Pellentesque et mi orci. Pellentesque
- habitant morbi tristique senectus et netus et malesuada fames ac
- turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus
- et ultrices posuere cubilia curae; Nulla facilisi. Donec aliquet,
- tortor nec commodo ultricies, lacus quam interdum libero, et
- pellentesque felis lorem nec dui. Nulla facilisi. Duis aliquet egestas
- purus in blandit. Curabitur vulputate, ligula lacinia scelerisque
- tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu.
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam
- scelerisque aliquam odio et faucibus. Nulla rhoncus feugiat eros quis
- consectetur. Morbi neque ex, condimentum dapibus congue et, vulputate
- ut ligula. Vestibulum sit amet urna turpis. Praesent sit amet
- tristique urna. Nulla facilisi. Pellentesque et mi orci. Pellentesque
- habitant morbi tristique senectus et netus et malesuada fames ac
- turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus
- et ultrices posuere cubilia curae; Nulla facilisi. Donec aliquet,
- tortor nec commodo ultricies, lacus quam interdum libero, et
- pellentesque felis lorem nec dui. Nulla facilisi. Duis aliquet egestas
- purus in blandit. Curabitur vulputate, ligula lacinia scelerisque
- tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu.
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam
- scelerisque aliquam odio et faucibus. Nulla rhoncus feugiat eros quis
- consectetur. Morbi neque ex, condimentum dapibus congue et, vulputate
- ut ligula. Vestibulum sit amet urna turpis. Praesent sit amet
- tristique urna. Nulla facilisi. Pellentesque et mi orci. Pellentesque
- habitant morbi tristique senectus et netus et malesuada fames ac
- turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus
- et ultrices posuere cubilia curae; Nulla facilisi. Donec aliquet,
- tortor nec commodo ultricies, lacus quam interdum libero, et
- pellentesque felis lorem nec dui. Nulla facilisi. Duis aliquet egestas
- purus in blandit. Curabitur vulputate, ligula lacinia scelerisque
- tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu.
-
-
+ IMPORTANT NOTICE: THESE TERMS OF SERVICE CONTAIN AN ARBITRATION
+ PROVISION REQUIRING BINDING ARBITRATION OF DISPUTES AND A WAIVER OF
+ CERTAIN RIGHTS TO A JURY TRIAL. PLEASE READ THESE TERMS OF SERVICE
+ CAREFULLY. IF YOU DO NOT AGREE, DO NOT USE CASHU.ME.
+
+
+ These Terms of Service (these “Terms”) constitute the entire agreement
+ and understanding between you (“you” or “your”) and Cashu.me
+ (“Cashu.me,” “we,” “us,” or “our”) regarding your use of the Cashu.me
+ website and any related applications, software, code, or services
+ (collectively, the “Site” or “Services”). By accessing or using the
+ Site or Services, you acknowledge that you have read, understand, and
+ agree to be bound by these Terms. If you do not agree, do not access
+ or use the Site or Services.
+
+ 1. Nature of the Services
+
+ 1.1 Non-Custodial Web Application: Cashu.me provides
+ a non-custodial web application (“wallet”) that is executed entirely
+ on your device. Our Site merely makes available client-side code
+ implementing the open-source Cashu protocol. We do not run a server
+ that holds your ecash or executes transactions on your behalf.
+
+
+ 1.2 No Control Over Mints: Cashu.me does not issue
+ ecash and does not operate or control any Mint. The choice of any Mint
+ and any transaction or relationship you establish with that Mint is
+ solely between you and that Mint. Cashu.me has no involvement,
+ responsibility, or liability in any such interaction.
+
+
+ 1.3 No Funds Access: At no time does Cashu.me have
+ custody, possession, or control of your ecash. Transactions occur
+ solely by your actions and through your chosen Mint. We do not
+ monitor, verify, or facilitate transfers between you and any Mint or
+ other parties.
+
+ 2. User Responsibilities & Disclaimers
+
+ 2.1 User’s Sole Responsibility: You understand and
+ agree that you use the Site and Services at your own risk and for your
+ own account. You alone are fully responsible for selecting Mints,
+ conducting transactions, and safeguarding your ecash and secret
+ values. Cashu.me is not a party to and disclaims any responsibility
+ for any agreements, terms, or disputes between you and any Mint.
+
+
+ 2.2 No Partnership with Mints: Cashu.me is not
+ affiliated with, endorsed by, or responsible for any Mint. We make no
+ representations, warranties, or guarantees about any Mint’s integrity,
+ legality, liquidity, or functionality. Your relationship with any
+ Mint, including the issuance, redemption, or valuation of ecash, is
+ solely a matter between you and that Mint.
+
+
+ 2.3 Risk of Ecash: Ecash is an experimental,
+ bearer-like digital asset that may not be recognized as money,
+ currency, or a store of value. Anyone with the secret value has
+ control over the ecash. You agree to review and understand all risks
+ disclosed in our Risk Disclosure Statement before using ecash.
+
+ 3. Modifications to Terms
+
+ We may amend or update these Terms at any time without notice. Your
+ continued use of the Site or Services after any modifications
+ constitutes acceptance of the updated Terms. If you do not agree,
+ discontinue your use.
+
+ 4. Compliance with Laws
+
+ Your use of the Site and any Services is void where prohibited by law.
+ You must determine whether your use of ecash and related activities
+ are lawful. You are solely responsible for compliance with all
+ applicable laws, taxes, and regulations.
+
+ 5. License to Use the Site
+
+ Subject to your compliance with these Terms, we grant you a limited,
+ personal, non-exclusive, non-transferable, revocable license to use
+ the Site. We may suspend or terminate your access at our sole
+ discretion.
+
+ 6. Risks and Limitation of Liability
+
+ 6.1
+ No Liability for Interactions with Mints: Cashu.me is
+ not liable for any transactions, disputes, or issues arising from your
+ dealings with Mints.
+
+
+ 6.2 Assumption of Risk: You acknowledge ecash-related
+ activities involve significant risks, including market volatility,
+ theft, and regulatory uncertainty.
+
+
+ 6.3 No Warranties: THE SITE AND SERVICES ARE PROVIDED
+ “AS IS” WITHOUT ANY WARRANTIES. WE DISCLAIM ALL WARRANTIES TO THE
+ MAXIMUM EXTENT PERMITTED BY LAW.
+
+
+ 6.4 Limitation of Liability: TO THE FULLEST EXTENT
+ PERMITTED BY LAW, CASHU.ME IS NOT LIABLE FOR INDIRECT, INCIDENTAL,
+ SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING OUT OF OR RELATED
+ TO THESE TERMS, THE SITE, OR THE SERVICES.
+
+ 7. Indemnification and Release
+
+ You agree to indemnify and hold harmless Cashu.me and its affiliates
+ from claims arising out of your use of the Site or Services. If you
+ have a dispute with any Mint or third party, you release Cashu.me from
+ all related claims.
+
+ 8. Arbitration and Dispute Resolution
+
+ Except for certain intellectual property claims, disputes shall be
+ resolved by binding arbitration in Wyoming under the American
+ Arbitration Association. The Federal Arbitration Act applies. You
+ waive any right to a trial by jury or to participate in a class
+ action.
+
+ 9. Prohibited Uses
+
+ You may not use the Site or Services for unlawful activities, to
+ violate applicable laws, or to engage in market manipulation. We may
+ suspend or terminate access for prohibited uses.
+
+ 10. Intellectual Property
+
+ All trademarks, logos, and content on the Site are owned by Cashu.me
+ or its licensors. You shall not use them without prior written
+ consent.
+
+ 11. Your Representations and Warranties
+
+ You represent and warrant you have the right and authority to enter
+ into these Terms and that your use of the Site will be lawful.
+
+ 12. No Investment Advice
+ Cashu.me does not provide investment, legal, or tax advice.
+ 13. No Waiver
+
+ No failure or delay to exercise any right by Cashu.me shall constitute
+ a waiver of that right.
+
+ 14. Force Majeure
+
+ Cashu.me is not liable for delays or failures due to events beyond our
+ reasonable control.
+
+ 15. Assignment
+
+ You may not assign your rights without our consent. We may assign our
+ rights freely.
+
+ 16. Severability
+
+ If any provision is deemed invalid, remaining provisions remain in
+ effect.
+
+ 17. Electronic Communications; Language
+
+ By using the Site or Services, you consent to receive communications
+ electronically. We will communicate in English.
+
+ 18. Governing Law; Venue
+
+ These Terms are governed by the laws of Wyoming. All disputes are
+ subject to arbitration or Wyoming courts, as provided herein.
+
+ 19. E-Sign Consent Policy
+
+ By using the Site, you consent to receive all communications
+ electronically.
+
+ 20. Risk Disclosure Statement
+
+ Using ecash involves significant risks including legal, market,
+ liquidity, counterparty, and operational risks. You acknowledge and
+ accept these risks.
+
+ 21. Entire Agreement
+
+ These Terms represent the entire agreement between you and Cashu.me.
+
diff --git a/src/router/routes.js b/src/router/routes.js
index 5760ea7d..08429be6 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -30,6 +30,13 @@ const routes = [
{ path: "", component: () => import("src/pages/WelcomePage.vue") },
],
},
+ {
+ path: "/terms",
+ component: () => import("layouts/FullscreenLayout.vue"),
+ children: [
+ { path: "", component: () => import("src/pages/TermsPage.vue") },
+ ],
+ },
// Always leave this as last one,
// but you can also remove it
From a777dd1e9e806a68938e2abdd242a87bf11d6287 Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 20:36:19 +0100
Subject: [PATCH 08/21] fix primary
---
src/components/NoMintWarnBanner.vue | 25 ++++++++++++++++++++++---
src/css/base.scss | 25 +++++++++++++++++++++++--
2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/src/components/NoMintWarnBanner.vue b/src/components/NoMintWarnBanner.vue
index a0854169..19b6883b 100644
--- a/src/components/NoMintWarnBanner.vue
+++ b/src/components/NoMintWarnBanner.vue
@@ -1,8 +1,13 @@
-
+
-
+
Join a mint
@@ -33,7 +38,7 @@
/>
-
+
+
diff --git a/src/css/base.scss b/src/css/base.scss
index 2eca4e93..28da7d3c 100644
--- a/src/css/base.scss
+++ b/src/css/base.scss
@@ -18,9 +18,9 @@ $themes: (
"freedom": (
primary: #e22156,
secondary: #b91a45,
- dark: #0a0a0a,
+ dark: #000,
info: #1b1b1b,
- marginal-bg: #2d293b,
+ marginal-bg: #000,
marginal-text: #fff,
),
"salvador": (
@@ -104,6 +104,27 @@ $themes: (
}
}
+@each $theme, $colors in $themes {
+ [data-theme="#{$theme}"] {
+ @each $name, $color in $colors {
+ @if $name == "primary" {
+ --q-primary: #{$color};
+ }
+ @if $name == "secondary" {
+ --q-secondary: #{$color};
+ }
+ }
+ @each $name, $color in $colors {
+ .bg-#{$name} {
+ background: $color !important;
+ }
+ .text-#{$name} {
+ color: $color !important;
+ }
+ }
+ }
+}
+
[data-theme="monochrome"] .q-badge.bg-primary,
[data-theme="cyber"] .q-badge.bg-primary {
background: primary !important;
From cc3974bb88965b39e0535650e215e95b9806e3ab Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 20:39:00 +0100
Subject: [PATCH 09/21] run format
---
src/components/AndroidPWAPrompt.vue | 4 ++--
src/stores/mints.ts | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/components/AndroidPWAPrompt.vue b/src/components/AndroidPWAPrompt.vue
index 9906f565..88df2bfa 100644
--- a/src/components/AndroidPWAPrompt.vue
+++ b/src/components/AndroidPWAPrompt.vue
@@ -32,7 +32,7 @@ export default defineComponent({
data() {
return {
showAndroidPWAPromptLocal:
- localStorage.getItem("cashu.showAndroidPWAPrompt") != "seen",
+ localStorage.getItem("cashu.ui.showAndroidPWAPrompt") != "seen",
showAndroidPWAPrompt: false,
};
},
@@ -47,7 +47,7 @@ export default defineComponent({
},
methods: {
closePrompt() {
- localStorage.setItem("cashu.showAndroidPWAPrompt", "seen");
+ localStorage.setItem("cashu.ui.showAndroidPWAPrompt", "seen");
this.showAndroidPWAPrompt = false;
},
isChromeOnAndroid() {
diff --git a/src/stores/mints.ts b/src/stores/mints.ts
index 93bba77b..d22e8058 100644
--- a/src/stores/mints.ts
+++ b/src/stores/mints.ts
@@ -420,7 +420,7 @@ export const useMintsStore = defineStore("mints", {
console.error(error);
try {
notifyApiError(error, "Could not get mint info");
- } catch { }
+ } catch {}
throw error;
}
},
@@ -465,7 +465,7 @@ export const useMintsStore = defineStore("mints", {
console.error(error);
try {
notifyApiError(error, "Could not get mint keys");
- } catch { }
+ } catch {}
throw error;
}
},
@@ -479,7 +479,7 @@ export const useMintsStore = defineStore("mints", {
console.error(error);
try {
notifyApiError(error, "Could not get mint keysets");
- } catch { }
+ } catch {}
throw error;
}
},
From 4cefef4bbe9721b0221f82e2e591e28eaf33aadc Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 20:39:42 +0100
Subject: [PATCH 10/21] link
---
src/components/MainHeader.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/MainHeader.vue b/src/components/MainHeader.vue
index 56a41b35..a25b82a0 100644
--- a/src/components/MainHeader.vue
+++ b/src/components/MainHeader.vue
@@ -133,7 +133,7 @@ const linksList = [
},
{
title: "Donate",
- caption: "Support Cashu development",
+ caption: "Support Cashu",
icon: "favorite",
link: "https://docs.cashu.space/contribute",
},
From 2df5bdb8990b47bc581dc5e73d28d217164835a7 Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 20:45:25 +0100
Subject: [PATCH 11/21] button
---
src/pages/WelcomePage.vue | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/pages/WelcomePage.vue b/src/pages/WelcomePage.vue
index 63f7aee8..1e051efe 100644
--- a/src/pages/WelcomePage.vue
+++ b/src/pages/WelcomePage.vue
@@ -35,9 +35,10 @@
flat
icon="arrow_left"
label="Previous"
- :disable="!welcomeStore.canGoPrev"
+ v-if="welcomeStore.canGoPrev"
@click="welcomeStore.goToPrevSlide"
/>
+
Date: Tue, 17 Dec 2024 23:10:08 +0100
Subject: [PATCH 12/21] update tos
---
src/pages/welcome/WelcomeSlide4.vue | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/pages/welcome/WelcomeSlide4.vue b/src/pages/welcome/WelcomeSlide4.vue
index 3447802e..c6301bce 100644
--- a/src/pages/welcome/WelcomeSlide4.vue
+++ b/src/pages/welcome/WelcomeSlide4.vue
@@ -131,11 +131,12 @@
8. Arbitration and Dispute Resolution
- Except for certain intellectual property claims, disputes shall be
- resolved by binding arbitration in Wyoming under the American
- Arbitration Association. The Federal Arbitration Act applies. You
- waive any right to a trial by jury or to participate in a class
- action.
+ Except for certain intellectual property claims, any dispute arising
+ out of or relating to these Terms, the Site, or the Services shall be
+ resolved through final and binding arbitration administered by a
+ reputable arbitration provider. You agree that all proceedings will be
+ conducted on an individual basis and you waive any right to a trial by
+ jury or to participate in a class action.
9. Prohibited Uses
@@ -181,10 +182,11 @@
By using the Site or Services, you consent to receive communications
electronically. We will communicate in English.
- 18. Governing Law; Venue
+ 18. Governing Law
- These Terms are governed by the laws of Wyoming. All disputes are
- subject to arbitration or Wyoming courts, as provided herein.
+ These Terms and any dispute arising from or related to these Terms,
+ the Site, or the Services shall be governed by principles of law
+ generally applicable, without regard to any conflicts of law rules.
19. E-Sign Consent Policy
From 364429bd8ee14e9e7eda3a4ca1574aa56c2ecb6e Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 17 Dec 2024 23:25:25 +0100
Subject: [PATCH 13/21] fix payment request mint
---
src/components/PaymentRequestDialog.vue | 43 ++++++++++++++++++----
src/pages/WalletPage.vue | 2 +-
src/stores/payment-request.ts | 27 ++++++++++++--
src/stores/wallet.ts | 48 +++++++------------------
4 files changed, 75 insertions(+), 45 deletions(-)
diff --git a/src/components/PaymentRequestDialog.vue b/src/components/PaymentRequestDialog.vue
index c774d13a..41f4d2c7 100644
--- a/src/components/PaymentRequestDialog.vue
+++ b/src/components/PaymentRequestDialog.vue
@@ -38,9 +38,15 @@
-
-
- {{ getShortUrl(activeMintUrl) }}
+
+
+ {{ getShortUrl(chosenMintUrl) }}
@@ -118,6 +124,8 @@ export default defineComponent({
amountInputValue: "",
amountLabelDefault: "Add amount",
amountLabel: "Add amount",
+ chosenMintUrl: "Any mint",
+ memo: "",
};
},
computed: {
@@ -134,14 +142,33 @@ export default defineComponent({
toggleUnit() {
this.paymentRequestAmount = undefined;
this.amountLabel = this.amountLabelDefault;
- this.newPaymentRequest(this.paymentRequestAmount);
+ this.newPaymentRequest(
+ this.paymentRequestAmount,
+ this.memo,
+ this.chosenMintUrl
+ );
},
newRequest() {
- this.newPaymentRequest(this.paymentRequestAmount);
+ this.newPaymentRequest(
+ this.paymentRequestAmount,
+ this.memo,
+ this.chosenMintUrl
+ );
},
getShortUrl(url) {
return getShortUrl(url);
},
+ setActiveMintUrl() {
+ if (this.activeMintUrl == this.chosenMintUrl) {
+ return;
+ }
+ this.chosenMintUrl = this.activeMintUrl;
+ this.newPaymentRequest(
+ this.paymentRequestAmount,
+ this.memo,
+ this.chosenMintUrl
+ );
+ },
startEditingAmount() {
this.isEditingAmount = true;
this.$nextTick(() => {
@@ -162,7 +189,11 @@ export default defineComponent({
this.activeUnit
);
}
- this.newPaymentRequest(this.paymentRequestAmount);
+ this.newPaymentRequest(
+ this.paymentRequestAmount,
+ this.memo,
+ this.chosenMintUrl
+ );
this.isEditingAmount = false;
this.amountInputValue = "";
},
diff --git a/src/pages/WalletPage.vue b/src/pages/WalletPage.vue
index 7bc2b2e1..0f9b018c 100644
--- a/src/pages/WalletPage.vue
+++ b/src/pages/WalletPage.vue
@@ -371,7 +371,6 @@ export default {
"checkPendingTokens",
"decodeRequest",
"initializeMnemonic",
- "createPaymentRequest",
]),
...mapActions(useCameraStore, ["closeCamera", "showCamera"]),
...mapActions(useNWCStore, ["listenToNWCCommands"]),
@@ -385,6 +384,7 @@ export default {
"initSigner",
]),
...mapActions(useStorageStore, ["checkLocalStorage"]),
+ ...mapActions(usePRStore, ["createPaymentRequest"]),
// TOKEN METHODS
decodeToken: function (encoded_token) {
try {
diff --git a/src/stores/payment-request.ts b/src/stores/payment-request.ts
index a55765b4..fcf9b536 100644
--- a/src/stores/payment-request.ts
+++ b/src/stores/payment-request.ts
@@ -14,6 +14,7 @@ import { useTokensStore } from "./tokens";
import token from "src/js/token";
import { notify, notifyError, notifySuccess } from "src/js/notify";
import { useLocalStorage } from "@vueuse/core";
+import { v4 as uuidv4 } from "uuid";
export const usePRStore = defineStore("payment-request", {
state: () => ({
@@ -27,9 +28,31 @@ export const usePRStore = defineStore("payment-request", {
}),
getters: {},
actions: {
- newPaymentRequest(amount?: number, memo?: string) {
+ newPaymentRequest(amount?: number, memo?: string, mintUrl?: string) {
const walletStore = useWalletStore();
- this.showPRKData = walletStore.createPaymentRequest(amount, memo);
+ this.showPRKData = this.createPaymentRequest(amount, memo, mintUrl);
+ },
+ createPaymentRequest: function (amount?: number, memo?: string, mintUrl?: string) {
+ const nostrStore = useNostrStore();
+ const mintStore = useMintsStore();
+ const tags = [["n", "17"]];
+ const transport = [
+ {
+ type: PaymentRequestTransportType.NOSTR,
+ target: nostrStore.seedSignerNprofile,
+ tags: tags,
+ },
+ ] as PaymentRequestTransport[];
+ const uuid = uuidv4().split("-")[0];
+ const paymentRequest = new PaymentRequest(
+ transport,
+ uuid,
+ amount,
+ mintStore.activeUnit,
+ mintUrl?.length ? mintStore.activeMintUrl ? [mintStore.activeMintUrl] : undefined : undefined,
+ memo
+ );
+ return paymentRequest.toEncodedRequest();
},
async decodePaymentRequest(pr: string) {
console.log("decodePaymentRequest", pr);
diff --git a/src/stores/wallet.ts b/src/stores/wallet.ts
index 66b53c9b..125c519f 100644
--- a/src/stores/wallet.ts
+++ b/src/stores/wallet.ts
@@ -42,8 +42,6 @@ import * as bolt11Decoder from "light-bolt11-decoder";
import { bech32 } from "bech32";
import axios from "axios";
import { date } from "quasar";
-import { useNostrStore } from "./nostr";
-import { v4 as uuidv4 } from "uuid";
// bip39 requires Buffer
// import { Buffer } from 'buffer';
@@ -740,8 +738,8 @@ export const useWalletStore = defineStore("wallet", {
notifySuccess(
"Paid " +
- uIStore.formatCurrency(amount_paid, mintStore.activeUnit) +
- " via Lightning"
+ uIStore.formatCurrency(amount_paid, mintStore.activeUnit) +
+ " via Lightning"
);
console.log("#### pay lightning: token paid");
// delete spent tokens from db
@@ -988,10 +986,10 @@ export const useWalletStore = defineStore("wallet", {
const proofStore = useProofsStore();
notifySuccess(
"Sent " +
- uIStore.formatCurrency(
- proofStore.sumProofs(spentProofs),
- mintStore.activeUnit
- )
+ uIStore.formatCurrency(
+ proofStore.sumProofs(spentProofs),
+ mintStore.activeUnit
+ )
);
} else {
console.log("### token not paid yet");
@@ -1088,8 +1086,8 @@ export const useWalletStore = defineStore("wallet", {
if (!!window.navigator.vibrate) navigator.vibrate(200);
notifySuccess(
"Received " +
- uIStore.formatCurrency(invoice.amount, mintStore.activeUnit) +
- " via Lightning"
+ uIStore.formatCurrency(invoice.amount, mintStore.activeUnit) +
+ " via Lightning"
);
return proofs;
} catch (error) {
@@ -1138,10 +1136,10 @@ export const useWalletStore = defineStore("wallet", {
if (!!window.navigator.vibrate) navigator.vibrate(200);
notifySuccess(
"Sent " +
- uIStore.formatCurrency(
- useProofsStore().sumProofs(proofs),
- mintStore.activeUnit
- )
+ uIStore.formatCurrency(
+ useProofsStore().sumProofs(proofs),
+ mintStore.activeUnit
+ )
);
}
// set invoice in history to paid
@@ -1436,27 +1434,5 @@ export const useWalletStore = defineStore("wallet", {
}
return false;
},
- createPaymentRequest: function (amount?: number, memo?: string): string {
- const nostrStore = useNostrStore();
- const mintStore = useMintsStore();
- const tags = [["n", "17"]];
- const transport = [
- {
- type: PaymentRequestTransportType.NOSTR,
- target: nostrStore.seedSignerNprofile,
- tags: tags,
- },
- ] as PaymentRequestTransport[];
- const uuid = uuidv4().split("-")[0];
- const paymentRequest = new PaymentRequest(
- transport,
- uuid,
- amount,
- mintStore.activeUnit,
- mintStore.activeMintUrl ? [mintStore.activeMintUrl] : undefined,
- memo
- );
- return paymentRequest.toEncodedRequest();
- },
},
});
From f5420bf0161e60475951b9037a3b1ae550712ce6 Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 01:08:42 +0100
Subject: [PATCH 14/21] slight changes
---
src/components/MainHeader.vue | 1 +
src/pages/welcome/WelcomeSlide1.vue | 2 +-
src/pages/welcome/WelcomeSlide3.vue | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/components/MainHeader.vue b/src/components/MainHeader.vue
index a25b82a0..31c244c6 100644
--- a/src/components/MainHeader.vue
+++ b/src/components/MainHeader.vue
@@ -9,6 +9,7 @@
color="primary"
aria-label="Menu"
@click="toggleLeftDrawer"
+ :disable="uiStore.globalMutexLock"
/>
diff --git a/src/pages/welcome/WelcomeSlide3.vue b/src/pages/welcome/WelcomeSlide3.vue
index ff7ca521..67276c6b 100644
--- a/src/pages/welcome/WelcomeSlide3.vue
+++ b/src/pages/welcome/WelcomeSlide3.vue
@@ -28,7 +28,7 @@
From 0339f133720dc4d956eb197c1a91912009a69729 Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 01:09:24 +0100
Subject: [PATCH 15/21] slight changes
---
src/components/MainHeader.vue | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/MainHeader.vue b/src/components/MainHeader.vue
index 31c244c6..12779fa5 100644
--- a/src/components/MainHeader.vue
+++ b/src/components/MainHeader.vue
@@ -65,6 +65,7 @@
:color="countdown > 0 ? 'negative' : 'primary'"
aria-label="Refresh"
@click="reload"
+ :disable="uiStore.globalMutexLock"
>
From d65e4a5971f2ccdf598fdcb1ac85097f86efb4cf Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 01:10:31 +0100
Subject: [PATCH 16/21] slight changes
---
src/components/MainHeader.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/MainHeader.vue b/src/components/MainHeader.vue
index 12779fa5..33ae1343 100644
--- a/src/components/MainHeader.vue
+++ b/src/components/MainHeader.vue
@@ -65,7 +65,7 @@
:color="countdown > 0 ? 'negative' : 'primary'"
aria-label="Refresh"
@click="reload"
- :disable="uiStore.globalMutexLock"
+ :disable="uiStore.globalMutexLock && countdown === 0"
>
From 867f843dbc8288e35f41535c4227e35e3e99f510 Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 09:35:44 +0100
Subject: [PATCH 17/21] add welcome
---
src/stores/welcome.ts | 127 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
create mode 100644 src/stores/welcome.ts
diff --git a/src/stores/welcome.ts b/src/stores/welcome.ts
new file mode 100644
index 00000000..5d99535e
--- /dev/null
+++ b/src/stores/welcome.ts
@@ -0,0 +1,127 @@
+// src/stores/welcome.ts
+import { defineStore } from "pinia";
+import { useLocalStorage } from "@vueuse/core";
+import { computed } from "vue";
+
+export type WelcomeState = {
+ showWelcome: boolean;
+ currentSlide: number;
+ seedPhraseValidated: boolean;
+ termsAccepted: boolean;
+};
+
+// Define the Pinia store
+export const useWelcomeStore = defineStore("welcome", {
+ state: (): WelcomeState => ({
+ showWelcome: useLocalStorage("cashu.welcome.showWelcome", true),
+ currentSlide: useLocalStorage("cashu.welcome.currentSlide", 0),
+ seedPhraseValidated: useLocalStorage(
+ "cashu.welcome.seedPhraseValidated",
+ false
+ ),
+ termsAccepted: useLocalStorage(
+ "cashu.welcome.termsAccepted",
+ false
+ ),
+ }),
+ getters: {
+ // Determines if the current slide is the last one
+ isLastSlide: (state) => state.currentSlide === 3, // Adjust if you have more slides
+
+ // Determines if the user can proceed to the next slide
+ canProceed: (state) => {
+ switch (state.currentSlide) {
+ case 0:
+ return true;
+ case 1:
+ return true; // Assuming no validation for PWA install
+ case 2:
+ return state.seedPhraseValidated;
+ case 3:
+ return state.termsAccepted;
+ default:
+ return false;
+ }
+ },
+
+ // Determines if the user can navigate to the previous slide
+ canGoPrev: (state) => state.currentSlide > 0,
+ },
+ actions: {
+ /**
+ * Initializes the welcome dialog based on local storage.
+ * Should be called when the store is initialized.
+ */
+ initializeWelcome() {
+ if (!this.showWelcome) {
+ window.location.href = "/";
+ }
+ },
+
+ /**
+ * Closes the welcome dialog and marks it as seen.
+ */
+ closeWelcome() {
+ this.showWelcome = false;
+ // Redirect to home or desired route
+ window.location.href = "/";
+ },
+
+ /**
+ * Sets the current slide index.
+ * @param index - The index of the slide to navigate to.
+ */
+ setCurrentSlide(index: number) {
+ this.currentSlide = index;
+ },
+
+ /**
+ * Marks the terms as accepted.
+ */
+ acceptTerms() {
+ this.termsAccepted = true;
+ },
+
+ /**
+ * Validates the seed phrase.
+ */
+ validateSeedPhrase() {
+ this.seedPhraseValidated = true;
+ },
+
+ /**
+ * Resets the welcome dialog state (useful for testing or resetting).
+ */
+ resetWelcome() {
+ this.showWelcome = true;
+ this.currentSlide = 0;
+ this.termsAccepted = false;
+ this.seedPhraseValidated = false;
+ },
+
+ /**
+ * Navigates to the previous slide if possible.
+ */
+ goToPrevSlide() {
+ if (this.canGoPrev) {
+ this.currentSlide -= 1;
+ }
+ // Optionally, handle edge cases or emit events
+ },
+
+ /**
+ * Navigates to the next slide if possible.
+ * If on the last slide, it can close the welcome dialog.
+ */
+ goToNextSlide() {
+ if (this.canProceed) {
+ if (this.isLastSlide) {
+ this.closeWelcome();
+ } else {
+ this.currentSlide += 1;
+ }
+ }
+ // Optionally, handle edge cases or emit events
+ },
+ },
+});
From 8baf6d2924137fba8328a296425838c7c0c5975e Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 09:51:53 +0100
Subject: [PATCH 18/21] layout
---
src/layouts/BlankLayout.vue | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 src/layouts/BlankLayout.vue
diff --git a/src/layouts/BlankLayout.vue b/src/layouts/BlankLayout.vue
new file mode 100644
index 00000000..a670c498
--- /dev/null
+++ b/src/layouts/BlankLayout.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
From a6fbe05a26c2d222d15d1b0c401f32e836d0019f Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 10:51:55 +0100
Subject: [PATCH 19/21] receive dialog no hyphen wrap
---
src/components/ReceiveTokenDialog.vue | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/components/ReceiveTokenDialog.vue b/src/components/ReceiveTokenDialog.vue
index da7889f1..ef9fdade 100644
--- a/src/components/ReceiveTokenDialog.vue
+++ b/src/components/ReceiveTokenDialog.vue
@@ -25,7 +25,7 @@
label="Paste Cashu token"
type="textarea"
autofocus
- class="q-mb-lg"
+ class="q-mb-lg cashub-nowrap"
@keyup.enter="receiveIfDecodes"
>
@@ -327,4 +327,11 @@ export default defineComponent({
border-top-left-radius: 0px !important;
border-top-right-radius: 0px !important;
}
+
+.cashub-nowrap {
+ word-break: break-all;
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ hyphens: none;
+}
From ba7b8a6d192c8d407ea7ead162ec26dde70641bd Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 13:30:27 +0100
Subject: [PATCH 20/21] Reverse proxy
---
README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/README.md b/README.md
index 00570169..88c08575 100644
--- a/README.md
+++ b/README.md
@@ -49,3 +49,47 @@ npm run build
### Customize the configuration
See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js).
+
+### Reverse proxy
+
+For Quasar Vue Router with history mode, add this fallback URL to allow refreshes: https://router.vuejs.org/guide/essentials/history-mode.html#HTML5-Mode
+
+`Caddyfile`:
+
+```
+# CORS snippet by https://kalnytskyi.com/posts/setup-cors-caddy-2/
+(cors) {
+ @cors_preflight method OPTIONS
+ @cors header Origin {args.0}
+
+ handle @cors_preflight {
+ header Access-Control-Allow-Origin "{args.0}"
+ header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE"
+ header Access-Control-Allow-Headers "Content-Type"
+ header Access-Control-Max-Age "3600"
+ respond "" 204
+ }
+
+ handle @cors {
+ header Access-Control-Allow-Origin "{args.0}"
+ header Access-Control-Expose-Headers "Link"
+ }
+}
+host.com {
+ import cors *
+ encode gzip
+
+ header /service-worker.js {
+ Service-Worker-Allowed "/"
+ Cache-Control "no-cache"
+ }
+
+ # SPA root
+ root * /usr/share/caddy/cashu.me/
+
+ # quasar vue router fallback history mode
+ try_files {path} /index.html
+
+ file_server
+}
+```
From 5e324816f4e1cb5ee19e27621f8feb0037f7068d Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Wed, 18 Dec 2024 14:07:13 +0100
Subject: [PATCH 21/21] notes on reverse proxy
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 88c08575..6eda7149 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,8 @@ See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-webpack/quas
For Quasar Vue Router with history mode, add this fallback URL to allow refreshes: https://router.vuejs.org/guide/essentials/history-mode.html#HTML5-Mode
+More info: https://stackoverflow.com/questions/36399319/vue-router-return-404-when-revisit-to-the-url
+
`Caddyfile`:
```