...
 
Commits (2)
......@@ -29,16 +29,66 @@ function to_hex(input) {
// HTML elements.
const setupForm = document.getElementById('setupForm')
const changeButton = document.getElementById('change')
const passphraseTextField = document.getElementById('passphrase')
const indeterminateProgressIndicator = document.getElementById('indeterminateProgressIndicator')
const generatedTextField = document.getElementById('generated')
const hypercoreContentsTextArea = document.getElementById('hypercoreContents')
const errorsTextArea = document.getElementById('errors')
const publicSigningKeyTextField = document.getElementById('publicSigningKey')
const privateSigningKeyTextArea = document.getElementById('privateSigningKey')
const publicEncryptionKeyTextField = document.getElementById('publicEncryptionKey')
const privateEncryptionKeyTextField = document.getElementById('privateEncryptionKey')
const signals = ['data', 'error', 'append', 'download', 'upload', 'sync', 'close']
function setSignalVisible(signal, state) {
const offState = document.querySelector(`#${signal}Signal > .off`)
const onState = document.querySelector(`#${signal}Signal > .on`)
if (state) {
onState.classList.add('visible')
offState.classList.add('invisible')
} else {
onState.classList.remove('visible')
offState.classList.remove('invisible')
}
}
function resetSignals() {
signals.forEach((signal) => {
setSignalVisible(signal, false)
})
}
function blinkSignal(signal) {
setSignalVisible(signal, true)
// Keep the ready signal lit throughout. All others, blink.
if (signal !== 'ready') {
setTimeout(() => {
setSignalVisible(signal, false)
}, 333)
}
}
function resetForm() {
passphraseTextField.value = ''
publicSigningKeyTextField.value = ''
generatedTextField.value = 'No'
resetSignals()
hypercoreContentsTextArea.value = ''
errorsTextArea.value = ''
privateSigningKeyTextArea.value = ''
publicEncryptionKeyTextField.value = ''
privateEncryptionKeyTextField.value = ''
}
function logError(error) {
errorsTextArea.value += error
}
function generatePassphrase () {
resetForm()
const passphrase = generateEFFDicewarePassphrase.entropy(100)
setupForm.elements.passphrase.value = passphrase.join(' ')
generateKeys()
......@@ -68,16 +118,14 @@ function generateKeys() {
clearOutputFields()
showProgressIndicator()
let feed = null
session25519(domain, passphrase, (error, keys) => {
hideProgressIndicator()
if (error) { alert(error); return }
// Close the existing feed, if one exists.
if (feed !== null) { feed.close() }
if (error) {
logError(error.message)
return
}
//
// Convert the keys first to ArrayBuffer and then to
......@@ -89,11 +137,14 @@ function generateKeys() {
//
// Error: key must be at least 16, was given undefined
//
console.log(`Creating new hypercore with read key ${to_hex(keys.publicSignKey)} and write key ${to_hex(keys.secretSignKey)}`)
const hypercoreReadKey = Buffer.from(keys.publicSignKey.buffer)
const hypercoreWriteKey = Buffer.from(keys.secretSignKey.buffer)
// Create a new hypercore using the newly-generated key material.
feed = hypercore((filename) => ram(filename), hypercoreReadKey, {
let feed = hypercore((filename) => ram(filename), hypercoreReadKey, {
createIfMissing: false,
overwrite: false,
valueEncoding: 'json',
......@@ -107,8 +158,9 @@ function generateKeys() {
})
feed.on('ready', () => {
console.log('Feed: [Ready]')
console.log(`Feed: [Ready] ${to_hex(feed.key)}`)
blinkSignal('ready')
generatedTextField.value = 'Yes'
if (!feed.writable) {
......@@ -129,6 +181,7 @@ function generateKeys() {
const stream = feed.createReadStream({live:true})
stream.on('data', (data) => {
blinkSignal('data')
console.log('Feed [read stream, on data]' , data)
// New data is available on the feed. Display it on the page.
......@@ -143,6 +196,7 @@ function generateKeys() {
const NUMBER_TO_APPEND = 3
let counter = 0
const intervalToUpdateInMS = 500
Date.prototype.getUnixTime = function() { return this.getTime()/1000|0 };
const updateInterval = setInterval(() => {
counter++
......@@ -157,36 +211,66 @@ function generateKeys() {
obj[key] = value
feed.append(obj, (error, sequence) => {
console.log('Append callback')
console.log('Error', error)
console.log('Sequence', sequence)
if (error) {
logError(error)
return
}
console.log(' Sequence', sequence)
})
}, 1000)
}, intervalToUpdateInMS)
})
feed.on('error', (error) => {
console.log(`Feed [Error] ${error}`)
blinkSignal('error')
logError(error)
})
feed.on('download', (index, data) => {
blinkSignal('download')
console.log(`Feed [Download] index = ${index}, data = ${data}`)
})
feed.on('upload', (index, data) => {
blinkSignal('upload')
console.log(`Feed [Upload] index = ${index}, data = ${data}`)
})
feed.on('append', () => {
blinkSignal('append')
console.log('Feed [Append]')
})
feed.on('sync', () => {
console.log('Feed sync')
blinkSignal('sync')
console.log('Feed [Sync]')
})
feed.on('close', () => {
console.log('Feed close')
blinkSignal('close')
console.log('Feed [Close]')
})
// Update the passphrase (and keys) when the change button is pressed.
function onChangeButtonPress (event) {
// If a feed exists, close it and then generate the new keys/feed.
if (feed !== null) {
feed.close((error) => {
// Feed is closed. Error is not really an error.
generatePassphrase()
})
event.preventDefault()
return
}
// Otherwise, just go ahead and generate the keys now.
generatePassphrase()
event.preventDefault()
}
setupForm.removeEventListener('submit', onChangeButtonPress)
setupForm.addEventListener('submit', onChangeButtonPress)
// Display the keys.
publicSigningKeyTextField.value = to_hex(keys.publicSignKey)
privateSigningKeyTextArea.value = to_hex(keys.secretSignKey)
......@@ -195,6 +279,8 @@ function generateKeys() {
})
}
let feedClosedInResponseToChangeButtonPress = false
// Main
document.addEventListener('DOMContentLoaded', () => {
......@@ -203,10 +289,4 @@ document.addEventListener('DOMContentLoaded', () => {
// Generate a passphrase at start
generatePassphrase()
// Update the passphrase (and keys) when the change button is pressed.
setupForm.addEventListener('submit', (event) => {
generatePassphrase()
event.preventDefault()
})
})
......@@ -20,11 +20,6 @@
<input type='text' id='domain' value='ar.al' readonly>
</div>
<div>
<label for='publicSigningKey'>Hyphalink:</label>
<input type='text' id='publicSigningKey'>
</div>
<div>
<label>Passphrase:</label>
<input type='text' id='passphrase' readonly>
......@@ -41,16 +36,40 @@
</div>
</div>
<div>
<label for='publicSigningKey'>Hyphalink:</label>
<input type='text' id='publicSigningKey'>
</div>
<div>
<label for='generated'>Hypercore created?</label>
<input type='text' id='generated' value='No'>
</div>
<div>
<label>Hypercore signals:</label>
<div>
<span id='readySignal' class='signal'><span class='off'></span><span class='on'></span> Ready</span>
<span id='dataSignal' class='signal'><span class='off'></span><span class='on'></span> Data</span>
<span id='errorSignal' class='signal'><span class='off'></span><span class='on'></span> Error</span>
<span id='appendSignal' class='signal'><span class='off'></span><span class='on'></span> Append</span>
<span id='downloadSignal' class='signal'><span class='off'></span><span class='on'></span></span>
<span id='uploadSignal' class='signal'><span class='off'></span><span class='on'></span></span>
<span id='syncSignal' class='signal'><span class='off'></span><span class='on'></span> Sync</span>
<span id='closeSignal' class='signal'><span class='off'></span><span class='on'></span> Close</span>
</div>
</div>
<div>
<label for='hypercoreContents'>Hypercore contents</label>
<textarea id='hypercoreContents'></textarea>
</div>
<div>
<label for='errors'>Errors:</label>
<textarea id='errors'>None</textarea>
</div>
<h3>Notes</h3>
<p>Your domain name and <em>hyphalink</em> are two ways for other people to find your Hypha. The difference is that your hyphalink is decentralised and resilient to censorship. If your domain registrar confiscates or blocks your domain, people will still be able to reach your Hypha as long as there is at least one replica of it on the Internet.</p>
......
......@@ -76,7 +76,7 @@ textarea {
height: 3em;
}
#hypercoreContents {
#hypercoreContents, #errors {
height: 6em;
}
......@@ -93,6 +93,28 @@ footer {
width: 64px;
}
/* Signals */
.visible { display: inline-block !important; }
.invisible { display: none !important; }
.on {
color: green;
display: none;
}
#errorSignal > .on {
color: red;
}
#closeSignal > .on {
color: black;
}
.off {
color: grey;
}
/* Spinkit CSS indeterminate progress indicator */
/* http://tobiasahlin.com/spinkit/ */
......