WIP
This commit is contained in:
parent
76affefad9
commit
cfed50a226
@ -2,7 +2,7 @@ import Routing from "/src/services/routing.service.ts";
|
||||
|
||||
const router = await Routing.getInstance();
|
||||
export async function confirm() {
|
||||
router.confirm()
|
||||
router.confirmPairing()
|
||||
}
|
||||
|
||||
export async function closeConfirmationModal() {
|
||||
|
@ -58,30 +58,32 @@ docReady(function () {
|
||||
scanDevice();
|
||||
var resultContainer = document.getElementById('qr-reader-results');
|
||||
var lastResult, countResults = 0;
|
||||
function onScanSuccess(decodedText, decodedResult) {
|
||||
++countResults;
|
||||
lastResult = decodedText;
|
||||
// Handle on success condition with the decoded message.
|
||||
console.log(`Scan result ${decodedText}`, decodedResult);
|
||||
try {
|
||||
// Attempt to parse the decoded text as a URL
|
||||
const scannedUrl = new URL(decodedText);
|
||||
async function onScanSuccess(decodedText, decodedResult) {
|
||||
if (lastResult === decodedText) { return; }
|
||||
lastResult = decodedText;
|
||||
++countResults;
|
||||
// Handle on success condition with the decoded message.
|
||||
console.log(`Scan result ${decodedText}`, decodedResult);
|
||||
try {
|
||||
// Attempt to parse the decoded text as a URL
|
||||
const scannedUrl = new URL(decodedText);
|
||||
|
||||
// Extract the 'sp_address' parameter
|
||||
const spAddress = scannedUrl.searchParams.get('sp_address');
|
||||
// Extract the 'sp_address' parameter
|
||||
const spAddress = scannedUrl.searchParams.get('sp_address');
|
||||
|
||||
if (spAddress) {
|
||||
// Call the sendPairingTx function with the extracted sp_address
|
||||
service.sendPairingTx(spAddress);
|
||||
} else {
|
||||
console.error('The scanned URL does not contain the sp_address parameter.');
|
||||
alert('Invalid QR code: sp_address parameter missing.');
|
||||
}
|
||||
} catch (error) {
|
||||
// Handle cases where decodedText is not a valid URL
|
||||
console.error('Scanned text is not a valid URL:', error);
|
||||
alert('Invalid QR code: Unable to parse URL.');
|
||||
}
|
||||
if (spAddress) {
|
||||
html5QrcodeScanner.clear();
|
||||
// Call the sendPairingTx function with the extracted sp_address
|
||||
await service.sendPairingTx(spAddress);
|
||||
} else {
|
||||
console.error('The scanned URL does not contain the sp_address parameter.');
|
||||
alert('Invalid QR code: sp_address parameter missing.');
|
||||
}
|
||||
} catch (error) {
|
||||
// Handle cases where decodedText is not a valid URL
|
||||
console.error('Scanned text is not a valid URL:', error);
|
||||
alert('Invalid QR code: Unable to parse URL.');
|
||||
}
|
||||
}
|
||||
|
||||
var html5QrcodeScanner = new Html5QrcodeScanner(
|
||||
|
14
src/index.ts
14
src/index.ts
@ -15,14 +15,16 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
await services.restoreProcesses();
|
||||
await services.restoreMessages();
|
||||
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString)
|
||||
const pairingAddress = urlParams.get('sp_address')
|
||||
if (services.isPaired()) { await services.injectProcessListPage() }
|
||||
else {
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString)
|
||||
const pairingAddress = urlParams.get('sp_address')
|
||||
|
||||
if(pairingAddress) {
|
||||
await services.sendPairingTx(pairingAddress)
|
||||
if(pairingAddress) {
|
||||
await services.sendPairingTx(pairingAddress)
|
||||
}
|
||||
}
|
||||
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
@ -1,188 +0,0 @@
|
||||
class Database {
|
||||
private static instance: Database;
|
||||
private db: IDBDatabase | null = null;
|
||||
private dbName: string = '4nk';
|
||||
private dbVersion: number = 1;
|
||||
private storeDefinitions = {
|
||||
AnkUser: {
|
||||
name: "user",
|
||||
options: {'keyPath': 'pre_id'},
|
||||
indices: []
|
||||
},
|
||||
AnkSpAddress: {
|
||||
name: "address",
|
||||
options: {'keyPath': 'sp_address'},
|
||||
indices: []
|
||||
},
|
||||
AnkCipherMessages: {
|
||||
name: "ciphers",
|
||||
options: {},
|
||||
indices: [ {'keyPath': 'id'}]
|
||||
},
|
||||
AnkSession: {
|
||||
name: "session",
|
||||
options: {},
|
||||
indices: []
|
||||
},
|
||||
AnkProcess: {
|
||||
name: "process",
|
||||
options: {'keyPath': 'id'},
|
||||
indices: [{
|
||||
name: 'by_name',
|
||||
keyPath: 'name',
|
||||
options: {
|
||||
'unique': true
|
||||
}
|
||||
}]
|
||||
},
|
||||
AnkMessages: {
|
||||
name: "messages",
|
||||
options: {'keyPath': 'id'},
|
||||
indices: []
|
||||
}
|
||||
}
|
||||
|
||||
// Private constructor to prevent direct instantiation from outside
|
||||
private constructor() {}
|
||||
|
||||
// Method to access the singleton instance of Database
|
||||
public static async getInstance(): Promise<Database> {
|
||||
if (!Database.instance) {
|
||||
Database.instance = new Database();
|
||||
await Database.instance.init();
|
||||
}
|
||||
return Database.instance;
|
||||
}
|
||||
|
||||
// Initialize the database
|
||||
private async init(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open(this.dbName, this.dbVersion);
|
||||
|
||||
request.onupgradeneeded = () => {
|
||||
const db = request.result;
|
||||
|
||||
Object.values(this.storeDefinitions).forEach(({name, options, indices}) => {
|
||||
if (!db.objectStoreNames.contains(name)) {
|
||||
let store = db.createObjectStore(name, options);
|
||||
|
||||
indices.forEach(({name, keyPath, options}) => {
|
||||
store.createIndex(name, keyPath, options);
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
request.onsuccess = () => {
|
||||
this.db = request.result;
|
||||
resolve();
|
||||
};
|
||||
|
||||
request.onerror = () => {
|
||||
console.error("Database error:", request.error);
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async getDb(): Promise<IDBDatabase> {
|
||||
if (!this.db) {
|
||||
await this.init();
|
||||
}
|
||||
return this.db!;
|
||||
}
|
||||
|
||||
public getStoreList(): {[key: string]: string} {
|
||||
const objectList: {[key: string]: string} = {};
|
||||
Object.keys(this.storeDefinitions).forEach(key => {
|
||||
objectList[key] = this.storeDefinitions[key as keyof typeof this.storeDefinitions].name;
|
||||
});
|
||||
return objectList;
|
||||
}
|
||||
|
||||
public writeObject(db: IDBDatabase, storeName: string, obj: any, key: IDBValidKey | null): Promise<IDBRequest> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(storeName, 'readwrite');
|
||||
const store = transaction.objectStore(storeName);
|
||||
let request: IDBRequest<any>;
|
||||
if (key) {
|
||||
request = store.add(obj, key);
|
||||
} else {
|
||||
request = store.add(obj);
|
||||
}
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
});
|
||||
}
|
||||
|
||||
public getObject<T>(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(storeName, 'readonly');
|
||||
const store = transaction.objectStore(storeName);
|
||||
const request = store.get(key);
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
});
|
||||
}
|
||||
|
||||
public rmObject(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(storeName, 'readwrite');
|
||||
const store = transaction.objectStore(storeName);
|
||||
const request = store.delete(key);
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
});
|
||||
}
|
||||
|
||||
public getFirstMatchWithIndex<T>(db: IDBDatabase, storeName: string, indexName: string, lookup: string): Promise<T | null> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(storeName, 'readonly');
|
||||
const store = transaction.objectStore(storeName);
|
||||
const index = store.index(indexName);
|
||||
const request = index.openCursor(IDBKeyRange.only(lookup));
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => {
|
||||
const cursor = request.result;
|
||||
if (cursor) {
|
||||
resolve(cursor.value);
|
||||
} else {
|
||||
resolve(null)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public setObject(db: IDBDatabase, storeName: string, obj: any, key: string | null): Promise<IDBRequest> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(storeName, 'readwrite');
|
||||
const store = transaction.objectStore(storeName);
|
||||
let request: IDBRequest<any>;
|
||||
if (key) {
|
||||
request = store.put(obj, key);
|
||||
} else {
|
||||
request = store.put(obj);
|
||||
}
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
});
|
||||
}
|
||||
|
||||
public getAll<T>(db: IDBDatabase, storeName: string): Promise<T[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(storeName, 'readonly');
|
||||
const store = transaction.objectStore(storeName);
|
||||
const request = store.getAll();
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default Database;
|
@ -1,14 +1,13 @@
|
||||
import Database from './database';
|
||||
import modalHtml from '../html/login-modal.html?raw';
|
||||
import confirmationModalHtml from '../html/confirmation-modal.html?raw';
|
||||
import modalScript from '../html/login-modal.js?raw';
|
||||
import confirmationModalScript from '../html/confirmation-modal.js?raw';
|
||||
import Services from './service';
|
||||
import { U32_MAX } from './service';
|
||||
|
||||
|
||||
export default class Routing {
|
||||
private static instance: Routing;
|
||||
private database: any;
|
||||
private sdkClient: any;
|
||||
private currentPrd: any;
|
||||
private currentOutpoint?: string;
|
||||
@ -25,7 +24,6 @@ export default class Routing {
|
||||
|
||||
public async init(): Promise<void> {
|
||||
this.sdkClient = await import("../../dist/pkg/sdk_client");
|
||||
this.database = Database.getInstance()
|
||||
}
|
||||
|
||||
public openLoginModal(myAddress: string, receiverAddress: string) {
|
||||
@ -45,10 +43,18 @@ export default class Routing {
|
||||
}
|
||||
|
||||
public openConfirmationModal(pcd: any, outpointCommitment: string) {
|
||||
console.log("")
|
||||
let roles = JSON.parse(pcd['roles']);// ['members'][0];
|
||||
console.log(roles);
|
||||
let members = roles['owner']['members'];
|
||||
console.log(members);
|
||||
// We take all the addresses except our own
|
||||
const local_address = this.sdkClient.get_address();
|
||||
console.log("🚀 ~ Routing ~ openConfirmationModal ~ pcd:", pcd)
|
||||
let paired_addresses: string[] = [];
|
||||
for (const address of members[0]['sp_addresses']) {
|
||||
if (address !== local_address) { paired_addresses.push(address) }
|
||||
}
|
||||
let html = confirmationModalHtml;
|
||||
// html = html.replace('{{device1}}', members[0]['sp_addresses'][0]);
|
||||
// html = html.replace('{{device2}}', members[0]['sp_addresses'][1]);
|
||||
@ -65,11 +71,11 @@ export default class Routing {
|
||||
|
||||
// Add correct text
|
||||
|
||||
// Close modal when clicking outside of it
|
||||
// Close modal when clicking outside of it
|
||||
window.onclick = (event) => {
|
||||
const modal = document.getElementById('modal');
|
||||
if (event.target === modal) {
|
||||
this.confirm(pcd, outpointCommitment);
|
||||
this.confirmPairing(paired_addresses);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,13 +90,21 @@ export default class Routing {
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
async confirm(prd: any, outpointCommitment: string) {
|
||||
async confirmPairing(paired_addresses: string[]) {
|
||||
const service = await Services.getInstance()
|
||||
const modal = document.getElementById('modal')
|
||||
console.log("🚀 ~ Routing ~ confirm ~ prd:", prd, outpointCommitment)
|
||||
// console.log("🚀 ~ Routing ~ confirm ~ prd:", prd)
|
||||
if (modal) modal.style.display = 'none';
|
||||
await service.pairDevice(prd, outpointCommitment);
|
||||
}
|
||||
// Just make an empty commitment for now
|
||||
const emptyTxid = '0'.repeat(64)
|
||||
const commitmentOutpoint = `${emptyTxid}:${U32_MAX}`;
|
||||
|
||||
// We take the paired device(s) from the contract
|
||||
this.sdkClient.pair_device(commitmentOutpoint, paired_addresses)
|
||||
|
||||
service.injectProcessListPage();
|
||||
}
|
||||
|
||||
async closeConfirmationModal() {
|
||||
const modal = document.getElementById('modal')
|
||||
if (modal) modal.style.display = 'none';
|
||||
|
@ -16,7 +16,7 @@ type ProcessesCache = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
const U32_MAX = 4294967295;
|
||||
export const U32_MAX = 4294967295;
|
||||
const wsurl = `https://demo.4nkweb.com/ws/`;
|
||||
|
||||
export default class Services {
|
||||
@ -83,11 +83,6 @@ export default class Services {
|
||||
newScript.setAttribute('type', 'module')
|
||||
newScript.textContent = homeScript;
|
||||
document.head.appendChild(newScript).parentNode?.removeChild(newScript);
|
||||
|
||||
const btn = container.querySelector('#scan-this-device')
|
||||
if(btn) {
|
||||
this.addSubscription(btn, 'click', 'injectProcessListPage')
|
||||
}
|
||||
}
|
||||
|
||||
private generateQRCode = async (text: string) => {
|
||||
@ -103,6 +98,14 @@ export default class Services {
|
||||
}
|
||||
}
|
||||
|
||||
public isPaired(): boolean | undefined {
|
||||
try {
|
||||
return this.sdkClient.is_linking();
|
||||
} catch (e) {
|
||||
console.error("isPaired ~ Error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
private prepareProcessTx(myAddress: string, recipientAddress: string) {
|
||||
const initial_session_privkey = new Uint8Array(32);
|
||||
const initial_session_pubkey = new Uint8Array(32);
|
||||
@ -281,48 +284,48 @@ export default class Services {
|
||||
|
||||
async pairDevice(prd: any, outpointCommitment: string) {
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ prd:", prd)
|
||||
const service = await Services.getInstance();
|
||||
const spAddress = await this.getDeviceAddress() as any;
|
||||
const sender = JSON.parse(prd?.sender)
|
||||
const senderAddress = sender?.sp_addresses?.find((address: string) => address !== spAddress)
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ senderAddress:", senderAddress)
|
||||
if(senderAddress) {
|
||||
const proposal = service.sdkClient.get_update_proposals(outpointCommitment);
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ proposal:", proposal)
|
||||
// const pairingTx = proposal.pairing_tx.replace(/^\"+|\"+$/g, '')
|
||||
const parsedProposal = JSON.parse(proposal[0])
|
||||
// const service = await Services.getInstance();
|
||||
// const spAddress = await this.getDeviceAddress() as any;
|
||||
// const sender = JSON.parse(prd?.sender)
|
||||
// const senderAddress = sender?.sp_addresses?.find((address: string) => address !== spAddress)
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ senderAddress:", senderAddress)
|
||||
// if(senderAddress) {
|
||||
// const proposal = service.sdkClient.get_update_proposals(outpointCommitment);
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ proposal:", proposal)
|
||||
// // const pairingTx = proposal.pairing_tx.replace(/^\"+|\"+$/g, '')
|
||||
// const parsedProposal = JSON.parse(proposal[0])
|
||||
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ parsedProposal:", parsedProposal)
|
||||
const roles = JSON.parse(parsedProposal.roles)
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ roles:", roles, Array.isArray(roles), !roles.owner)
|
||||
if(Array.isArray(roles) || !roles.owner) return
|
||||
const proposalMembers = roles?.owner?.members
|
||||
const isFirstDevice = proposalMembers.some((member: Member) => member.sp_addresses.some(address => address === spAddress))
|
||||
const isSecondDevice = proposalMembers.some((member: Member) => member.sp_addresses.some(address => address === senderAddress))
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ proposalMembers:", proposalMembers)
|
||||
if(proposalMembers?.length !== 2 || !isFirstDevice || !isSecondDevice) return
|
||||
const pairingTx = parsedProposal?.pairing_tx?.replace(/^\"+|\"+$/g, '')
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ parsedProposal:", parsedProposal)
|
||||
// const roles = JSON.parse(parsedProposal.roles)
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ roles:", roles, Array.isArray(roles), !roles.owner)
|
||||
// if(Array.isArray(roles) || !roles.owner) return
|
||||
// const proposalMembers = roles?.owner?.members
|
||||
// const isFirstDevice = proposalMembers.some((member: Member) => member.sp_addresses.some(address => address === spAddress))
|
||||
// const isSecondDevice = proposalMembers.some((member: Member) => member.sp_addresses.some(address => address === senderAddress))
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ proposalMembers:", proposalMembers)
|
||||
// if(proposalMembers?.length !== 2 || !isFirstDevice || !isSecondDevice) return
|
||||
// const pairingTx = parsedProposal?.pairing_tx?.replace(/^\"+|\"+$/g, '')
|
||||
|
||||
let txid = '0'.repeat(64)
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ pairingTx:", pairingTx, `${txid}:4294967295`)
|
||||
// let txid = '0'.repeat(64)
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ pairingTx:", pairingTx, `${txid}:4294967295`)
|
||||
|
||||
const pairing = await service.sdkClient.pair_device(`${txid}:4294967295`, [senderAddress])
|
||||
const device = this.dumpDevice()
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ device:", device)
|
||||
this.saveDevice(device)
|
||||
// await service.sdkClient.pair_device(pairingTx, [senderAddress])
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ pairing:", pairing)
|
||||
// const process = await this.prepareProcessTx(spAddress, senderAddress)
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ process:", outpointCommitment, prd, prd.payload)
|
||||
const prdString = JSON.stringify(prd).trim()
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ prdString:", prdString)
|
||||
let tx = await service.sdkClient.response_prd(outpointCommitment, prdString, true)
|
||||
console.log("🚀 ~ Services ~ pairDevice ~ tx:", tx)
|
||||
if(tx.ciphers_to_send) {
|
||||
tx.ciphers_to_send.forEach((cipher: string) => service.websocketConnection?.sendMessage('Cipher', cipher))
|
||||
}
|
||||
this.injectProcessListPage()
|
||||
}
|
||||
// const pairing = await service.sdkClient.pair_device(`${txid}:4294967295`, [senderAddress])
|
||||
// const device = this.dumpDevice()
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ device:", device)
|
||||
// this.saveDevice(device)
|
||||
// // await service.sdkClient.pair_device(pairingTx, [senderAddress])
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ pairing:", pairing)
|
||||
// // const process = await this.prepareProcessTx(spAddress, senderAddress)
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ process:", outpointCommitment, prd, prd.payload)
|
||||
// const prdString = JSON.stringify(prd).trim()
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ prdString:", prdString)
|
||||
// let tx = await service.sdkClient.response_prd(outpointCommitment, prdString, true)
|
||||
// console.log("🚀 ~ Services ~ pairDevice ~ tx:", tx)
|
||||
// if(tx.ciphers_to_send) {
|
||||
// tx.ciphers_to_send.forEach((cipher: string) => service.websocketConnection?.sendMessage('Cipher', cipher))
|
||||
// }
|
||||
// this.injectProcessListPage()
|
||||
// }
|
||||
}
|
||||
|
||||
// async saveTxToDb(tx: CachedMessage) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { AnkFlag, CachedMessage } from "dist/pkg/sdk_client";
|
||||
import Services from "./services/service";
|
||||
import Database from "./services/database";
|
||||
// import { AnkFlag, AnkNetworkMsg, CachedMessage } from "../dist/pkg/sdk_client";
|
||||
|
||||
class WebSocketClient {
|
||||
|
@ -38,9 +38,5 @@ export default defineConfig({
|
||||
open: false,
|
||||
port: 3001,
|
||||
strictPort: true, // Empêche de changer de port si le 3001 est occupé
|
||||
hmr: {
|
||||
port: 9050, // Assure que le WebSocket HMR utilise bien le même port
|
||||
protocol: 'wss',
|
||||
}
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user