diff --git a/src/html/confirmation-modal.js b/src/html/confirmation-modal.js
index 2349489..298ffd1 100644
--- a/src/html/confirmation-modal.js
+++ b/src/html/confirmation-modal.js
@@ -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() {
diff --git a/src/html/home.js b/src/html/home.js
index 449a0c8..bc58957 100644
--- a/src/html/home.js
+++ b/src/html/home.js
@@ -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(
diff --git a/src/index.ts b/src/index.ts
index c5a6018..f057c04 100644
--- a/src/index.ts
+++ b/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);
diff --git a/src/services/database.ts b/src/services/database.ts
deleted file mode 100644
index a246429..0000000
--- a/src/services/database.ts
+++ /dev/null
@@ -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 {
- if (!Database.instance) {
- Database.instance = new Database();
- await Database.instance.init();
- }
- return Database.instance;
- }
-
- // Initialize the database
- private async init(): Promise {
- 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 {
- 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 {
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(storeName, 'readwrite');
- const store = transaction.objectStore(storeName);
- let request: IDBRequest;
- if (key) {
- request = store.add(obj, key);
- } else {
- request = store.add(obj);
- }
-
- request.onerror = () => reject(request.error);
- request.onsuccess = () => resolve(request.result);
- });
- }
-
- public getObject(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise {
- 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 {
- 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(db: IDBDatabase, storeName: string, indexName: string, lookup: string): Promise {
- 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 {
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(storeName, 'readwrite');
- const store = transaction.objectStore(storeName);
- let request: IDBRequest;
- if (key) {
- request = store.put(obj, key);
- } else {
- request = store.put(obj);
- }
-
- request.onerror = () => reject(request.error);
- request.onsuccess = () => resolve(request.result);
- });
- }
-
- public getAll(db: IDBDatabase, storeName: string): Promise {
- 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;
diff --git a/src/services/routing.service.ts b/src/services/routing.service.ts
index 204675e..8d362b2 100644
--- a/src/services/routing.service.ts
+++ b/src/services/routing.service.ts
@@ -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 {
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';
diff --git a/src/services/service.ts b/src/services/service.ts
index 40fabb4..a4f6c4e 100644
--- a/src/services/service.ts
+++ b/src/services/service.ts
@@ -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) {
diff --git a/src/websockets.ts b/src/websockets.ts
index d1b45f2..83236ed 100644
--- a/src/websockets.ts
+++ b/src/websockets.ts
@@ -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 {
diff --git a/vite.config.ts b/vite.config.ts
index 7a4c68a..4793531 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -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',
- }
},
});
\ No newline at end of file