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
+413
View File
@@ -0,0 +1,413 @@
import { decode as _decode } from '../decode.js';
import {
Token,
Type
} from '../token.js';
import { decodeCodePointsArray } from '../byte-utils.js';
import { decodeErrPrefix } from '../common.js';
class Tokenizer {
constructor(data, options = {}) {
this.pos = 0;
this.data = data;
this.options = options;
this.modeStack = ['value'];
this.lastToken = '';
}
done() {
return this.pos >= this.data.length;
}
ch() {
return this.data[this.pos];
}
currentMode() {
return this.modeStack[this.modeStack.length - 1];
}
skipWhitespace() {
let c = this.ch();
while (c === 32 || c === 9 || c === 13 || c === 10) {
c = this.data[++this.pos];
}
}
expect(str) {
if (this.data.length - this.pos < str.length) {
throw new Error(`${ decodeErrPrefix } unexpected end of input at position ${ this.pos }`);
}
for (let i = 0; i < str.length; i++) {
if (this.data[this.pos++] !== str[i]) {
throw new Error(`${ decodeErrPrefix } unexpected token at position ${ this.pos }, expected to find '${ String.fromCharCode(...str) }'`);
}
}
}
parseNumber() {
const startPos = this.pos;
let negative = false;
let float = false;
const swallow = chars => {
while (!this.done()) {
const ch = this.ch();
if (chars.includes(ch)) {
this.pos++;
} else {
break;
}
}
};
if (this.ch() === 45) {
negative = true;
this.pos++;
}
if (this.ch() === 48) {
this.pos++;
if (this.ch() === 46) {
this.pos++;
float = true;
} else {
return new Token(Type.uint, 0, this.pos - startPos);
}
}
swallow([
48,
49,
50,
51,
52,
53,
54,
55,
56,
57
]);
if (negative && this.pos === startPos + 1) {
throw new Error(`${ decodeErrPrefix } unexpected token at position ${ this.pos }`);
}
if (!this.done() && this.ch() === 46) {
if (float) {
throw new Error(`${ decodeErrPrefix } unexpected token at position ${ this.pos }`);
}
float = true;
this.pos++;
swallow([
48,
49,
50,
51,
52,
53,
54,
55,
56,
57
]);
}
if (!this.done() && (this.ch() === 101 || this.ch() === 69)) {
float = true;
this.pos++;
if (!this.done() && (this.ch() === 43 || this.ch() === 45)) {
this.pos++;
}
swallow([
48,
49,
50,
51,
52,
53,
54,
55,
56,
57
]);
}
const numStr = String.fromCharCode.apply(null, this.data.subarray(startPos, this.pos));
const num = parseFloat(numStr);
if (float) {
return new Token(Type.float, num, this.pos - startPos);
}
if (this.options.allowBigInt !== true || Number.isSafeInteger(num)) {
return new Token(num >= 0 ? Type.uint : Type.negint, num, this.pos - startPos);
}
return new Token(num >= 0 ? Type.uint : Type.negint, BigInt(numStr), this.pos - startPos);
}
parseString() {
if (this.ch() !== 34) {
throw new Error(`${ decodeErrPrefix } unexpected character at position ${ this.pos }; this shouldn't happen`);
}
this.pos++;
for (let i = this.pos, l = 0; i < this.data.length && l < 65536; i++, l++) {
const ch = this.data[i];
if (ch === 92 || ch < 32 || ch >= 128) {
break;
}
if (ch === 34) {
const str = String.fromCharCode.apply(null, this.data.subarray(this.pos, i));
this.pos = i + 1;
return new Token(Type.string, str, l);
}
}
const startPos = this.pos;
const chars = [];
const readu4 = () => {
if (this.pos + 4 >= this.data.length) {
throw new Error(`${ decodeErrPrefix } unexpected end of unicode escape sequence at position ${ this.pos }`);
}
let u4 = 0;
for (let i = 0; i < 4; i++) {
let ch = this.ch();
if (ch >= 48 && ch <= 57) {
ch -= 48;
} else if (ch >= 97 && ch <= 102) {
ch = ch - 97 + 10;
} else if (ch >= 65 && ch <= 70) {
ch = ch - 65 + 10;
} else {
throw new Error(`${ decodeErrPrefix } unexpected unicode escape character at position ${ this.pos }`);
}
u4 = u4 * 16 + ch;
this.pos++;
}
return u4;
};
const readUtf8Char = () => {
const firstByte = this.ch();
let codePoint = null;
let bytesPerSequence = firstByte > 239 ? 4 : firstByte > 223 ? 3 : firstByte > 191 ? 2 : 1;
if (this.pos + bytesPerSequence > this.data.length) {
throw new Error(`${ decodeErrPrefix } unexpected unicode sequence at position ${ this.pos }`);
}
let secondByte, thirdByte, fourthByte, tempCodePoint;
switch (bytesPerSequence) {
case 1:
if (firstByte < 128) {
codePoint = firstByte;
}
break;
case 2:
secondByte = this.data[this.pos + 1];
if ((secondByte & 192) === 128) {
tempCodePoint = (firstByte & 31) << 6 | secondByte & 63;
if (tempCodePoint > 127) {
codePoint = tempCodePoint;
}
}
break;
case 3:
secondByte = this.data[this.pos + 1];
thirdByte = this.data[this.pos + 2];
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128) {
tempCodePoint = (firstByte & 15) << 12 | (secondByte & 63) << 6 | thirdByte & 63;
if (tempCodePoint > 2047 && (tempCodePoint < 55296 || tempCodePoint > 57343)) {
codePoint = tempCodePoint;
}
}
break;
case 4:
secondByte = this.data[this.pos + 1];
thirdByte = this.data[this.pos + 2];
fourthByte = this.data[this.pos + 3];
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128 && (fourthByte & 192) === 128) {
tempCodePoint = (firstByte & 15) << 18 | (secondByte & 63) << 12 | (thirdByte & 63) << 6 | fourthByte & 63;
if (tempCodePoint > 65535 && tempCodePoint < 1114112) {
codePoint = tempCodePoint;
}
}
}
if (codePoint === null) {
codePoint = 65533;
bytesPerSequence = 1;
} else if (codePoint > 65535) {
codePoint -= 65536;
chars.push(codePoint >>> 10 & 1023 | 55296);
codePoint = 56320 | codePoint & 1023;
}
chars.push(codePoint);
this.pos += bytesPerSequence;
};
while (!this.done()) {
const ch = this.ch();
let ch1;
switch (ch) {
case 92:
this.pos++;
if (this.done()) {
throw new Error(`${ decodeErrPrefix } unexpected string termination at position ${ this.pos }`);
}
ch1 = this.ch();
this.pos++;
switch (ch1) {
case 34:
case 39:
case 92:
case 47:
chars.push(ch1);
break;
case 98:
chars.push(8);
break;
case 116:
chars.push(9);
break;
case 110:
chars.push(10);
break;
case 102:
chars.push(12);
break;
case 114:
chars.push(13);
break;
case 117:
chars.push(readu4());
break;
default:
throw new Error(`${ decodeErrPrefix } unexpected string escape character at position ${ this.pos }`);
}
break;
case 34:
this.pos++;
return new Token(Type.string, decodeCodePointsArray(chars), this.pos - startPos);
default:
if (ch < 32) {
throw new Error(`${ decodeErrPrefix } invalid control character at position ${ this.pos }`);
} else if (ch < 128) {
chars.push(ch);
this.pos++;
} else {
readUtf8Char();
}
}
}
throw new Error(`${ decodeErrPrefix } unexpected end of string at position ${ this.pos }`);
}
parseValue() {
switch (this.ch()) {
case 123:
this.modeStack.push('obj-start');
this.pos++;
return new Token(Type.map, Infinity, 1);
case 91:
this.modeStack.push('array-start');
this.pos++;
return new Token(Type.array, Infinity, 1);
case 34: {
return this.parseString();
}
case 110:
this.expect([
110,
117,
108,
108
]);
return new Token(Type.null, null, 4);
case 102:
this.expect([
102,
97,
108,
115,
101
]);
return new Token(Type.false, false, 5);
case 116:
this.expect([
116,
114,
117,
101
]);
return new Token(Type.true, true, 4);
case 45:
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
return this.parseNumber();
default:
throw new Error(`${ decodeErrPrefix } unexpected character at position ${ this.pos }`);
}
}
next() {
this.skipWhitespace();
switch (this.currentMode()) {
case 'value':
this.modeStack.pop();
return this.parseValue();
case 'array-value': {
this.modeStack.pop();
if (this.ch() === 93) {
this.pos++;
this.skipWhitespace();
return new Token(Type.break, undefined, 1);
}
if (this.ch() !== 44) {
throw new Error(`${ decodeErrPrefix } unexpected character at position ${ this.pos }, was expecting array delimiter but found '${ String.fromCharCode(this.ch()) }'`);
}
this.pos++;
this.modeStack.push('array-value');
this.skipWhitespace();
return this.parseValue();
}
case 'array-start': {
this.modeStack.pop();
if (this.ch() === 93) {
this.pos++;
this.skipWhitespace();
return new Token(Type.break, undefined, 1);
}
this.modeStack.push('array-value');
this.skipWhitespace();
return this.parseValue();
}
case 'obj-key':
if (this.ch() === 125) {
this.modeStack.pop();
this.pos++;
this.skipWhitespace();
return new Token(Type.break, undefined, 1);
}
if (this.ch() !== 44) {
throw new Error(`${ decodeErrPrefix } unexpected character at position ${ this.pos }, was expecting object delimiter but found '${ String.fromCharCode(this.ch()) }'`);
}
this.pos++;
this.skipWhitespace();
case 'obj-start': {
this.modeStack.pop();
if (this.ch() === 125) {
this.pos++;
this.skipWhitespace();
return new Token(Type.break, undefined, 1);
}
const token = this.parseString();
this.skipWhitespace();
if (this.ch() !== 58) {
throw new Error(`${ decodeErrPrefix } unexpected character at position ${ this.pos }, was expecting key/value delimiter ':' but found '${ String.fromCharCode(this.ch()) }'`);
}
this.pos++;
this.modeStack.push('obj-value');
return token;
}
case 'obj-value': {
this.modeStack.pop();
this.modeStack.push('obj-key');
this.skipWhitespace();
return this.parseValue();
}
default:
throw new Error(`${ decodeErrPrefix } unexpected parse state at position ${ this.pos }; this shouldn't happen`);
}
}
}
function decode(data, options) {
options = Object.assign({ tokenizer: new Tokenizer(data, options) }, options);
return _decode(data, options);
}
export {
decode,
Tokenizer
};
+160
View File
@@ -0,0 +1,160 @@
import { Type } from '../token.js';
import { encodeCustom } from '../encode.js';
import { encodeErrPrefix } from '../common.js';
import {
asU8A,
fromString
} from '../byte-utils.js';
class JSONEncoder extends Array {
constructor() {
super();
this.inRecursive = [];
}
prefix(buf) {
const recurs = this.inRecursive[this.inRecursive.length - 1];
if (recurs) {
if (recurs.type === Type.array) {
recurs.elements++;
if (recurs.elements !== 1) {
buf.push([44]);
}
}
if (recurs.type === Type.map) {
recurs.elements++;
if (recurs.elements !== 1) {
if (recurs.elements % 2 === 1) {
buf.push([44]);
} else {
buf.push([58]);
}
}
}
}
}
[Type.uint.major](buf, token) {
this.prefix(buf);
const is = String(token.value);
const isa = [];
for (let i = 0; i < is.length; i++) {
isa[i] = is.charCodeAt(i);
}
buf.push(isa);
}
[Type.negint.major](buf, token) {
this[Type.uint.major](buf, token);
}
[Type.bytes.major](_buf, _token) {
throw new Error(`${ encodeErrPrefix } unsupported type: Uint8Array`);
}
[Type.string.major](buf, token) {
this.prefix(buf);
const byts = fromString(JSON.stringify(token.value));
buf.push(byts.length > 32 ? asU8A(byts) : byts);
}
[Type.array.major](buf, _token) {
this.prefix(buf);
this.inRecursive.push({
type: Type.array,
elements: 0
});
buf.push([91]);
}
[Type.map.major](buf, _token) {
this.prefix(buf);
this.inRecursive.push({
type: Type.map,
elements: 0
});
buf.push([123]);
}
[Type.tag.major](_buf, _token) {
}
[Type.float.major](buf, token) {
if (token.type.name === 'break') {
const recurs = this.inRecursive.pop();
if (recurs) {
if (recurs.type === Type.array) {
buf.push([93]);
} else if (recurs.type === Type.map) {
buf.push([125]);
} else {
throw new Error('Unexpected recursive type; this should not happen!');
}
return;
}
throw new Error('Unexpected break; this should not happen!');
}
if (token.value === undefined) {
throw new Error(`${ encodeErrPrefix } unsupported type: undefined`);
}
this.prefix(buf);
if (token.type.name === 'true') {
buf.push([
116,
114,
117,
101
]);
return;
} else if (token.type.name === 'false') {
buf.push([
102,
97,
108,
115,
101
]);
return;
} else if (token.type.name === 'null') {
buf.push([
110,
117,
108,
108
]);
return;
}
const is = String(token.value);
const isa = [];
let dp = false;
for (let i = 0; i < is.length; i++) {
isa[i] = is.charCodeAt(i);
if (!dp && (isa[i] === 46 || isa[i] === 101 || isa[i] === 69)) {
dp = true;
}
}
if (!dp) {
isa.push(46);
isa.push(48);
}
buf.push(isa);
}
}
function mapSorter(e1, e2) {
if (Array.isArray(e1[0]) || Array.isArray(e2[0])) {
throw new Error(`${ encodeErrPrefix } complex map keys are not supported`);
}
const keyToken1 = e1[0];
const keyToken2 = e2[0];
if (keyToken1.type !== Type.string || keyToken2.type !== Type.string) {
throw new Error(`${ encodeErrPrefix } non-string map keys are not supported`);
}
if (keyToken1 < keyToken2) {
return -1;
}
if (keyToken1 > keyToken2) {
return 1;
}
throw new Error(`${ encodeErrPrefix } unexpected duplicate map keys, this is not supported`);
}
const defaultEncodeOptions = {
addBreakTokens: true,
mapSorter
};
function encode(data, options) {
options = Object.assign({}, defaultEncodeOptions, options);
return encodeCustom(data, new JSONEncoder(), options);
}
export {
encode
};
+10
View File
@@ -0,0 +1,10 @@
import { encode } from './encode.js';
import {
decode,
Tokenizer
} from './decode.js';
export {
encode,
decode,
Tokenizer
};