merge_code
This commit is contained in:
commit
b50d244d84
@ -34,4 +34,4 @@
|
||||
<div id="emoji-display-2"></div>
|
||||
<button id="okButton" style="display: none">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -55,7 +55,15 @@ async function onScanSuccess(decodedText: any, decodedResult: any) {
|
||||
html5QrcodeScanner.clear();
|
||||
const service = await Services.getInstance();
|
||||
// Call the sendPairingTx function with the extracted sp_address
|
||||
await service.sendPairingTx(spAddress);
|
||||
try {
|
||||
const member = {
|
||||
sp_addresses: [spAddress],
|
||||
}
|
||||
await service.connectMember([member]);
|
||||
// await service.sendPairingTx(spAddress);
|
||||
} catch (e) {
|
||||
console.error('Failed to pair:', e);
|
||||
}
|
||||
} else {
|
||||
console.error('The scanned URL does not contain the sp_address parameter.');
|
||||
alert('Invalid QR code: sp_address parameter missing.');
|
||||
|
@ -104,7 +104,6 @@ async function init(): Promise<void> {
|
||||
await services.restoreDevice(device);
|
||||
}
|
||||
await services.restoreProcesses();
|
||||
await services.restoreMessages();
|
||||
|
||||
if (services.isPaired()) {
|
||||
await navigate('process');
|
||||
@ -113,7 +112,14 @@ async function init(): Promise<void> {
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const pairingAddress = urlParams.get('sp_address');
|
||||
if (pairingAddress) {
|
||||
setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000);
|
||||
setTimeout(async () => {
|
||||
// await services.sendPairingTx(pairingAddress)
|
||||
try {
|
||||
await services.connectMember([{sp_addresses: [pairingAddress]}]);
|
||||
} catch (e) {
|
||||
console.error('Failed to pair:', e);
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
await navigate('home');
|
||||
}
|
||||
|
20
src/service-workers/cache.worker.js
Normal file
20
src/service-workers/cache.worker.js
Normal file
@ -0,0 +1,20 @@
|
||||
const addResourcesToCache = async (resources) => {
|
||||
const cache = await caches.open("v1");
|
||||
await cache.addAll(resources);
|
||||
};
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
event.waitUntil(
|
||||
addResourcesToCache([
|
||||
"/",
|
||||
"/index.html",
|
||||
"/style.css",
|
||||
"/app.js",
|
||||
"/image-list.js",
|
||||
"/star-wars-logo.jpg",
|
||||
"/gallery/bountyHunters.jpg",
|
||||
"/gallery/myLittleVader.jpg",
|
||||
"/gallery/snowTroopers.jpg",
|
||||
]),
|
||||
);
|
||||
});
|
@ -1,5 +1,3 @@
|
||||
import Database from '../services/database.service';
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(self.skipWaiting()); // Activate worker immediately
|
||||
});
|
||||
@ -11,7 +9,6 @@ self.addEventListener('activate', (event) => {
|
||||
// Event listener for messages from clients
|
||||
self.addEventListener('message', async (event) => {
|
||||
const data = event.data;
|
||||
const db = await Database.getInstance();
|
||||
|
||||
if (data.type === 'ADD_OBJECT') {
|
||||
try {
|
||||
@ -19,26 +16,18 @@ self.addEventListener('message', async (event) => {
|
||||
const db = await openDatabase();
|
||||
const tx = db.transaction(storeName, 'readwrite');
|
||||
const store = tx.objectStore(storeName);
|
||||
await store.put(object);
|
||||
event.ports[0].postMessage({ status: 'success', message: 'Object added or replaced successfully' });
|
||||
|
||||
if (key) {
|
||||
await store.put(object, key);
|
||||
} else {
|
||||
await store.put(object);
|
||||
}
|
||||
|
||||
event.ports[0].postMessage({ status: 'success', message: '' });
|
||||
} catch (error) {
|
||||
event.ports[0].postMessage({ status: 'error', message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
if (data.type === 'GET_OBJECT') {
|
||||
const { storeName, key } = data.payload;
|
||||
const db = await openDatabase();
|
||||
const tx = db.transaction(storeName, 'readonly');
|
||||
const store = tx.objectStore(storeName);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
const getRequest = store.get(key);
|
||||
getRequest.onsuccess = (event) => resolve(getRequest.result);
|
||||
getRequest.onerror = (event) => reject(getRequest.error);
|
||||
});
|
||||
|
||||
event.ports[0].postMessage({ type: 'GET_OBJECT_RESULT', payload: result });
|
||||
}
|
||||
});
|
||||
|
||||
async function openDatabase() {
|
||||
|
@ -17,9 +17,14 @@ class Database {
|
||||
options: { keyPath: 'id' },
|
||||
indices: [],
|
||||
},
|
||||
AnkMessages: {
|
||||
name: 'messages',
|
||||
options: { keyPath: 'id' },
|
||||
AnkSharedSecrets: {
|
||||
name: 'shared_secrets',
|
||||
options: { keyPath: 'key' },
|
||||
indices: [],
|
||||
},
|
||||
AnkUnconfirmedSecrets: {
|
||||
name: 'unconfirmed_secrets',
|
||||
options: { autoIncrement: true },
|
||||
indices: [],
|
||||
},
|
||||
AnkProcessData: {
|
||||
@ -139,31 +144,52 @@ class Database {
|
||||
console.log('Received response from service worker (GET_OBJECT):', event.data);
|
||||
};
|
||||
|
||||
public addObject(payload: { storeName: string; object: any; key: any }) {
|
||||
if (this.serviceWorkerRegistration?.active) {
|
||||
const messageChannel = this.createMessageChannel(this.handleAddObjectResponse);
|
||||
this.serviceWorkerRegistration.active.postMessage(
|
||||
{
|
||||
type: 'ADD_OBJECT',
|
||||
payload,
|
||||
},
|
||||
[messageChannel.port2],
|
||||
);
|
||||
}
|
||||
public addObject(payload: { storeName: string; object: any; key: any }): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Check if the service worker is active
|
||||
if (!this.serviceWorkerRegistration?.active) {
|
||||
reject(new Error('Service worker is not active'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a message channel for communication
|
||||
const messageChannel = new MessageChannel();
|
||||
|
||||
// Handle the response from the service worker
|
||||
messageChannel.port1.onmessage = (event) => {
|
||||
if (event.data.status === 'success') {
|
||||
resolve();
|
||||
} else {
|
||||
const error = event.data.message;
|
||||
reject(new Error(error || 'Unknown error occurred while adding object'));
|
||||
}
|
||||
};
|
||||
|
||||
// Send the add object request to the service worker
|
||||
try {
|
||||
this.serviceWorkerRegistration.active.postMessage(
|
||||
{
|
||||
type: 'ADD_OBJECT',
|
||||
payload,
|
||||
},
|
||||
[messageChannel.port2],
|
||||
);
|
||||
} catch (error) {
|
||||
reject(new Error(`Failed to send message to service worker: ${error}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public getObject(storeName: string, key: string) {
|
||||
if (this.serviceWorkerRegistration?.active) {
|
||||
const messageChannel = this.createMessageChannel(this.handleGetObjectResponse);
|
||||
|
||||
this.serviceWorkerRegistration.active.postMessage(
|
||||
{
|
||||
type: 'GET_OBJECT',
|
||||
payload: { storeName, key },
|
||||
},
|
||||
[messageChannel.port2],
|
||||
);
|
||||
}
|
||||
public async getObject(storeName: string, key: string): Promise<any | null> {
|
||||
const db = await this.getDb();
|
||||
const tx = db.transaction(storeName, 'readonly');
|
||||
const store = tx.objectStore(storeName);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
const getRequest = store.get(key);
|
||||
getRequest.onsuccess = () => resolve(getRequest.result);
|
||||
getRequest.onerror = () => reject(getRequest.error);
|
||||
});
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,50 @@ export default class Services {
|
||||
return apiReturn;
|
||||
}
|
||||
|
||||
public async connectMember(members: Member[]): Promise<void> {
|
||||
if (members.length === 0) {
|
||||
throw new Error('Trying to connect to empty members list');
|
||||
}
|
||||
|
||||
const members_str = members.map(member => JSON.stringify(member));
|
||||
|
||||
const waitForAmount = async (): Promise<BigInt> => {
|
||||
let attempts = 3;
|
||||
while (attempts > 0) {
|
||||
const amount = this.getAmount();
|
||||
if (amount !== 0n) {
|
||||
return amount;
|
||||
}
|
||||
attempts--;
|
||||
if (attempts > 0) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for 1 second
|
||||
}
|
||||
}
|
||||
throw new Error('Amount is still 0 after 3 attempts');
|
||||
};
|
||||
|
||||
let availableAmt = this.getAmount();
|
||||
if (availableAmt === 0n) {
|
||||
const faucetMsg = this.createFaucetMessage();
|
||||
this.sendFaucetMessage(faucetMsg);
|
||||
|
||||
try {
|
||||
availableAmt = await waitForAmount();
|
||||
} catch (e) {
|
||||
console.error('Failed to retrieve amount:', e);
|
||||
throw e; // Rethrow the error if needed
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const apiReturn = this.sdkClient.create_connect_transaction(members_str, 1);
|
||||
|
||||
await this.handleApiReturn(apiReturn);
|
||||
} catch (e) {
|
||||
console.error('Failed to connect:', e);
|
||||
}
|
||||
}
|
||||
|
||||
public async sendPairingTx(spAddress: string): Promise<void> {
|
||||
const localAddress = this.sdkClient.get_address();
|
||||
const emptyTxid = '0'.repeat(64);
|
||||
@ -142,9 +186,10 @@ export default class Services {
|
||||
}
|
||||
}
|
||||
|
||||
async sendFaucetMessage(message: string): Promise<void> {
|
||||
await sendMessage('Faucet', message);
|
||||
sendFaucetMessage(message: string): void {
|
||||
sendMessage('Faucet', message);
|
||||
}
|
||||
|
||||
async parseCipher(message: string) {
|
||||
try {
|
||||
console.log('parsing new cipher');
|
||||
@ -159,7 +204,7 @@ export default class Services {
|
||||
|
||||
async parseNewTx(tx: string) {
|
||||
try {
|
||||
const parsedTx = await this.sdkClient.parse_new_tx(tx, 0, 0.0001);
|
||||
const parsedTx = await this.sdkClient.parse_new_tx(tx, 0);
|
||||
if (parsedTx) {
|
||||
console.log('🚀 ~ Services ~ parseNewTx ~ parsedTx:', parsedTx);
|
||||
try {
|
||||
@ -176,8 +221,33 @@ export default class Services {
|
||||
}
|
||||
|
||||
private async handleApiReturn(apiReturn: ApiReturn) {
|
||||
if (apiReturn.ciphers_to_send && apiReturn.ciphers_to_send.length) {
|
||||
await this.sendCipherMessages(apiReturn.ciphers_to_send);
|
||||
if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) {
|
||||
await this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send));
|
||||
}
|
||||
|
||||
if (apiReturn.secrets) {
|
||||
const unconfirmedSecrets = apiReturn.secrets.unconfirmed_secrets;
|
||||
const confirmedSecrets = apiReturn.secrets.shared_secrets;
|
||||
|
||||
console.log('confirmedSecrets:', confirmedSecrets);
|
||||
const db = await Database.getInstance();
|
||||
for (const secret of unconfirmedSecrets) {
|
||||
db.addObject({
|
||||
storeName: 'unconfirmed_secrets',
|
||||
object: secret,
|
||||
key: null,
|
||||
});
|
||||
}
|
||||
const entries = Object.entries(confirmedSecrets).map(([key, value]) => ({ key, value }));
|
||||
for (const entry of entries) {
|
||||
console.log('entry:', entry);
|
||||
|
||||
db.addObject({
|
||||
storeName: 'shared_secrets',
|
||||
object: entry,
|
||||
key: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(async () => {
|
||||
@ -207,27 +277,17 @@ export default class Services {
|
||||
}
|
||||
}
|
||||
|
||||
if (apiReturn.updated_cached_msg && apiReturn.updated_cached_msg.length) {
|
||||
apiReturn.updated_cached_msg.forEach(async (msg, index) => {
|
||||
// console.debug(`CachedMessage ${index}:`, msg);
|
||||
// Save the message to local storage
|
||||
localStorage.setItem(msg.id.toString(), JSON.stringify(msg));
|
||||
const db = await Database.getInstance();
|
||||
db.addObject({
|
||||
storeName: 'messages',
|
||||
object: { id: msg.id.toString(), msg },
|
||||
key: msg.id.toString(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (apiReturn.commit_to_send) {
|
||||
const commit = apiReturn.commit_to_send;
|
||||
await this.sendCommitMessage(JSON.stringify(commit));
|
||||
}
|
||||
|
||||
if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) {
|
||||
await this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send));
|
||||
if (apiReturn.decrypted_pcds && apiReturn.decrypted_pcds.length != 0) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (apiReturn.ciphers_to_send && apiReturn.ciphers_to_send.length != 0) {
|
||||
await this.sendCipherMessages(apiReturn.ciphers_to_send);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
@ -281,8 +341,8 @@ export default class Services {
|
||||
}
|
||||
}
|
||||
|
||||
async getAmount(): Promise<BigInt> {
|
||||
const amount = await this.sdkClient.get_available_amount();
|
||||
public getAmount(): BigInt {
|
||||
const amount = this.sdkClient.get_available_amount();
|
||||
return amount;
|
||||
}
|
||||
|
||||
@ -297,18 +357,30 @@ export default class Services {
|
||||
|
||||
async saveDevice(device: any): Promise<any> {
|
||||
const db = await Database.getInstance();
|
||||
db.addObject({
|
||||
storeName: 'wallet',
|
||||
object: { pre_id: '1', device },
|
||||
key: '1',
|
||||
});
|
||||
localStorage.setItem('wallet', device);
|
||||
try {
|
||||
await db.addObject({
|
||||
storeName: 'wallet',
|
||||
object: { pre_id: '1', device },
|
||||
key: null,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
async getDevice(): Promise<string | null> {
|
||||
const db = await Database.getInstance();
|
||||
db.getObject('wallet', '1');
|
||||
return localStorage.getItem('wallet');
|
||||
try {
|
||||
const dbRes = await db.getObject('wallet', '1');
|
||||
if (dbRes) {
|
||||
const wallet = dbRes['device'];
|
||||
return wallet;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error(`Failed to retrieve device from db: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
async dumpWallet() {
|
||||
@ -317,8 +389,8 @@ export default class Services {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
async createFaucetMessage() {
|
||||
const message = await this.sdkClient.create_faucet_msg();
|
||||
public createFaucetMessage() {
|
||||
const message = this.sdkClient.create_faucet_msg();
|
||||
console.log('🚀 ~ Services ~ createFaucetMessage ~ message:', message);
|
||||
return message;
|
||||
}
|
||||
@ -447,38 +519,6 @@ export default class Services {
|
||||
return hexObjects;
|
||||
}
|
||||
|
||||
private getCachedMessages(): string[] {
|
||||
const u32KeyRegex = /^\d+$/;
|
||||
const U32_MAX = 4294967295;
|
||||
const messages: string[] = [];
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
|
||||
if (!key) {
|
||||
return messages;
|
||||
}
|
||||
|
||||
if (u32KeyRegex.test(key)) {
|
||||
const num = parseInt(key, 10);
|
||||
if (num < 0 || num > U32_MAX) {
|
||||
console.warn(`Key ${key} is outside the u32 range and will be ignored.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = localStorage.getItem(key);
|
||||
if (!value) {
|
||||
console.warn(`No value found for key: ${key}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
messages.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
public async restoreProcesses() {
|
||||
const processesCache = this.getProcessesCache();
|
||||
console.log('🚀 ~ Services ~ restoreProcesses ~ processesCache:', processesCache);
|
||||
@ -495,19 +535,6 @@ export default class Services {
|
||||
}
|
||||
}
|
||||
|
||||
public async restoreMessages() {
|
||||
const cachedMessages = this.getCachedMessages();
|
||||
console.log('🚀 ~ Services ~ restoreMessages ~ chachedMessages:', cachedMessages);
|
||||
|
||||
if (cachedMessages && cachedMessages.length != 0) {
|
||||
try {
|
||||
await this.sdkClient.set_message_cache(cachedMessages);
|
||||
} catch (e) {
|
||||
console.error('Services ~ restoreMessages ~ Error:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getNotifications(): INotification[] {
|
||||
return [
|
||||
{
|
||||
|
@ -148,7 +148,15 @@ export function initAddressInput() {
|
||||
async function onOkButtonClick() {
|
||||
const service = await Services.getInstance();
|
||||
const addressInput = (document.getElementById('addressInput') as HTMLInputElement).value;
|
||||
await service.sendPairingTx(addressInput);
|
||||
const member = {
|
||||
sp_addresses: [addressInput],
|
||||
}
|
||||
try {
|
||||
await service.connectMember([member]);
|
||||
// await service.sendPairingTx(addressInput);
|
||||
} catch (e) {
|
||||
console.error('onOkButtonClick error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateQRCode(spAddress: string) {
|
||||
|
@ -3,21 +3,13 @@ import Services from './services/service';
|
||||
|
||||
let ws: WebSocket;
|
||||
let messageQueue: string[] = [];
|
||||
let services: Services;
|
||||
export async function initWebsocket(url: string) {
|
||||
ws = new WebSocket(url);
|
||||
services = await Services.getInstance();
|
||||
|
||||
if (ws !== null) {
|
||||
ws.onopen = async (event) => {
|
||||
console.log('WebSocket connection established');
|
||||
|
||||
const amount = await services.getAmount();
|
||||
|
||||
if (amount === 0n) {
|
||||
const faucetMsg = await services.createFaucetMessage();
|
||||
await services.sendFaucetMessage(faucetMsg);
|
||||
}
|
||||
while (messageQueue.length > 0) {
|
||||
const message = messageQueue.shift();
|
||||
if (message) {
|
||||
@ -36,6 +28,7 @@ export async function initWebsocket(url: string) {
|
||||
try {
|
||||
const feeRate = 0.0001;
|
||||
const parsedMessage = JSON.parse(msgData);
|
||||
const services = await Services.getInstance();
|
||||
switch (parsedMessage.flag) {
|
||||
case 'NewTx':
|
||||
await services.parseNewTx(parsedMessage.content);
|
||||
@ -66,7 +59,7 @@ export async function initWebsocket(url: string) {
|
||||
}
|
||||
|
||||
// Method to send messages
|
||||
export async function sendMessage(flag: AnkFlag, message: string): Promise<void> {
|
||||
export function sendMessage(flag: AnkFlag, message: string): void {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
const networkMessage = {
|
||||
flag: flag,
|
||||
|
Loading…
x
Reference in New Issue
Block a user