diff options
| -rw-r--r-- | src/app.js | 22 | ||||
| -rw-r--r-- | src/features/gifts.js | 20 | ||||
| -rw-r--r-- | src/i18n.js | 2 | ||||
| -rw-r--r-- | src/locales/ar.json | 2 | ||||
| -rw-r--r-- | src/locales/bn.json | 2 | ||||
| -rw-r--r-- | src/locales/de.json | 2 | ||||
| -rw-r--r-- | src/locales/es.json | 2 | ||||
| -rw-r--r-- | src/locales/fr.json | 2 | ||||
| -rw-r--r-- | src/locales/hi.json | 2 | ||||
| -rw-r--r-- | src/locales/id.json | 4 | ||||
| -rw-r--r-- | src/locales/it.json | 2 | ||||
| -rw-r--r-- | src/locales/ja.json | 2 | ||||
| -rw-r--r-- | src/locales/ko.json | 2 | ||||
| -rw-r--r-- | src/locales/mr.json | 4 | ||||
| -rw-r--r-- | src/locales/pt.json | 2 | ||||
| -rw-r--r-- | src/locales/ru.json | 2 | ||||
| -rw-r--r-- | src/locales/sw.json | 4 | ||||
| -rw-r--r-- | src/locales/ta.json | 4 | ||||
| -rw-r--r-- | src/locales/te.json | 4 | ||||
| -rw-r--r-- | src/locales/tr.json | 2 | ||||
| -rw-r--r-- | src/locales/ur.json | 4 | ||||
| -rw-r--r-- | src/locales/vi.json | 4 | ||||
| -rw-r--r-- | src/locales/zh.json | 2 | ||||
| -rw-r--r-- | tools/gift-profile-setup-test.js | 91 |
24 files changed, 171 insertions, 18 deletions
@@ -4210,16 +4210,18 @@ function onboardScreen() { } if (o.step === 'spend') { return page([ - title(t('onbSpendTitle')), - h('p', { class: 'muted', style: 'margin:0' }, t('onbSpendBody')), + title(t(o.fromGift ? 'onbGiftNameTitle' : 'onbSpendTitle')), + h('p', { class: 'muted', style: 'margin:0' }, t(o.fromGift ? 'onbGiftNameBody' : 'onbSpendBody')), featureHook('namesClaimForm') || h('div', { class: 'row gap6', style: 'align-items:center' }, h('span', { class: 'spinner sm' }), h('span', { class: 'small muted' }, t('onbNameWait'))), // Optional means optional: one tap to the wallet, no questions — on - // Savings, the account that exists without any setup. + // Savings, the account that exists without any setup (or, after a + // gift, the account the gift arrived in). h('button', { class: 'btn-ghost btn-block', onClick: () => { + const home = o.home || 'savings'; ui.onb = null; try { localStorage.removeItem(ONB_STEP_KEY); } catch {} - ui.account = 'savings'; - try { localStorage.setItem(ACCOUNT_KEY, 'savings'); } catch {} + ui.account = home; + try { localStorage.setItem(ACCOUNT_KEY, home); } catch {} ui.tab = 'receive'; render(); } }, t('onbNotNow')), @@ -4439,6 +4441,15 @@ function claimMigratedName() { attempt(); } +// After a gift is claimed into a fresh wallet (and its seed written down): +// the wizard's name → look → done steps, the rest of a first run. `home` is +// the account a skip lands on — the one the gift arrived in. +function offerProfileSetup({ home = 'savings' } = {}) { + if (!canOfferSpending()) return false; + ui.onb = { step: 'spend', enterAddr: undefined, fromGift: true, home }; + return true; +} + function leaveWizard() { ui.onb = null; try { localStorage.removeItem(ONB_STEP_KEY); } catch {} @@ -6480,6 +6491,7 @@ const ctx = { || (wallet.nostrPubkey && wallet.nostrPubkey()) || (activeAccount() || {}).nostrPk || null, getAccount: () => accountSel(), setAccount: (a, dir) => setAccountSel(a, dir), + offerProfileSetup, pickConfirm, // Open (or create) a wallet from a mnemonic — used by nostr login. openMnemonic: async (mnemonic, passphrase, opts) => enterWallet(mnemonic, passphrase, opts), // Profile pictures retain the metadata-scrubbing image uploader. Public diff --git a/src/features/gifts.js b/src/features/gifts.js index 56fd99e..0ed3dc1 100644 --- a/src/features/gifts.js +++ b/src/features/gifts.js @@ -15,7 +15,7 @@ export function giftsFeature(ctx) { h, ui, render, wallet, toast, copyBtn, pasteBtn, blankSend, goBack, goHome, openExternal, fmtAmount, unitLabel, unitTag, parseAmount, getUnit, toggleUnit, download, brandHeader, activeAccount, setAccounts, getAccounts, claimTargets, - enterWallet, activateAccount, commitAccount, + enterWallet, activateAccount, commitAccount, pickConfirm, } = ctx; installGiftWallet(wallet); // gift primitives live outside the core wallet // Ark-gift support comes from the ark feature (when this build ships it); @@ -214,7 +214,7 @@ export function giftsFeature(ctx) { ), h('div', { class: 'row gap6' }, copyBtn(wallet.mnemonic, t('copyPhrase'))), h('button', { class: 'btn-primary btn-block', onClick: () => { ui.confirm = pickConfirm(words); ui.claimError = ''; ui.claimStep = 'verify'; render(); } }, t('verifyBackup')), - h('button', { class: 'btn-block', onClick: () => { ui.screen = 'wallet'; ui.claimStep = null; landAccount(); render(); } }, t('skipVerification')) + h('button', { class: 'btn-block', onClick: finishClaim }, t('skipVerification')) ) ); } @@ -246,13 +246,11 @@ export function giftsFeature(ctx) { onClick: () => { const ok = ui.confirm.every((c) => c.value.toLowerCase() === words[c.index]); if (!ok) { ui.claimError = t('wordsMismatch'); render(); return; } - ui.screen = 'wallet'; ui.claimStep = null; ui.claimError = ''; - landAccount(); - render(); + finishClaim(); }, }, t('openWallet')) ), - h('button', { class: 'btn-block', onClick: () => { ui.screen = 'wallet'; ui.claimStep = null; landAccount(); render(); } }, t('skipVerification')) + h('button', { class: 'btn-block', onClick: finishClaim }, t('skipVerification')) ) ); } @@ -388,6 +386,16 @@ export function giftsFeature(ctx) { if (ctx.setAccount) ctx.setAccount('spending'); } + // The seed is written down: into the new wallet — by way of the + // wizard's username, avatar and cover, so a gift's recipient arrives as + // someone people can pay by name (skippable, like any first run). + function finishClaim() { + ui.screen = 'wallet'; ui.claimStep = null; ui.claimError = ''; + landAccount(); + if (ctx.offerProfileSetup) ctx.offerProfileSetup({ home: ui.claimVia === 'ark' ? 'spending' : 'savings' }); + render(); + } + function afterClaim(amount) { ui.claimedAmount = amount; const wasProvisional = !!(activeAccount() && activeAccount().provisional); diff --git a/src/i18n.js b/src/i18n.js index 1e71e95..ebd8d31 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -1388,6 +1388,8 @@ const STR = { onbSpendBody: 'Claim a username and get your own payment address. People can send you bitcoin instantly, with just your name.', onbNameWait: 'Getting things ready…', onbNotNow: 'Not now', + onbGiftNameTitle: 'Now pick a username', + onbGiftNameBody: 'Claim a name and get your own payment address, so people can send you bitcoin with just your name. Then choose a picture and a cover.', onbAvatarTitle: 'Choose your look', onbAvatarBody: 'Pick a cover and an avatar, or upload your own. You can change them anytime.', onbCover: 'Cover image', diff --git a/src/locales/ar.json b/src/locales/ar.json index 28af336..d6b5a54 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -618,6 +618,8 @@ "onbSpendBody": "اطالب بلقب مستخدم والحصول على عنوان الدفع الخاص بك - الناس يمكن أن ترسل لك قليلا على الفور، مع مجرد اسمك.", "onbNameWait": "جهز الأشياء", "onbNotNow": "ليس الآن", + "onbGiftNameTitle": "الآن اختر اسم مستخدم", + "onbGiftNameBody": "احجز اسمًا واحصل على عنوان دفع خاص بك، ليتمكن الناس من إرسال البيتكوين إليك باسمك فقط. ثم اختر صورة وغلافًا.", "onbAvatarTitle": "اختر مظهرك", "onbAvatarBody": "اختر صورة رمزية أو ارفع صورتك. يمكنك تغييرها في أي وقت", "onbUpload": "تحميل الصورة", diff --git a/src/locales/bn.json b/src/locales/bn.json index d3d6253..f36ba9e 100644 --- a/src/locales/bn.json +++ b/src/locales/bn.json @@ -618,6 +618,8 @@ "onbSpendBody": "আপনার নাম শুধু আপনার নামের সঙ্গে সঙ্গে সঙ্গে সঙ্গে আপনি আপনার পেকেন পাঠাতে পারেন ।", "onbNameWait": "জিনিস প্রস্তুত করা হচ্ছে...", "onbNotNow": "এই মুহূর্তে নয়", + "onbGiftNameTitle": "এবার একটি ইউজারনেম বেছে নিন", + "onbGiftNameBody": "একটি নাম নিন এবং নিজের পেমেন্ট ঠিকানা পান, যাতে লোকে শুধু আপনার নাম দিয়েই আপনাকে বিটকয়েন পাঠাতে পারে। তারপর একটি ছবি আর একটি কভার বেছে নিন।", "onbAvatarTitle": "আপনার চেহারা পছন্দ করুন", "onbAvatarBody": "একটি অবতার বেছে নাও অথবা নিজের ছবি আপলোড করো। যেকোনো সময় এটি বদলাতে পারো।", "onbUpload": "একটি ছবি আপলোড করুন", diff --git a/src/locales/de.json b/src/locales/de.json index c5a981f..18951fb 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -618,6 +618,8 @@ "onbSpendBody": "Fordern Sie einen Benutzernamen an und erhalten Sie Ihre eigene Zahlungsadresse Die Leute können Ihnen Bitcoin sofort mit Ihrem Namen senden.", "onbNameWait": "Bereitmachen...", "onbNotNow": "Nicht jetzt", + "onbGiftNameTitle": "Wähle jetzt einen Benutzernamen", + "onbGiftNameBody": "Sichere dir einen Namen und deine eigene Zahlungsadresse, damit man dir Bitcoin einfach an deinen Namen senden kann. Danach wählst du ein Bild und ein Titelbild.", "onbAvatarTitle": "Wählen Sie Ihren Look", "onbAvatarBody": "Wählen Sie einen Avatar oder laden Sie Ihr eigenes Bild hoch. Sie können ihn jederzeit ändern.", "onbUpload": "Foto hochladen", diff --git a/src/locales/es.json b/src/locales/es.json index 781a2e8..ca5f2e3 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -618,6 +618,8 @@ "onbSpendBody": "Reclame un nombre de usuario y obtenga su propia dirección de pago, la gente puede enviarle bitcoin al instante, con sólo su nombre.", "onbNameWait": "Preparando las cosas...", "onbNotNow": "Ahora no.", + "onbGiftNameTitle": "Ahora elige un nombre de usuario", + "onbGiftNameBody": "Reclama un nombre y obtén tu propia dirección de pago, para que te puedan enviar bitcoin solo con tu nombre. Después elige una foto y una portada.", "onbAvatarTitle": "Elige tu look", "onbAvatarBody": "Escoge un avatar o sube tu propia imagen. Puedes cambiarlo en cualquier momento.", "onbUpload": "Sube una foto", diff --git a/src/locales/fr.json b/src/locales/fr.json index da332ae..33d4cca 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -618,6 +618,8 @@ "onbSpendBody": "Réclamez un nom d'utilisateur et obtenez votre propre adresse de paiement, les gens peuvent vous envoyer Bitcoin instantanément, avec juste votre nom.", "onbNameWait": "Préparer les choses...", "onbNotNow": "Pas maintenant.", + "onbGiftNameTitle": "Choisissez maintenant un nom d'utilisateur", + "onbGiftNameBody": "Réservez un nom et obtenez votre propre adresse de paiement, pour qu'on puisse vous envoyer des bitcoins avec votre seul nom. Choisissez ensuite une photo et une couverture.", "onbAvatarTitle": "Choisissez votre look", "onbAvatarBody": "Choisissez un avatar ou téléchargez votre propre photo. Vous pouvez le changer à tout moment.", "onbUpload": "Télécharger une photo", diff --git a/src/locales/hi.json b/src/locales/hi.json index 2b0f5a6..5857818 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -618,6 +618,8 @@ "onbSpendBody": "एक उपयोगकर्ता नाम का दावा करें और अपना खुद का भुगतान पता प्राप्त करें - लोग तुरंत अपने नाम के साथ बिटकॉइन भेज सकते हैं।", "onbNameWait": "चीजों को तैयार करना", "onbNotNow": "अब नहीं", + "onbGiftNameTitle": "अब एक यूज़रनेम चुनें", + "onbGiftNameBody": "एक नाम लें और अपना भुगतान पता पाएं, ताकि लोग सिर्फ़ आपके नाम से आपको बिटकॉइन भेज सकें। फिर एक तस्वीर और एक कवर चुनें।", "onbAvatarTitle": "अपना लुक चुनें", "onbAvatarBody": "एक अवतार चुनें या अपनी तस्वीर अपलोड करें। आप इसे कभी भी बदल सकते हैं।", "onbUpload": "फ़ोटो अपलोड करें", diff --git a/src/locales/id.json b/src/locales/id.json index 6a6f24a..28e7970 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -263,5 +263,7 @@ "arkRenewViewTx": "Lihat transaksi ronde", "pagerFetchingVideo": "Mengambil video berikutnya…", "pagerFetchingPictures": "Mengambil gambar lainnya…", - "pagerCaughtUp": "Sementara itu saja" + "pagerCaughtUp": "Sementara itu saja", + "onbGiftNameTitle": "Sekarang pilih nama pengguna", + "onbGiftNameBody": "Klaim sebuah nama dan dapatkan alamat pembayaran sendiri, agar orang bisa mengirimimu bitcoin hanya dengan namamu. Lalu pilih foto dan sampul." } diff --git a/src/locales/it.json b/src/locales/it.json index 196b4c8..9660d81 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1156,6 +1156,8 @@ "onbSpendBody": "Scegli un nome utente e ottieni il tuo indirizzo di pagamento. Chiunque potrà inviarti bitcoin all’istante, solo con il tuo nome.", "onbNameWait": "Preparazione in corso…", "onbNotNow": "Non ora", + "onbGiftNameTitle": "Ora scegli un nome utente", + "onbGiftNameBody": "Prendi un nome e ottieni il tuo indirizzo di pagamento, così ti possono inviare bitcoin solo con il tuo nome. Poi scegli una foto e una copertina.", "onbAvatarTitle": "Scegli il tuo aspetto", "onbAvatarBody": "Scegli una copertina e un avatar, oppure carica i tuoi. Puoi cambiarli quando vuoi.", "onbCover": "Immagine di copertina", diff --git a/src/locales/ja.json b/src/locales/ja.json index c37ebf3..ce46732 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -618,6 +618,8 @@ "onbSpendBody": "ユーザー名を主張し、独自の支払いアドレスを取得する, 人々は、あなたの名前だけで、即座にビットコインを送ることができます。", "onbNameWait": "物事を準備する...", "onbNotNow": "今は今", + "onbGiftNameTitle": "次にユーザー名を選びましょう", + "onbGiftNameBody": "名前を取得して自分の支払いアドレスを手に入れましょう。名前だけでビットコインを受け取れます。そのあと写真とカバーを選びます。", "onbAvatarTitle": "お問い合わせ", "onbAvatarBody": "アバターを選ぶか、自分の写真をアップロードしてください。いつでも変更できます。", "onbUpload": "写真をアップロードする", diff --git a/src/locales/ko.json b/src/locales/ko.json index 58da658..ad2d340 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -617,6 +617,8 @@ "onbSpendBody": "사용자 이름 및 자신의 지불 주소를 얻기, 사람들은 즉시 Bitcoin을 보낼 수 있습니다, 그냥 당신의 이름.", "onbNameWait": "준비하는 것들 ...", "onbNotNow": "현재 위치", + "onbGiftNameTitle": "이제 사용자 이름을 고르세요", + "onbGiftNameBody": "이름을 등록하고 나만의 결제 주소를 받으세요. 이름만으로 비트코인을 받을 수 있어요. 그다음 사진과 커버를 고르세요.", "onbAvatarTitle": "자주 묻는 질문", "onbAvatarBody": "아바타를 선택하거나 사진을 업로드하세요. 언제든지 변경할 수 있습니다.", "onbUpload": "사진 업로드", diff --git a/src/locales/mr.json b/src/locales/mr.json index 5936679..c72ed32 100644 --- a/src/locales/mr.json +++ b/src/locales/mr.json @@ -263,5 +263,7 @@ "arkRenewViewTx": "राउंडचा व्यवहार पहा", "pagerFetchingVideo": "पुढचा व्हिडिओ आणत आहे…", "pagerFetchingPictures": "आणखी चित्रे आणत आहे…", - "pagerCaughtUp": "सध्या एवढेच" + "pagerCaughtUp": "सध्या एवढेच", + "onbGiftNameTitle": "आता एक युजरनेम निवडा", + "onbGiftNameBody": "एक नाव घ्या आणि स्वतःचा पेमेंट पत्ता मिळवा, म्हणजे लोक फक्त तुमच्या नावाने तुम्हाला बिटकॉइन पाठवू शकतील. मग एक फोटो आणि कव्हर निवडा." } diff --git a/src/locales/pt.json b/src/locales/pt.json index b206ee0..f0a4e82 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -618,6 +618,8 @@ "onbSpendBody": "Reclame um nome de usuário e obtenha seu próprio endereço de pagamento, as pessoas podem enviar bitcoin instantaneamente, com apenas seu nome.", "onbNameWait": "Preparando as coisas...", "onbNotNow": "Agora não.", + "onbGiftNameTitle": "Agora escolha um nome de usuário", + "onbGiftNameBody": "Reserve um nome e ganhe seu próprio endereço de pagamento, para que possam te enviar bitcoin só com o seu nome. Depois escolha uma foto e uma capa.", "onbAvatarTitle": "Escolha o seu look", "onbAvatarBody": "Escolha um avatar ou carregue a sua própria foto. Podes mudá-lo quando quiseres.", "onbUpload": "Enviar uma foto", diff --git a/src/locales/ru.json b/src/locales/ru.json index 910e781..bd69688 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -618,6 +618,8 @@ "onbSpendBody": "Заявите имя пользователя и получите свой собственный платежный адрес, люди могут отправить вам биткойн мгновенно, только с вашим именем.", "onbNameWait": "Готовить вещи...", "onbNotNow": "Не сейчас", + "onbGiftNameTitle": "Теперь выберите имя пользователя", + "onbGiftNameBody": "Займите имя и получите свой платёжный адрес — тогда вам смогут отправлять биткоин просто по имени. Потом выберите фото и обложку.", "onbAvatarTitle": "Выберите свой взгляд", "onbAvatarBody": "Выберите аватар или загрузите свою фотографию. Его можно изменить в любое время.", "onbUpload": "Загрузить фото", diff --git a/src/locales/sw.json b/src/locales/sw.json index 5fcc4f0..182668b 100644 --- a/src/locales/sw.json +++ b/src/locales/sw.json @@ -263,5 +263,7 @@ "arkRenewViewTx": "Tazama muamala wa raundi", "pagerFetchingVideo": "Inaleta video inayofuata…", "pagerFetchingPictures": "Inaleta picha zaidi…", - "pagerCaughtUp": "Hayo ndiyo yote kwa sasa" + "pagerCaughtUp": "Hayo ndiyo yote kwa sasa", + "onbGiftNameTitle": "Sasa chagua jina la mtumiaji", + "onbGiftNameBody": "Chukua jina upate anwani yako ya malipo, ili watu wakutumie bitcoin kwa jina lako tu. Kisha chagua picha na jalada." } diff --git a/src/locales/ta.json b/src/locales/ta.json index e866428..fd3825d 100644 --- a/src/locales/ta.json +++ b/src/locales/ta.json @@ -263,5 +263,7 @@ "arkRenewViewTx": "சுற்றின் பரிவர்த்தனையைக் காண்க", "pagerFetchingVideo": "அடுத்த வீடியோவைப் பெறுகிறது…", "pagerFetchingPictures": "மேலும் படங்களைப் பெறுகிறது…", - "pagerCaughtUp": "இப்போதைக்கு இவ்வளவுதான்" + "pagerCaughtUp": "இப்போதைக்கு இவ்வளவுதான்", + "onbGiftNameTitle": "இப்போது ஒரு பயனர்பெயரைத் தேர்ந்தெடுங்கள்", + "onbGiftNameBody": "ஒரு பெயரைப் பெற்று உங்கள் சொந்த பணம் பெறும் முகவரியைப் பெறுங்கள்; உங்கள் பெயரை மட்டும் வைத்தே மற்றவர்கள் பிட்காயின் அனுப்பலாம். பிறகு ஒரு படத்தையும் அட்டைப்படத்தையும் தேர்ந்தெடுங்கள்." } diff --git a/src/locales/te.json b/src/locales/te.json index 40ba4ad..87b750e 100644 --- a/src/locales/te.json +++ b/src/locales/te.json @@ -261,5 +261,7 @@ "arkRenewViewTx": "రౌండ్ లావాదేవీని చూడండి", "pagerFetchingVideo": "తదుపరి వీడియోను తెస్తోంది…", "pagerFetchingPictures": "మరిన్ని చిత్రాలను తెస్తోంది…", - "pagerCaughtUp": "ప్రస్తుతానికి ఇంతే" + "pagerCaughtUp": "ప్రస్తుతానికి ఇంతే", + "onbGiftNameTitle": "ఇప్పుడు ఒక యూజర్నేమ్ ఎంచుకోండి", + "onbGiftNameBody": "ఒక పేరు తీసుకుని మీ సొంత చెల్లింపు చిరునామా పొందండి, అప్పుడు మీ పేరుతోనే ఎవరైనా మీకు బిట్కాయిన్ పంపవచ్చు. తర్వాత ఒక ఫోటో, ఒక కవర్ ఎంచుకోండి." } diff --git a/src/locales/tr.json b/src/locales/tr.json index 31734b9..b1530c1 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -617,6 +617,8 @@ "onbSpendBody": "Bir kullanıcı adı talep edin ve kendi ödeme adresinizi alın - insanlar size anında Bitcoin gönderebilir, sadece adınızla.", "onbNameWait": "İşler hazır olsun...", "onbNotNow": "Şimdi Değil", + "onbGiftNameTitle": "Şimdi bir kullanıcı adı seç", + "onbGiftNameBody": "Bir isim al ve kendi ödeme adresine sahip ol; insanlar sana sadece adınla bitcoin gönderebilsin. Sonra bir fotoğraf ve kapak seç.", "onbAvatarTitle": "görünümünü seçin", "onbAvatarBody": "Bir avatar seçin veya kendi resminizi yükleyin. İstediğiniz zaman değiştirebilirsiniz.", "onbUpload": "Bir fotoğraf", diff --git a/src/locales/ur.json b/src/locales/ur.json index 0fb30a2..21f0071 100644 --- a/src/locales/ur.json +++ b/src/locales/ur.json @@ -263,5 +263,7 @@ "arkRenewViewTx": "راؤنڈ کی ٹرانزیکشن دیکھیں", "pagerFetchingVideo": "اگلی ویڈیو لائی جا رہی ہے…", "pagerFetchingPictures": "مزید تصاویر لائی جا رہی ہیں…", - "pagerCaughtUp": "فی الحال بس اتنا ہی" + "pagerCaughtUp": "فی الحال بس اتنا ہی", + "onbGiftNameTitle": "اب ایک یوزرنیم چنیں", + "onbGiftNameBody": "ایک نام لیں اور اپنا ادائیگی کا پتہ پائیں، تاکہ لوگ صرف آپ کے نام سے آپ کو بٹ کوائن بھیج سکیں۔ پھر ایک تصویر اور ایک کور چنیں۔" } diff --git a/src/locales/vi.json b/src/locales/vi.json index 92e3362..cb87b30 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -263,5 +263,7 @@ "arkRenewViewTx": "Xem giao dịch của vòng", "pagerFetchingVideo": "Đang tải video tiếp theo…", "pagerFetchingPictures": "Đang tải thêm ảnh…", - "pagerCaughtUp": "Tạm thời chỉ có vậy" + "pagerCaughtUp": "Tạm thời chỉ có vậy", + "onbGiftNameTitle": "Giờ hãy chọn tên người dùng", + "onbGiftNameBody": "Nhận một cái tên và địa chỉ thanh toán của riêng bạn, để mọi người gửi bitcoin cho bạn chỉ bằng tên. Sau đó chọn ảnh đại diện và ảnh bìa." } diff --git a/src/locales/zh.json b/src/locales/zh.json index 502e12a..54169eb 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -618,6 +618,8 @@ "onbSpendBody": "要求一个用户名并获得你自己的付款地址,人们可以立刻发送你比特币,只要你的名字.", "onbNameWait": "准备...", "onbNotNow": "现在不行", + "onbGiftNameTitle": "现在选一个用户名", + "onbGiftNameBody": "领取一个名字,获得你自己的收款地址,别人只用你的名字就能给你发比特币。然后选一张头像和封面。", "onbAvatarTitle": "选择你的外观", "onbAvatarBody": "选择一个头像或上传自己的照片。你可以随时更改", "onbUpload": "上传相片", diff --git a/tools/gift-profile-setup-test.js b/tools/gift-profile-setup-test.js new file mode 100644 index 0000000..67da261 --- /dev/null +++ b/tools/gift-profile-setup-test.js @@ -0,0 +1,91 @@ +// After a gift is opened into a fresh wallet and its seed written down, the +// first-run wizard asks for a username, then a picture and a cover — the gift's +// recipient should arrive as someone people can pay by name. "Not now" lands in +// the account the gift went to. +// Drives an ark gift on mutinynet whose bearer key holds nothing (a random +// secret: the staging ASP sees no coin, so the sweep finds it taken), then +// "Create wallet anyway" → the seed → on to the wizard. +// Run: bun run build && bun tools/gift-profile-setup-test.js [screenshot.png] +import puppeteer from './puppeteer.js'; +import { base32nopad } from '@scure/base'; +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); +let ok = true; +const check = (n, c, d = '') => { console.log(` ${c ? '✓' : '✗'} ${n}${d ? ' — ' + d : ''}`); if (!c) ok = false; }; +const server = Bun.serve({ port: 0, async fetch(req) { + const p = new URL(req.url).pathname; + const f = Bun.file('dist' + (p === '/' ? '/index.html' : p)); + return (await f.exists()) ? new Response(f) : new Response(Bun.file('dist/index.html'), { headers: { 'content-type': 'text/html' } }); +} }); +const giftCode = () => { + const b = new Uint8Array(42); + b[0] = 0x11; b[1] = 3; // ark gift, mutinynet + new DataView(b.buffer).setBigUint64(2, 1000n, true); + b.set(crypto.getRandomValues(new Uint8Array(32)), 10); + return base32nopad.encode(b); +}; +const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome', headless: true, args: ['--no-sandbox'] }); +const text = (page) => page.evaluate(() => document.body.innerText); +const click = (page, x) => page.evaluate((x) => { + const e = [...document.querySelectorAll('button')].find((n) => n.textContent.trim().toLowerCase().includes(x)); + e?.click(); return !!e; +}, x); +const waitText = async (page, re, ms = 30000) => { + for (let t = 0; t < ms; t += 250) { if (re.test(await text(page))) return true; await sleep(250); } + return false; +}; +async function toSeed(page) { + await page.goto(server.url.href); + await page.evaluate(() => { localStorage.clear(); localStorage.setItem('btc-wallet-network', 'mutinynet'); }); + await page.goto(server.url.href + 'ag/' + giftCode()); + check('the gift opens: the server sees no coin behind it', await waitText(page, /aren.t visible/i)); + await click(page, 'claim'); + check('...so the claim finds it taken', await waitText(page, /create a wallet anyway/i)); + check('...create a wallet anyway shows the seed', await click(page, 'create a wallet anyway') && await waitText(page, /recovery phrase/i, 10000)); +} +try { + const page = await browser.newPage(); + const errors = []; + page.on('pageerror', (e) => errors.push(String(e))); + await page.setViewport({ width: 390, height: 844, deviceScaleFactor: 2 }); + await toSeed(page); + await click(page, 'skip verification'); + check('the seed done: the wizard asks for a username', await waitText(page, /now pick a username/i, 10000), (await text(page)).slice(0, 200)); + check('...with the claim form (or its wait) and Not now', await page.evaluate(() => !!document.querySelector('.onb')) && /not now/i.test(await text(page))); + if (process.argv[2]) await page.screenshot({ path: process.argv[2] }); + // the look step follows the name, as in any first run + await page.evaluate(() => localStorage.setItem('btc-wallet-onb-step', 'avatar')); + await page.reload(); + check('the next step is the picture and cover', !!await page.waitForSelector('.onb-cover', { timeout: 15000 }).catch(() => null)); + // a second gift, verified this time, then Not now + const p2 = await browser.newPage(); + p2.on('pageerror', (e) => errors.push(String(e))); + await p2.setViewport({ width: 390, height: 844, deviceScaleFactor: 2 }); + await toSeed(p2); + check('Verify backup opens the word check', await click(p2, 'verify') && await waitText(p2, /word #?\d/i, 5000)); + await sleep(500); + // the verify page doesn't show the words: read them from the account + const filled = await p2.evaluate(() => { + const accs = JSON.parse(sessionStorage.getItem('btc-wallet-accounts') || '{}'); + const list = Array.isArray(accs) ? accs : accs.accounts || accs.list || []; + const m = list.map((a) => a.mnemonic).filter(Boolean).pop(); if (!m) return false; + const w = m.split(' '); + for (const lab of document.querySelectorAll('label.field')) { + const n = Number(lab.querySelector('.lab').textContent.match(/\d+/)[0]); + const inp = lab.querySelector('input'); + const set = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set; + set.call(inp, w[n - 1]); inp.dispatchEvent(new Event('input', { bubbles: true })); + } + return true; + }); + if (filled) { + await click(p2, 'open wallet'); + check('a verified seed leads to the username step too', await waitText(p2, /now pick a username/i, 10000)); + await click(p2, 'not now'); + let gone = false; + for (let i = 0; i < 20 && !gone; i++) { await sleep(250); gone = !(await p2.evaluate(() => !!document.querySelector('.onb'))); } + check('Not now: into the wallet, the wizard gone', gone, (await text(p2)).slice(0, 200)); + } else console.log(' (accounts not in localStorage — verify path not driven)'); + check('no page errors', errors.length === 0, errors.join(' | ')); +} finally { await browser.close(); server.stop(true); } +console.log(ok ? '\n✅ a gift\'s new wallet is offered a name, a picture and a cover' : '\n❌ failed'); +process.exit(ok ? 0 : 1); |
