aboutsummaryrefslogtreecommitdiffstats
path: root/src/app.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-17 11:26:04 -0700
committerAdam Soltys <[email protected]>2026-08-17 11:26:04 -0700
commitea588ca8553a4c83be32ad36d27dc73038b39874 (patch)
tree5eaa76ccd4d22ad24787477c3946f38a23a5ff77 /src/app.js
parent574cb69de872365ebd57afba0da7fa0f0c4748a7 (diff)
downloadcoinosv3-ea588ca8553a4c83be32ad36d27dc73038b39874.tar.gz
coinosv3-ea588ca8553a4c83be32ad36d27dc73038b39874.zip
The import pane learns the entropy trick: the same fold, the same text, the same wallet — typed entropy fills the phrase field with its derived words and clears only what it filled
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
Diffstat (limited to 'src/app.js')
-rw-r--r--src/app.js60
1 files changed, 40 insertions, 20 deletions
diff --git a/src/app.js b/src/app.js
index 6484cc8..d310cad 100644
--- a/src/app.js
+++ b/src/app.js
@@ -817,26 +817,9 @@ function createPane() {
// have to parse it. Deterministic on purpose: the typed text alone
// derives the words (live, as you type), so re-typing it IS an import;
// clearing the field brings the randomly generated phrase back.
- h('button', {
- class: 'linklike small', style: 'align-self:flex-start',
- onClick: () => { ui.ownEntropyOpen = !ui.ownEntropyOpen; render(); },
- }, (ui.ownEntropyOpen ? '▾ ' : '▸ ') + t('entropyToggle')),
- ui.ownEntropyOpen
- ? h('div', { class: 'col gap6' },
- h('p', { class: 'small muted', style: 'margin:0' }, t('entropyHint')),
- h('div', { class: 'warn-box small' }, t('entropyWarn')),
- h('textarea', {
- rows: '2', style: 'font-family:var(--sans)', placeholder: t('entropyPlaceholder'),
- autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false',
- value: ui.ownEntropy || '',
- onInput: (e) => {
- ui.ownEntropy = e.target.value;
- const txt = ui.ownEntropy.trim();
- ui.draftMnemonic = txt ? newMnemonic(128, txt) : (ui.draftRandom || ui.draftMnemonic);
- render();
- },
- }))
- : null,
+ ...entropyPanel('ownEntropyOpen', 'ownEntropy', (txt) => {
+ ui.draftMnemonic = txt ? newMnemonic(128, txt) : (ui.draftRandom || ui.draftMnemonic);
+ }),
optionsPanel(),
h(
'button',
@@ -907,6 +890,33 @@ function pickConfirm(words) {
return [...idx].sort((a, b) => a - b).map((index) => ({ index, value: '' }));
}
+// The BYO-entropy fold, shared by Create (re-derives the draft phrase) and
+// Import (fills the phrase field): the typed text alone determines the seed,
+// so the same text recreates the same wallet anywhere.
+function entropyPanel(openKey, textKey, onText) {
+ return [
+ h('button', {
+ class: 'linklike small', style: 'align-self:flex-start',
+ onClick: () => { ui[openKey] = !ui[openKey]; render(); },
+ }, (ui[openKey] ? '▾ ' : '▸ ') + t('entropyToggle')),
+ ui[openKey]
+ ? h('div', { class: 'col gap6' },
+ h('p', { class: 'small muted', style: 'margin:0' }, t('entropyHint')),
+ h('div', { class: 'warn-box small' }, t('entropyWarn')),
+ h('textarea', {
+ rows: '2', style: 'font-family:var(--sans)', placeholder: t('entropyPlaceholder'),
+ autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false',
+ value: ui[textKey] || '',
+ onInput: (e) => {
+ ui[textKey] = e.target.value;
+ onText(ui[textKey].trim());
+ render();
+ },
+ }))
+ : null,
+ ];
+}
+
function importPane() {
const ta = h('textarea', {
placeholder: t('importPlaceholder'),
@@ -925,6 +935,16 @@ function importPane() {
h('span', { class: 'lab' }, t('importLabel')),
pasteInto(ta, (text) => { ta.value = text; ui.importText = text; })
),
+ // A wallet born from typed entropy comes back the same way: the text
+ // fills the phrase field with its derived words, visibly. Clearing the
+ // text clears only what it filled — a pasted phrase is left alone.
+ ...entropyPanel('importEntropyOpen', 'importEntropy', (txt) => {
+ if (txt) {
+ ui.importText = ui._entropyFilled = newMnemonic(128, txt);
+ } else if (ui.importText === ui._entropyFilled) {
+ ui.importText = '';
+ }
+ }),
optionsPanel(),
h('button', { class: 'btn-primary btn-block', onClick: () => openWallet(ui.importText) }, t('openWallet'))
);