@thezelijah/majik-message 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +67 -0
- package/README.md +265 -0
- package/dist/core/contacts/majik-contact-directory.d.ts +34 -0
- package/dist/core/contacts/majik-contact-directory.js +165 -0
- package/dist/core/contacts/majik-contact.d.ts +53 -0
- package/dist/core/contacts/majik-contact.js +135 -0
- package/dist/core/crypto/constants.d.ts +7 -0
- package/dist/core/crypto/constants.js +6 -0
- package/dist/core/crypto/crypto-provider.d.ts +20 -0
- package/dist/core/crypto/crypto-provider.js +70 -0
- package/dist/core/crypto/encryption-engine.d.ts +59 -0
- package/dist/core/crypto/encryption-engine.js +257 -0
- package/dist/core/crypto/keystore.d.ts +126 -0
- package/dist/core/crypto/keystore.js +575 -0
- package/dist/core/messages/envelope-cache.d.ts +51 -0
- package/dist/core/messages/envelope-cache.js +375 -0
- package/dist/core/messages/message-envelope.d.ts +36 -0
- package/dist/core/messages/message-envelope.js +161 -0
- package/dist/core/scanner/scanner-engine.d.ts +27 -0
- package/dist/core/scanner/scanner-engine.js +120 -0
- package/dist/core/types.d.ts +23 -0
- package/dist/core/types.js +1 -0
- package/dist/core/utils/APITranscoder.d.ts +114 -0
- package/dist/core/utils/APITranscoder.js +305 -0
- package/dist/core/utils/idb-majik-system.d.ts +15 -0
- package/dist/core/utils/idb-majik-system.js +37 -0
- package/dist/core/utils/majik-file-utils.d.ts +16 -0
- package/dist/core/utils/majik-file-utils.js +153 -0
- package/dist/core/utils/utilities.d.ts +22 -0
- package/dist/core/utils/utilities.js +80 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/majik-message.d.ts +202 -0
- package/dist/majik-message.js +940 -0
- package/package.json +97 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import APITranscoder from "./APITranscoder";
|
|
2
|
+
export async function importMajikFileData(file) {
|
|
3
|
+
if (!file)
|
|
4
|
+
throw new Error("Invalid file.");
|
|
5
|
+
if (!file.name.endsWith(".mjkb")) {
|
|
6
|
+
throw new Error("Oops! Only .mjkb files are allowed. Please load a valid MajikFile.");
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
// Step 1: Read as base64 text
|
|
10
|
+
const base64String = (await readBlobFile(file));
|
|
11
|
+
// Step 2: base64 → JSON
|
|
12
|
+
const jsonString = base64DecodeUtf8(base64String);
|
|
13
|
+
const parsedData = JSON.parse(jsonString);
|
|
14
|
+
// Step 3: Decrypt
|
|
15
|
+
const decryptedData = APITranscoder.decryptPayload(parsedData);
|
|
16
|
+
return decryptedData;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error("Import Error:", error);
|
|
20
|
+
throw new Error("Failed to import and decrypt .mjkb file.");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function loadSavedMajikFileData(file) {
|
|
24
|
+
try {
|
|
25
|
+
const content = await readBlobFile(file);
|
|
26
|
+
// Step 2: base64 → UTF-8 JSON string
|
|
27
|
+
const jsonString = base64DecodeUtf8(content);
|
|
28
|
+
// Step 3: Parse encrypted payload
|
|
29
|
+
const parsedData = JSON.parse(jsonString);
|
|
30
|
+
const decryptedData = APITranscoder.decryptPayload(parsedData);
|
|
31
|
+
const MajikFileData = decryptedData;
|
|
32
|
+
return MajikFileData;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error("Loading Autosaved File Error: ", error);
|
|
36
|
+
throw new Error("Failed to load autosaved .MajikFile file.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function autoSaveMajikFileData(json, version = "1.0.0") {
|
|
40
|
+
const rawData = {
|
|
41
|
+
j: json,
|
|
42
|
+
s: secureTimecode(),
|
|
43
|
+
v: version,
|
|
44
|
+
};
|
|
45
|
+
const generatedRQC = APITranscoder.generateRQC();
|
|
46
|
+
const encryptedData = APITranscoder.encryptPayload(rawData, generatedRQC);
|
|
47
|
+
const dataString = JSON.stringify(encryptedData);
|
|
48
|
+
// 🔐 Convert JSON string to base64
|
|
49
|
+
const base64Encoded = base64EncodeUtf8(dataString);
|
|
50
|
+
const blobData = prepareToBlobFile(base64Encoded);
|
|
51
|
+
return blobData;
|
|
52
|
+
}
|
|
53
|
+
export function exportMajikFileData(json, name, version = "1.0.0") {
|
|
54
|
+
const rawData = {
|
|
55
|
+
j: json,
|
|
56
|
+
s: secureTimecode(),
|
|
57
|
+
v: version,
|
|
58
|
+
};
|
|
59
|
+
const generatedRQC = APITranscoder.generateRQC();
|
|
60
|
+
const encryptedData = APITranscoder.encryptPayload(rawData, generatedRQC);
|
|
61
|
+
const dataString = JSON.stringify(encryptedData);
|
|
62
|
+
// 🔐 Convert JSON string to base64
|
|
63
|
+
const base64Encoded = base64EncodeUtf8(dataString);
|
|
64
|
+
const blobData = prepareToBlobFile(base64Encoded);
|
|
65
|
+
downloadBlob(blobData, "MajikFile", name);
|
|
66
|
+
}
|
|
67
|
+
// Prepare Blob file from various input types
|
|
68
|
+
export function prepareToBlobFile(data) {
|
|
69
|
+
return new Blob([data], { type: "text/plain" });
|
|
70
|
+
}
|
|
71
|
+
// Download Blob file
|
|
72
|
+
function downloadBlob(blob, filetype, fileName) {
|
|
73
|
+
const file = new File([blob], `${fileName}.${filetype}`, { type: blob.type });
|
|
74
|
+
const tryShare = async () => {
|
|
75
|
+
if (typeof navigator !== "undefined" &&
|
|
76
|
+
navigator.canShare &&
|
|
77
|
+
navigator.canShare({ files: [file] })) {
|
|
78
|
+
try {
|
|
79
|
+
await navigator.share({
|
|
80
|
+
files: [file],
|
|
81
|
+
title: fileName,
|
|
82
|
+
text: `Download ${fileName}.${filetype}`,
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.warn("Share not supported in desktop:", error);
|
|
88
|
+
// Fallback continues
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Fallback to download
|
|
92
|
+
const url = URL.createObjectURL(blob);
|
|
93
|
+
const a = document.createElement("a");
|
|
94
|
+
a.href = url;
|
|
95
|
+
a.download = `${fileName}.${filetype}`;
|
|
96
|
+
document.body.appendChild(a);
|
|
97
|
+
a.click();
|
|
98
|
+
document.body.removeChild(a);
|
|
99
|
+
URL.revokeObjectURL(url);
|
|
100
|
+
};
|
|
101
|
+
// Ensure it's wrapped in a user-triggered event like a button click
|
|
102
|
+
void tryShare();
|
|
103
|
+
}
|
|
104
|
+
// Read Blob file and decode its content
|
|
105
|
+
function readBlobFile(blob) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
const reader = new FileReader();
|
|
108
|
+
reader.onload = () => resolve(reader.result);
|
|
109
|
+
reader.onerror = () => reject(new Error("Error reading file"));
|
|
110
|
+
reader.readAsText(blob);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Converts a Unix timestamp, Date object, ISO string, or null/undefined into a secure Base64 string.
|
|
115
|
+
* Defaults to the current time if input is null or undefined.
|
|
116
|
+
*
|
|
117
|
+
* @param {(number | Date | string | null | undefined)} input - The time input.
|
|
118
|
+
* @returns {string} A secure Base64 encoded string generated from the timestamp.
|
|
119
|
+
* @throws {Error} Throws an error if the input is not a valid time format.
|
|
120
|
+
*/
|
|
121
|
+
function secureTimecode(input) {
|
|
122
|
+
const unixTimestamp = (() => {
|
|
123
|
+
if (input === null || input === undefined)
|
|
124
|
+
return Math.floor(Date.now() / 1000);
|
|
125
|
+
if (typeof input === "number")
|
|
126
|
+
return input;
|
|
127
|
+
if (input instanceof Date)
|
|
128
|
+
return Math.floor(input.getTime() / 1000);
|
|
129
|
+
if (typeof input === "string")
|
|
130
|
+
return Math.floor(new Date(input).getTime() / 1000);
|
|
131
|
+
throw new Error("Invalid input type. Must be Unix timestamp, Date object, or ISO string.");
|
|
132
|
+
})();
|
|
133
|
+
const unixArray = Array.from(String(unixTimestamp), Number);
|
|
134
|
+
const reversedArray = [...unixArray].reverse();
|
|
135
|
+
const invertedArray = [];
|
|
136
|
+
for (let i = 0; i < unixArray.length; i++) {
|
|
137
|
+
invertedArray.push(unixArray[i], reversedArray[i]);
|
|
138
|
+
}
|
|
139
|
+
return btoa(String.fromCharCode(...invertedArray));
|
|
140
|
+
}
|
|
141
|
+
export function base64EncodeUtf8(str) {
|
|
142
|
+
const bytes = new TextEncoder().encode(str);
|
|
143
|
+
let binary = "";
|
|
144
|
+
bytes.forEach((b) => {
|
|
145
|
+
binary += String.fromCharCode(b);
|
|
146
|
+
});
|
|
147
|
+
return btoa(binary);
|
|
148
|
+
}
|
|
149
|
+
export function base64DecodeUtf8(base64) {
|
|
150
|
+
const binary = atob(base64);
|
|
151
|
+
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
152
|
+
return new TextDecoder().decode(bytes);
|
|
153
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare function arrayToBase64(data: Uint8Array): string;
|
|
2
|
+
export declare function base64ToUint8Array(base64: string): Uint8Array;
|
|
3
|
+
export declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
4
|
+
export declare function base64ToArrayBuffer(base64: string): ArrayBuffer;
|
|
5
|
+
export declare function base64ToUtf8(base64: string): string;
|
|
6
|
+
export declare function utf8ToBase64(str: string): string;
|
|
7
|
+
export declare function concatArrayBuffers(a: ArrayBuffer, b: ArrayBuffer): ArrayBuffer;
|
|
8
|
+
export declare function concatUint8Arrays(a: Uint8Array, b: Uint8Array): Uint8Array;
|
|
9
|
+
export interface MnemonicJSON {
|
|
10
|
+
seed: string[];
|
|
11
|
+
id: string;
|
|
12
|
+
phrase?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Converts a space-separated seed phrase string into MnemonicJSON
|
|
16
|
+
*/
|
|
17
|
+
export declare function seedToJSON(seed: string, id: string, phrase?: string): MnemonicJSON;
|
|
18
|
+
/**
|
|
19
|
+
* Converts MnemonicJSON into a single space-separated string
|
|
20
|
+
*/
|
|
21
|
+
export declare function jsonToSeed(json: MnemonicJSON): string;
|
|
22
|
+
export declare function seedStringToArray(seed: string): string[];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* ================================
|
|
2
|
+
* Utilities
|
|
3
|
+
* ================================ */
|
|
4
|
+
// utils/utilities.ts
|
|
5
|
+
export function arrayToBase64(data) {
|
|
6
|
+
let binary = "";
|
|
7
|
+
const bytes = data;
|
|
8
|
+
const len = bytes.byteLength;
|
|
9
|
+
for (let i = 0; i < len; i++) {
|
|
10
|
+
binary += String.fromCharCode(bytes[i]);
|
|
11
|
+
}
|
|
12
|
+
return btoa(binary);
|
|
13
|
+
}
|
|
14
|
+
export function base64ToUint8Array(base64) {
|
|
15
|
+
return new Uint8Array(base64ToArrayBuffer(base64));
|
|
16
|
+
}
|
|
17
|
+
export function arrayBufferToBase64(buffer) {
|
|
18
|
+
const bytes = new Uint8Array(buffer);
|
|
19
|
+
let binary = "";
|
|
20
|
+
const chunkSize = 0x8000;
|
|
21
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
22
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
23
|
+
}
|
|
24
|
+
return btoa(binary);
|
|
25
|
+
}
|
|
26
|
+
export function base64ToArrayBuffer(base64) {
|
|
27
|
+
const binary = atob(base64);
|
|
28
|
+
const bytes = new Uint8Array(binary.length);
|
|
29
|
+
for (let i = 0; i < binary.length; i++) {
|
|
30
|
+
bytes[i] = binary.charCodeAt(i);
|
|
31
|
+
}
|
|
32
|
+
return bytes.buffer;
|
|
33
|
+
}
|
|
34
|
+
export function base64ToUtf8(base64) {
|
|
35
|
+
const buf = base64ToArrayBuffer(base64);
|
|
36
|
+
return new TextDecoder().decode(new Uint8Array(buf));
|
|
37
|
+
}
|
|
38
|
+
export function utf8ToBase64(str) {
|
|
39
|
+
const bytes = new TextEncoder().encode(str);
|
|
40
|
+
return arrayBufferToBase64(bytes.buffer);
|
|
41
|
+
}
|
|
42
|
+
export function concatArrayBuffers(a, b) {
|
|
43
|
+
const tmp = new Uint8Array(a.byteLength + b.byteLength);
|
|
44
|
+
tmp.set(new Uint8Array(a), 0);
|
|
45
|
+
tmp.set(new Uint8Array(b), a.byteLength);
|
|
46
|
+
return tmp.buffer;
|
|
47
|
+
}
|
|
48
|
+
export function concatUint8Arrays(a, b) {
|
|
49
|
+
const out = new Uint8Array(a.byteLength + b.byteLength);
|
|
50
|
+
out.set(a, 0);
|
|
51
|
+
out.set(b, a.byteLength);
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Converts a space-separated seed phrase string into MnemonicJSON
|
|
56
|
+
*/
|
|
57
|
+
export function seedToJSON(seed, id, phrase) {
|
|
58
|
+
return {
|
|
59
|
+
seed: seed
|
|
60
|
+
.trim()
|
|
61
|
+
.split(/\s+/)
|
|
62
|
+
.map((w) => w.toLowerCase())
|
|
63
|
+
.filter(Boolean),
|
|
64
|
+
id,
|
|
65
|
+
phrase,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Converts MnemonicJSON into a single space-separated string
|
|
70
|
+
*/
|
|
71
|
+
export function jsonToSeed(json) {
|
|
72
|
+
return json.seed.join(" ");
|
|
73
|
+
}
|
|
74
|
+
export function seedStringToArray(seed) {
|
|
75
|
+
return seed
|
|
76
|
+
.trim()
|
|
77
|
+
.split(/\s+/)
|
|
78
|
+
.map((w) => w.toLowerCase())
|
|
79
|
+
.filter(Boolean);
|
|
80
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./majik-message";
|
|
2
|
+
export type * from "./core/types";
|
|
3
|
+
export * from "./core/contacts/majik-contact";
|
|
4
|
+
export * from "./core/contacts/majik-contact-directory";
|
|
5
|
+
export * from "./core/crypto/constants";
|
|
6
|
+
export * from "./core/crypto/crypto-provider";
|
|
7
|
+
export * from "./core/crypto/encryption-engine";
|
|
8
|
+
export * from "./core/crypto/keystore";
|
|
9
|
+
export * from "./core/messages/message-envelope";
|
|
10
|
+
export * from "./core/messages/envelope-cache";
|
|
11
|
+
export * from "./core/scanner/scanner-engine";
|
|
12
|
+
export * from "./core/utils/APITranscoder";
|
|
13
|
+
export * from "./core/utils/utilities";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./majik-message";
|
|
2
|
+
export * from "./core/contacts/majik-contact";
|
|
3
|
+
export * from "./core/contacts/majik-contact-directory";
|
|
4
|
+
export * from "./core/crypto/constants";
|
|
5
|
+
export * from "./core/crypto/crypto-provider";
|
|
6
|
+
export * from "./core/crypto/encryption-engine";
|
|
7
|
+
export * from "./core/crypto/keystore";
|
|
8
|
+
export * from "./core/messages/message-envelope";
|
|
9
|
+
export * from "./core/messages/envelope-cache";
|
|
10
|
+
export * from "./core/scanner/scanner-engine";
|
|
11
|
+
export * from "./core/utils/APITranscoder";
|
|
12
|
+
export * from "./core/utils/utilities";
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { MajikContact, type MajikContactMeta, type SerializedMajikContact } from "./core/contacts/majik-contact";
|
|
2
|
+
import { MessageEnvelope } from "./core/messages/message-envelope";
|
|
3
|
+
import { EnvelopeCache, type EnvelopeCacheItem, type EnvelopeCacheJSON } from "./core/messages/envelope-cache";
|
|
4
|
+
import { KeyStore } from "./core/crypto/keystore";
|
|
5
|
+
import { MajikContactDirectory, type MajikContactDirectoryData } from "./core/contacts/majik-contact-directory";
|
|
6
|
+
import type { MAJIK_API_RESPONSE } from "./core/types";
|
|
7
|
+
type MajikMessageEvents = "message" | "envelope" | "untrusted" | "error";
|
|
8
|
+
export interface MajikMessageConfig {
|
|
9
|
+
keyStore: KeyStore;
|
|
10
|
+
contactDirectory?: MajikContactDirectory;
|
|
11
|
+
envelopeCache?: EnvelopeCache;
|
|
12
|
+
}
|
|
13
|
+
export interface MajikMessageJSON {
|
|
14
|
+
id: string;
|
|
15
|
+
contacts: MajikContactDirectoryData;
|
|
16
|
+
envelopeCache: EnvelopeCacheJSON;
|
|
17
|
+
ownAccounts?: {
|
|
18
|
+
accounts: SerializedMajikContact[];
|
|
19
|
+
order: string[];
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
type EventCallback = (...args: any[]) => void;
|
|
23
|
+
export declare class MajikMessage {
|
|
24
|
+
private pinHash?;
|
|
25
|
+
private id;
|
|
26
|
+
private contactDirectory;
|
|
27
|
+
private envelopeCache;
|
|
28
|
+
private scanner;
|
|
29
|
+
private listeners;
|
|
30
|
+
private ownAccounts;
|
|
31
|
+
private ownAccountsOrder;
|
|
32
|
+
private autosaveTimer;
|
|
33
|
+
private autosaveIntervalMs;
|
|
34
|
+
private autosaveDebounceMs;
|
|
35
|
+
constructor(config: MajikMessageConfig, id?: string);
|
|
36
|
+
/**
|
|
37
|
+
* Create a new account (generates identity via KeyStore) and add it as an own account.
|
|
38
|
+
* Returns the created identity id and a backup blob (base64) that the user should store.
|
|
39
|
+
*/
|
|
40
|
+
createAccount(passphrase: string, label?: string): Promise<{
|
|
41
|
+
id: string;
|
|
42
|
+
fingerprint: string;
|
|
43
|
+
backup: string;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Import an account from a backup blob (created with `exportIdentityBackup`) and unlock it.
|
|
47
|
+
*/
|
|
48
|
+
importAccountFromBackup(backupBase64: string, passphrase: string, label?: string): Promise<{
|
|
49
|
+
id: string;
|
|
50
|
+
fingerprint: string;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* Generate a BIP39 mnemonic for backup (12 words by default).
|
|
54
|
+
*/
|
|
55
|
+
generateMnemonic(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Export a mnemonic-encrypted backup for an unlocked identity.
|
|
58
|
+
*/
|
|
59
|
+
exportAccountMnemonicBackup(id: string, mnemonic: string): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Import an account from a mnemonic-encrypted backup blob and store it using `passphrase`.
|
|
62
|
+
*/
|
|
63
|
+
importAccountFromMnemonicBackup(backupBase64: string, mnemonic: string, passphrase: string, label?: string): Promise<{
|
|
64
|
+
id: string;
|
|
65
|
+
fingerprint: string;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Create a new account deterministically from `mnemonic` and store it encrypted with `passphrase`.
|
|
69
|
+
* Returns the created identity id (which equals fingerprint) and fingerprint.
|
|
70
|
+
*/
|
|
71
|
+
createAccountFromMnemonic(mnemonic: string, passphrase: string, label?: string): Promise<{
|
|
72
|
+
id: string;
|
|
73
|
+
fingerprint: string;
|
|
74
|
+
backup: string;
|
|
75
|
+
}>;
|
|
76
|
+
addOwnAccount(account: MajikContact): void;
|
|
77
|
+
listOwnAccounts(): MajikContact[];
|
|
78
|
+
getOwnAccountById(id: string): MajikContact | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Set an active account (moves it to index 0)
|
|
81
|
+
*/
|
|
82
|
+
setActiveAccount(id: string): boolean;
|
|
83
|
+
getActiveAccount(): MajikContact | null;
|
|
84
|
+
isAccountActive(id: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Remove an own account from the in-memory registry.
|
|
87
|
+
*/
|
|
88
|
+
removeOwnAccount(id: string): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Retrieve a contact from the directory by ID.
|
|
91
|
+
* Validates that the input is a non-empty string.
|
|
92
|
+
* Returns the MajikContact instance or null if not found.
|
|
93
|
+
*/
|
|
94
|
+
getContactByID(id: string): MajikContact | null;
|
|
95
|
+
/**
|
|
96
|
+
* Returns a JSON string representation of a contact
|
|
97
|
+
* suitable for sharing.
|
|
98
|
+
*/
|
|
99
|
+
exportContactAsJSON(contactId: string): Promise<string | null>;
|
|
100
|
+
/**
|
|
101
|
+
* Returns a compact base64 string for sharing a contact.
|
|
102
|
+
* Encodes JSON payload into base64.
|
|
103
|
+
*/
|
|
104
|
+
exportContactAsString(contactId: string): Promise<string | null>;
|
|
105
|
+
importContactFromJSON(jsonStr: string): Promise<MAJIK_API_RESPONSE>;
|
|
106
|
+
/**
|
|
107
|
+
* List cached envelopes stored in the local cache (most recent first).
|
|
108
|
+
* Returns objects: { id, envelope, timestamp, source }
|
|
109
|
+
*/
|
|
110
|
+
listCachedEnvelopes(offset?: number, limit?: number): Promise<EnvelopeCacheItem[]>;
|
|
111
|
+
/**
|
|
112
|
+
* Clear cached envelopes stored in the local cache.
|
|
113
|
+
*/
|
|
114
|
+
clearCachedEnvelopes(): Promise<boolean>;
|
|
115
|
+
hasOwnIdentity(fingerprint: string): Promise<boolean>;
|
|
116
|
+
/**
|
|
117
|
+
* Attempt to decrypt a given envelope and return the plaintext string.
|
|
118
|
+
* Will prompt to unlock identity if necessary.
|
|
119
|
+
*/
|
|
120
|
+
decryptEnvelope(envelope: MessageEnvelope, bypassIdentity?: boolean): Promise<string>;
|
|
121
|
+
importContactFromString(base64Str: string): Promise<void>;
|
|
122
|
+
addContact(contact: MajikContact): void;
|
|
123
|
+
removeContact(id: string): void;
|
|
124
|
+
updateContactMeta(id: string, meta: Partial<MajikContactMeta>): void;
|
|
125
|
+
blockContact(id: string): void;
|
|
126
|
+
unblockContact(id: string): void;
|
|
127
|
+
listContacts(all?: boolean): MajikContact[];
|
|
128
|
+
/**
|
|
129
|
+
* Update the passphrase for an identity.
|
|
130
|
+
* - `id` defaults to the current active account if not provided.
|
|
131
|
+
* - Throws if no active account exists or passphrase is invalid.
|
|
132
|
+
*/
|
|
133
|
+
updatePassphrase(currentPassphrase: string, newPassphrase: string, id?: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Encrypts a plaintext message for a single recipient (solo message)
|
|
136
|
+
* Returns a MessageEnvelope instance and caches it automatically.
|
|
137
|
+
*/
|
|
138
|
+
encryptSoloMessage(toId: string, plaintext: string, cache?: boolean): Promise<MessageEnvelope>;
|
|
139
|
+
/**
|
|
140
|
+
* Encrypts a plaintext message for a group of recipients.
|
|
141
|
+
* Returns a unified group MessageEnvelope instance.
|
|
142
|
+
*/
|
|
143
|
+
encryptGroupMessage(recipientIds: string[], plaintext: string, cache?: boolean): Promise<MessageEnvelope>;
|
|
144
|
+
sendMessage(recipients: string[], plaintext: string): Promise<MessageEnvelope>;
|
|
145
|
+
/**
|
|
146
|
+
* Encrypts currently selected text in the browser DOM for given recipients.
|
|
147
|
+
* If `recipients` is empty, defaults to the first own account.
|
|
148
|
+
* Returns the fully serialized base64 envelope string for the scanner.
|
|
149
|
+
*/
|
|
150
|
+
encryptSelectedTextForScanner(recipients?: string[]): Promise<string | null>;
|
|
151
|
+
/**
|
|
152
|
+
* Encrypt a provided plaintext string and return a serialized MajikMessage envelope string.
|
|
153
|
+
* Supports single or multiple recipients. Safe to call from background contexts.
|
|
154
|
+
*/
|
|
155
|
+
encryptTextForScanner(plaintext: string, recipients?: string[], cache?: boolean): Promise<string | null>;
|
|
156
|
+
/**
|
|
157
|
+
* Encrypt text for a given target (label or ID).
|
|
158
|
+
* - If target is self or not found, just encrypt normally.
|
|
159
|
+
* - If target is another contact, always make a group message including self + target.
|
|
160
|
+
*/
|
|
161
|
+
encryptForTarget(target: string, // can be label or id
|
|
162
|
+
plaintext: string): Promise<string | null>;
|
|
163
|
+
scanDOM(rootNode: Node): void;
|
|
164
|
+
startDOMObserver(rootNode: Node): void;
|
|
165
|
+
stopDOMObserver(): void;
|
|
166
|
+
on(event: MajikMessageEvents, callback: EventCallback): void;
|
|
167
|
+
private emit;
|
|
168
|
+
private handleEnvelope;
|
|
169
|
+
/**
|
|
170
|
+
* Ensure an identity is unlocked. If locked, prompt the user for a passphrase.
|
|
171
|
+
* `promptFn` can be provided to show a custom UI: either synchronous returning string
|
|
172
|
+
* or async Promise<string>. If omitted, falls back to `window.prompt`.
|
|
173
|
+
*/
|
|
174
|
+
ensureIdentityUnlocked(id: string, promptFn?: (identityId: string) => string | Promise<string>): Promise<CryptoKey | {
|
|
175
|
+
raw: Uint8Array;
|
|
176
|
+
}>;
|
|
177
|
+
isPassphraseValid(passphrase: string, id?: string): Promise<boolean>;
|
|
178
|
+
toJSON(): Promise<MajikMessageJSON>;
|
|
179
|
+
static fromJSON(json: MajikMessageJSON): Promise<MajikMessage>;
|
|
180
|
+
/**
|
|
181
|
+
* Set a PIN (stores hash). Passphrase is any string; we store SHA-256(base64) of it.
|
|
182
|
+
*/
|
|
183
|
+
setPIN(pin: string): Promise<void>;
|
|
184
|
+
clearPIN(): Promise<void>;
|
|
185
|
+
isValidPIN(pin: string): Promise<boolean>;
|
|
186
|
+
getPinHash(): string | null;
|
|
187
|
+
private static hashPIN;
|
|
188
|
+
private autosaveIntervalId;
|
|
189
|
+
private attachAutosaveHandlers;
|
|
190
|
+
startAutosave(): void;
|
|
191
|
+
stopAutosave(): void;
|
|
192
|
+
private scheduleAutosave;
|
|
193
|
+
/** Save current state into IndexedDB (autosave). */
|
|
194
|
+
saveState(): Promise<void>;
|
|
195
|
+
/** Load state from IndexedDB and apply to this instance. */
|
|
196
|
+
loadState(): Promise<void>;
|
|
197
|
+
/**
|
|
198
|
+
* Try to load an existing state from IDB; if none exists, create a fresh instance and save it.
|
|
199
|
+
*/
|
|
200
|
+
static loadOrCreate(config: MajikMessageConfig): Promise<MajikMessage>;
|
|
201
|
+
}
|
|
202
|
+
export {};
|