Add comprehensive installation and setup documentation

- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
This commit is contained in:
Dorian
2026-01-27 17:18:21 +00:00
parent a81f655133
commit 0d073fa89e
22658 changed files with 4494151 additions and 6 deletions
+173
View File
@@ -0,0 +1,173 @@
import { arr2text, text2arr, arr2hex } from 'uint8-util'
const INTEGER_START = 0x69 // 'i'
const STRING_DELIM = 0x3A // ':'
const DICTIONARY_START = 0x64 // 'd'
const LIST_START = 0x6C // 'l'
const END_OF_TYPE = 0x65 // 'e'
/**
* replaces parseInt(buffer.toString('ascii', start, end)).
* For strings with less then ~30 charachters, this is actually a lot faster.
*
* @param {Uint8Array} data
* @param {Number} start
* @param {Number} end
* @return {Number} calculated number
*/
function getIntFromBuffer (buffer, start, end) {
let sum = 0
let sign = 1
for (let i = start; i < end; i++) {
const num = buffer[i]
if (num < 58 && num >= 48) {
sum = sum * 10 + (num - 48)
continue
}
if (i === start && num === 43) { // +
continue
}
if (i === start && num === 45) { // -
sign = -1
continue
}
if (num === 46) { // .
// its a float. break here.
break
}
throw new Error('not a number: buffer[' + i + '] = ' + num)
}
return sum * sign
}
/**
* Decodes bencoded data.
*
* @param {Uint8Array} data
* @param {Number} start (optional)
* @param {Number} end (optional)
* @param {String} encoding (optional)
* @return {Object|Array|Uint8Array|String|Number}
*/
function decode (data, start, end, encoding) {
if (data == null || data.length === 0) {
return null
}
if (typeof start !== 'number' && encoding == null) {
encoding = start
start = undefined
}
if (typeof end !== 'number' && encoding == null) {
encoding = end
end = undefined
}
decode.position = 0
decode.encoding = encoding || null
decode.data = !(ArrayBuffer.isView(data))
? text2arr(data)
: new Uint8Array(data.slice(start, end))
decode.bytes = decode.data.length
return decode.next()
}
decode.bytes = 0
decode.position = 0
decode.data = null
decode.encoding = null
decode.next = function () {
switch (decode.data[decode.position]) {
case DICTIONARY_START:
return decode.dictionary()
case LIST_START:
return decode.list()
case INTEGER_START:
return decode.integer()
default:
return decode.buffer()
}
}
decode.find = function (chr) {
let i = decode.position
const c = decode.data.length
const d = decode.data
while (i < c) {
if (d[i] === chr) return i
i++
}
throw new Error(
'Invalid data: Missing delimiter "' +
String.fromCharCode(chr) + '" [0x' +
chr.toString(16) + ']'
)
}
decode.dictionary = function () {
decode.position++
const dict = {}
while (decode.data[decode.position] !== END_OF_TYPE) {
const buffer = decode.buffer()
let key = arr2text(buffer)
if (key.includes('\uFFFD')) key = arr2hex(buffer)
dict[key] = decode.next()
}
decode.position++
return dict
}
decode.list = function () {
decode.position++
const lst = []
while (decode.data[decode.position] !== END_OF_TYPE) {
lst.push(decode.next())
}
decode.position++
return lst
}
decode.integer = function () {
const end = decode.find(END_OF_TYPE)
const number = getIntFromBuffer(decode.data, decode.position + 1, end)
decode.position += end + 1 - decode.position
return number
}
decode.buffer = function () {
let sep = decode.find(STRING_DELIM)
const length = getIntFromBuffer(decode.data, decode.position, sep)
const end = ++sep + length
decode.position = end
return decode.encoding
? arr2text(decode.data.slice(sep, end))
: decode.data.slice(sep, end)
}
export default decode
+136
View File
@@ -0,0 +1,136 @@
import { concat, text2arr } from 'uint8-util'
import { getType } from './util.js'
/**
* Encodes data in bencode.
*
* @param {Uint8Array|Array|String|Object|Number|Boolean} data
* @return {Uint8Array}
*/
function encode (data, buffer, offset) {
const buffers = []
let result = null
encode._encode(buffers, data)
result = concat(buffers)
encode.bytes = result.length
if (ArrayBuffer.isView(buffer)) {
buffer.set(result, offset)
return buffer
}
return result
}
encode.bytes = -1
encode._floatConversionDetected = false
encode._encode = function (buffers, data) {
if (data == null) { return }
switch (getType(data)) {
case 'object': encode.dict(buffers, data); break
case 'map': encode.dictMap(buffers, data); break
case 'array': encode.list(buffers, data); break
case 'set': encode.listSet(buffers, data); break
case 'string': encode.string(buffers, data); break
case 'number': encode.number(buffers, data); break
case 'boolean': encode.number(buffers, data); break
case 'arraybufferview': encode.buffer(buffers, new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); break
case 'arraybuffer': encode.buffer(buffers, new Uint8Array(data)); break
}
}
const buffE = new Uint8Array([0x65])
const buffD = new Uint8Array([0x64])
const buffL = new Uint8Array([0x6C])
encode.buffer = function (buffers, data) {
buffers.push(text2arr(data.length + ':'), data)
}
encode.string = function (buffers, data) {
buffers.push(text2arr(text2arr(data).byteLength + ':' + data))
}
encode.number = function (buffers, data) {
if (Number.isInteger(data)) return buffers.push(text2arr('i' + BigInt(data) + 'e'))
const maxLo = 0x80000000
const hi = (data / maxLo) << 0
const lo = (data % maxLo) << 0
const val = hi * maxLo + lo
buffers.push(text2arr('i' + val + 'e'))
if (val !== data && !encode._floatConversionDetected) {
encode._floatConversionDetected = true
console.warn(
'WARNING: Possible data corruption detected with value "' + data + '":',
'Bencoding only defines support for integers, value was converted to "' + val + '"'
)
console.trace()
}
}
encode.dict = function (buffers, data) {
buffers.push(buffD)
let j = 0
let k
// fix for issue #13 - sorted dicts
const keys = Object.keys(data).sort()
const kl = keys.length
for (; j < kl; j++) {
k = keys[j]
if (data[k] == null) continue
encode.string(buffers, k)
encode._encode(buffers, data[k])
}
buffers.push(buffE)
}
encode.dictMap = function (buffers, data) {
buffers.push(buffD)
const keys = Array.from(data.keys()).sort()
for (const key of keys) {
if (data.get(key) == null) continue
ArrayBuffer.isView(key)
? encode._encode(buffers, key)
: encode.string(buffers, String(key))
encode._encode(buffers, data.get(key))
}
buffers.push(buffE)
}
encode.list = function (buffers, data) {
let i = 0
const c = data.length
buffers.push(buffL)
for (; i < c; i++) {
if (data[i] == null) continue
encode._encode(buffers, data[i])
}
buffers.push(buffE)
}
encode.listSet = function (buffers, data) {
buffers.push(buffL)
for (const item of data) {
if (item == null) continue
encode._encode(buffers, item)
}
buffers.push(buffE)
}
export default encode
+69
View File
@@ -0,0 +1,69 @@
import { text2arr } from 'uint8-util'
import { digitCount, getType } from './util.js'
function listLength (list) {
let length = 1 + 1 // type marker + end-of-type marker
for (const value of list) {
length += encodingLength(value)
}
return length
}
function mapLength (map) {
let length = 1 + 1 // type marker + end-of-type marker
for (const [key, value] of map) {
const keyLength = text2arr(key).byteLength
length += digitCount(keyLength) + 1 + keyLength
length += encodingLength(value)
}
return length
}
function objectLength (value) {
let length = 1 + 1 // type marker + end-of-type marker
const keys = Object.keys(value)
for (let i = 0; i < keys.length; i++) {
const keyLength = text2arr(keys[i]).byteLength
length += digitCount(keyLength) + 1 + keyLength
length += encodingLength(value[keys[i]])
}
return length
}
function stringLength (value) {
const length = text2arr(value).byteLength
return digitCount(length) + 1 + length
}
function arrayBufferLength (value) {
const length = value.byteLength - value.byteOffset
return digitCount(length) + 1 + length
}
function encodingLength (value) {
const length = 0
if (value == null) return length
const type = getType(value)
switch (type) {
case 'arraybufferview': return arrayBufferLength(value)
case 'string': return stringLength(value)
case 'array': case 'set': return listLength(value)
case 'number': return 1 + digitCount(Math.floor(value)) + 1
case 'bigint': return 1 + value.toString().length + 1
case 'object': return objectLength(value)
case 'map': return mapLength(value)
default:
throw new TypeError(`Unsupported value of type "${type}"`)
}
}
export default encodingLength
+20
View File
@@ -0,0 +1,20 @@
export function digitCount (value) {
// Add a digit for negative numbers, as the sign will be prefixed
const sign = value < 0 ? 1 : 0
// Guard against negative numbers & zero going into log10(),
// as that would return -Infinity
value = Math.abs(Number(value || 1))
return Math.floor(Math.log10(value)) + 1 + sign
}
export function getType (value) {
if (ArrayBuffer.isView(value)) return 'arraybufferview'
if (Array.isArray(value)) return 'array'
if (value instanceof Number) return 'number'
if (value instanceof Boolean) return 'boolean'
if (value instanceof Set) return 'set'
if (value instanceof Map) return 'map'
if (value instanceof String) return 'string'
if (value instanceof ArrayBuffer) return 'arraybuffer'
return typeof value
}