diff --git a/examples/dapp.html b/examples/dapp.html index c0fe55f1..8f33e4a2 100644 --- a/examples/dapp.html +++ b/examples/dapp.html @@ -184,7 +184,7 @@ el.innerText = `'time' ${start} ${label}` el.setAttribute('style', 'background-color: grey') document.getElementById('logger-output').appendChild(el) - console.time(label) + start ? console.time(label) : console.timeEnd(label) } timeLog(method, ...args) { @@ -234,7 +234,7 @@ }, featuredWallets: ['kukai', 'metamask', 'airgap'], network: { - type: beacon.NetworkType.GHOSTNET + type: beacon.NetworkType.MAINNET }, enableMetrics: true // matrixNodes: ['test.papers.tech', 'test2.papers.tech', 'matrix.papers.tech'] @@ -275,7 +275,8 @@ }) } - client.subscribeToEvent('ACTIVE_ACCOUNT_SET', () => { + client.subscribeToEvent('ACTIVE_ACCOUNT_SET', (account) => { + console.log('ACTIVE_ACCOUNT_SET received', account) updateActiveAccount() }) @@ -407,7 +408,6 @@ .disconnect() .then(() => console.log('disconnected.')) .catch((err) => console.error(err.message)) - } const requestSimulatedProofOfEventChallenge = () => { diff --git a/lerna.json b/lerna.json index 3f8ca361..fbd1321c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,4 @@ { - "version": "4.2.1", + "version": "4.2.2", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } diff --git a/package-lock.json b/package-lock.json index 2fa6f946..bb27da85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25390,38 +25390,38 @@ }, "packages/beacon-blockchain-substrate": { "name": "@airgap/beacon-blockchain-substrate", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } }, "packages/beacon-blockchain-tezos": { "name": "@airgap/beacon-blockchain-tezos", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } }, "packages/beacon-blockchain-tezos-sapling": { "name": "@airgap/beacon-blockchain-tezos-sapling", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } }, "packages/beacon-core": { "name": "@airgap/beacon-core", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "@stablelib/ed25519": "^1.0.3", "@stablelib/nacl": "^1.0.4", "@stablelib/utf8": "^1.0.1", @@ -25431,67 +25431,67 @@ }, "packages/beacon-dapp": { "name": "@airgap/beacon-dapp", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-transport-matrix": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1", - "@airgap/beacon-transport-walletconnect": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-transport-matrix": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2", + "@airgap/beacon-transport-walletconnect": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } }, "packages/beacon-sdk": { "name": "@airgap/beacon-sdk", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-blockchain-substrate": "4.2.1", - "@airgap/beacon-blockchain-tezos": "4.2.1", - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-dapp": "4.2.1", - "@airgap/beacon-transport-matrix": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1", - "@airgap/beacon-utils": "4.2.1", - "@airgap/beacon-wallet": "4.2.1" + "@airgap/beacon-blockchain-substrate": "4.2.2", + "@airgap/beacon-blockchain-tezos": "4.2.2", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-dapp": "4.2.2", + "@airgap/beacon-transport-matrix": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2", + "@airgap/beacon-utils": "4.2.2", + "@airgap/beacon-wallet": "4.2.2" } }, "packages/beacon-transport-matrix": { "name": "@airgap/beacon-transport-matrix", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "axios": "^1.6.2" } }, "packages/beacon-transport-postmessage": { "name": "@airgap/beacon-transport-postmessage", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1" + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2" } }, "packages/beacon-transport-walletconnect": { "name": "@airgap/beacon-transport-walletconnect", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "@walletconnect/sign-client": "2.11.2" } }, "packages/beacon-types": { "name": "@airgap/beacon-types", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { "@types/chrome": "0.0.246" @@ -25499,13 +25499,13 @@ }, "packages/beacon-ui": { "name": "@airgap/beacon-ui", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "@walletconnect/utils": "2.11.2", "qrcode-svg": "^1.1.0", "solid-js": "^1.7.11" @@ -25528,7 +25528,7 @@ }, "packages/beacon-utils": { "name": "@airgap/beacon-utils", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { "@stablelib/ed25519": "^1.0.3", @@ -25540,12 +25540,12 @@ }, "packages/beacon-wallet": { "name": "@airgap/beacon-wallet", - "version": "4.2.1", + "version": "4.2.2", "license": "ISC", "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-transport-matrix": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1" + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-transport-matrix": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2" } } } diff --git a/packages/beacon-blockchain-substrate/package.json b/packages/beacon-blockchain-substrate/package.json index 9aec6d23..ea72f9a9 100644 --- a/packages/beacon-blockchain-substrate/package.json +++ b/packages/beacon-blockchain-substrate/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-blockchain-substrate", - "version": "4.2.1", + "version": "4.2.2", "description": "This package adds support for `substrate` based blockchains. It can be used in combination with the `@airgap/beacon-dapp` or `@airgap/beacon-wallet` packages.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,7 +34,7 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } } diff --git a/packages/beacon-blockchain-tezos-sapling/package.json b/packages/beacon-blockchain-tezos-sapling/package.json index 4ae7c7f8..7c681836 100644 --- a/packages/beacon-blockchain-tezos-sapling/package.json +++ b/packages/beacon-blockchain-tezos-sapling/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-blockchain-tezos-sapling", - "version": "4.2.1", + "version": "4.2.2", "description": "This package adds support for `tezos-sapling`, the sapling integration on the Tezos blockchain. It can be used in combination with the `@airgap/beacon-dapp` or `@airgap/beacon-wallet` packages.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,7 +34,7 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } } diff --git a/packages/beacon-blockchain-tezos/package.json b/packages/beacon-blockchain-tezos/package.json index bc94739d..4c10ef3e 100644 --- a/packages/beacon-blockchain-tezos/package.json +++ b/packages/beacon-blockchain-tezos/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-blockchain-tezos", - "version": "4.2.1", + "version": "4.2.2", "description": "This package adds support for the `tezos` blockchain. It can be used in combination with the `@airgap/beacon-dapp` or `@airgap/beacon-wallet` packages.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,7 +34,7 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } } diff --git a/packages/beacon-core/package.json b/packages/beacon-core/package.json index 3559f088..c4bcd8b1 100644 --- a/packages/beacon-core/package.json +++ b/packages/beacon-core/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-core", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains internal methods that are used by both the dApp and wallet client.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,8 +34,8 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "@stablelib/ed25519": "^1.0.3", "@stablelib/nacl": "^1.0.4", "@stablelib/utf8": "^1.0.1", diff --git a/packages/beacon-core/src/clients/client/Client.ts b/packages/beacon-core/src/clients/client/Client.ts index 1a062499..60ad83a1 100644 --- a/packages/beacon-core/src/clients/client/Client.ts +++ b/packages/beacon-core/src/clients/client/Client.ts @@ -1,4 +1,4 @@ -import { ExposedPromise, ExposedPromiseStatus, generateGUID } from '@airgap/beacon-utils' +import { ExposedPromise, generateGUID } from '@airgap/beacon-utils' import { ConnectionContext, TransportType, @@ -52,6 +52,11 @@ export abstract class Client extends BeaconClient { protected readonly matrixNodes: NodeDistributions + private transportListeners: Map< + TransportType, + (message: any, connectionInfo: ConnectionContext) => Promise + > = new Map() + protected _transport: ExposedPromise> = new ExposedPromise() protected get transport(): Promise> { return this._transport.promise @@ -86,6 +91,21 @@ export abstract class Client extends BeaconClient { ) } } + protected async cleanup() { + if (!this.transportListeners.size) { + return + } + + if (this._transport.isResolved()) { + const transport = await this.transport + await Promise.all( + Array.from(this.transportListeners.values()).map((listener) => + transport.removeListener(listener) + ) + ) + this.transportListeners.clear() + } + } /** * Return all locally known accounts @@ -138,7 +158,7 @@ export abstract class Client extends BeaconClient { * @param transport A transport that can be provided by the user */ public async init(transport: Transport): Promise { - if (this._transport.status === ExposedPromiseStatus.RESOLVED) { + if (this._transport.isResolved()) { return (await this.transport).type } @@ -174,8 +194,13 @@ export abstract class Client extends BeaconClient { } public async destroy(): Promise { - if (this._transport.status === ExposedPromiseStatus.RESOLVED) { - await (await this.transport).disconnect() + if (this._transport.isResolved()) { + const transport = await this.transport + await this.cleanup() + await transport.disconnect() + if (transport.type === TransportType.WALLETCONNECT) { + await (transport as any).doClientCleanup() // any because I cannot import the type definition + } } await super.destroy() } @@ -200,16 +225,28 @@ export abstract class Client extends BeaconClient { } protected async addListener(transport: Transport): Promise { - transport - .addListener(async (message: unknown, connectionInfo: ConnectionContext) => { - if (typeof message === 'string') { - const deserializedMessage = (await new Serializer().deserialize( - message - )) as BeaconRequestMessage - this.handleResponse(deserializedMessage, connectionInfo) - } - }) - .catch((error) => logger.error('addListener', error)) + // in beacon we subscribe to the transport on client init only + // unsubscribing from the transport is only beneficial when running + // a single page dApp. + // However, while running a multiple tabs setup, if one of the dApps disconnects + // the others wont't recover until after a page refresh + + if (this.transportListeners.has(transport.type)) { + await transport.removeListener(this.transportListeners.get(transport.type)!) + } + + const subscription = async (message: any, connectionInfo: ConnectionContext) => { + if (typeof message === 'string') { + const deserializedMessage = (await new Serializer().deserialize( + message + )) as BeaconRequestMessage + this.handleResponse(deserializedMessage, connectionInfo) + } + } + + this.transportListeners.set(transport.type, subscription) + + transport.addListener(subscription).catch((error) => logger.error('addListener', error)) } protected async sendDisconnectToPeer(peer: PeerInfo, transport?: Transport): Promise { diff --git a/packages/beacon-core/src/constants.ts b/packages/beacon-core/src/constants.ts index 2696e1e0..8aef4d51 100644 --- a/packages/beacon-core/src/constants.ts +++ b/packages/beacon-core/src/constants.ts @@ -1,4 +1,4 @@ -export const SDK_VERSION: string = '4.2.1' +export const SDK_VERSION: string = '4.2.2' export const BEACON_VERSION: string = '3' export const NOTIFICATION_ORACLE_URL: string = diff --git a/packages/beacon-core/src/storage/IndexedDBStorage.ts b/packages/beacon-core/src/storage/IndexedDBStorage.ts index ba34774b..54da990c 100644 --- a/packages/beacon-core/src/storage/IndexedDBStorage.ts +++ b/packages/beacon-core/src/storage/IndexedDBStorage.ts @@ -4,128 +4,143 @@ import { Logger } from '@airgap/beacon-core' const logger = new Logger('IndexedDBStorage') export class IndexedDBStorage extends Storage { + private db: IDBDatabase | null = null + private isSupported: boolean = true + constructor( private readonly dbName: string = 'WALLET_CONNECT_V2_INDEXED_DB', private readonly storeName: string = 'keyvaluestorage' ) { super() - this.init() + this.initDB() + .then((db) => (this.db = db)) + .catch((err) => logger.error(err.message)) } - private async init() { - const request = indexedDB.open(this.dbName) - - request.onupgradeneeded = (event: any) => { - const db = event.target?.result - - if (!db.objectStoreNames.contains(this.storeName)) { - db.createObjectStore(this.storeName) - } - } - - request.onsuccess = (event: any) => { - logger.log(`Database ${this.dbName} and store ${this.dbName} are ready for use.`) - const db = event.target?.result - - db.close() - } - - request.onerror = (event: any) => { - logger.error(`Error opening database ${this.dbName}:`, event.target?.error) + private isIndexedDBSupported() { + if (typeof window !== 'undefined' && 'indexedDB' in window) { + logger.log('isIndexedDBSupported', 'IndexedDB is supported in this browser.') + return true + } else { + logger.error('isIndexedDBSupported', 'IndexedDB is not supported in this browser.') + return false } } - get(key: K): Promise { + private async initDB(): Promise { return new Promise((resolve, reject) => { - const request = indexedDB.open(this.dbName) - - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result - - const transaction = db.transaction(this.storeName, 'readonly') - const objectStore = transaction.objectStore(this.storeName) - - const getRequest = objectStore.get(key) - - getRequest.onsuccess = () => { - const result = getRequest.result - resolve(result) - } - - getRequest.onerror = (getEvent) => { - logger.error(`Error getting record with key ${key}:`, getEvent.target) - reject(getEvent.target) - } + this.isSupported = this.isIndexedDBSupported() + if (!this.isSupported) { + reject('IndexedDB is not supported.') } - request.onerror = (event) => { - logger.error('Error opening database:', event.target) - reject(event.target) + const request = indexedDB.open(this.dbName) + request.onupgradeneeded = (event) => { + const request = event.target as IDBOpenDBRequest + const db = request.result + if (!db.objectStoreNames.contains(this.storeName)) { + db.createObjectStore(this.storeName) + } } + request.onsuccess = (event: any) => resolve(event.target.result) + request.onerror = (event: any) => reject(event.target.error) }) } - set(key: K, value: StorageKeyReturnType[K]): Promise { + private async transaction( + mode: IDBTransactionMode, + operation: (store: IDBObjectStore) => Promise + ): Promise { return new Promise((resolve, reject) => { - const request = indexedDB.open(this.dbName) - - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result - - const transaction = db.transaction(this.storeName, 'readwrite') - const objectStore = transaction.objectStore(this.storeName) - - const putRequest = objectStore.put(value, key) - - putRequest.onsuccess = () => { - logger.log(`Record with key ${key} updated/inserted successfully`) - resolve() - } - - putRequest.onerror = (putEvent) => { - logger.error(`Error updating/inserting record with key ${key}:`, putEvent.target) - reject(putEvent.target) - } + if (!this.isSupported) { + reject('IndexedDB is not supported.') } - request.onerror = (event) => { - logger.error('Error opening database:', event.target) - reject(event.target) + if (!this.db?.objectStoreNames.contains(this.storeName)) { + reject(`${this.storeName} not found. error: ${new Error().stack}`) } + + const transaction = this.db?.transaction(this.storeName, mode) + const objectStore = transaction?.objectStore(this.storeName) + objectStore && operation(objectStore).then(resolve).catch(reject) }) } - delete(key: K): Promise { - return new Promise((resolve, reject) => { - const request = indexedDB.open(this.dbName) + public get(key: K): Promise { + return this.transaction( + 'readonly', + (store) => + new Promise((resolve, reject) => { + const getRequest = store.get(key) + getRequest.onsuccess = () => resolve(getRequest.result) + getRequest.onerror = () => reject(getRequest.error) + }) + ) + } - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result + public set(key: K, value: StorageKeyReturnType[K]): Promise { + return this.transaction( + 'readwrite', + (store) => + new Promise((resolve, reject) => { + const putRequest = store.put(value, key) + putRequest.onsuccess = () => resolve() + putRequest.onerror = () => reject(putRequest.error) + }) + ) + } - const transaction = db.transaction(this.storeName, 'readwrite') - const objectStore = transaction.objectStore(this.storeName) + public delete(key: K): Promise { + return this.transaction( + 'readwrite', + (store) => + new Promise((resolve, reject) => { + const deleteRequest = store.delete(key) + deleteRequest.onsuccess = () => resolve() + deleteRequest.onerror = () => reject(deleteRequest.error) + }) + ) + } - const deleteRequest = objectStore.delete(key) + public getAll(): Promise { + return this.transaction( + 'readonly', + (store) => + new Promise((resolve, reject) => { + const getAllRequest = store.getAll() + getAllRequest.onsuccess = () => resolve(getAllRequest.result) + getAllRequest.onerror = () => reject(getAllRequest.error) + }) + ) + } - deleteRequest.onsuccess = () => { - logger.log(`Record with key ${key} deleted successfully`) - resolve() - } + public getAllKeys(): Promise { + return this.transaction( + 'readonly', + (store) => + new Promise((resolve, reject) => { + const getAllKeysRequest = store.getAllKeys() + getAllKeysRequest.onsuccess = () => resolve(getAllKeysRequest.result) + getAllKeysRequest.onerror = () => reject(getAllKeysRequest.error) + }) + ) + } - deleteRequest.onerror = (deleteEvent: Event) => { - logger.error( - `Error deleting record with key ${key}:`, - (deleteEvent.target as IDBRequest).error - ) - reject((deleteEvent.target as IDBRequest).error) - } - } + public clearStore(): Promise { + return this.transaction( + 'readwrite', + (store) => + new Promise((resolve, reject) => { + const clearRequest = store.clear() + clearRequest.onsuccess = () => resolve() + clearRequest.onerror = () => reject(clearRequest.error) + }) + ) + } - request.onerror = (event: Event) => { - logger.error('Error opening database:', (event.target as IDBRequest).error) - reject((event.target as IDBRequest).error) - } - }) + getPrefixedKey(key: K): string { + logger.debug('getPrefixedKey', key) + throw new Error('Method not implemented.') } subscribeToStorageChanged( @@ -140,186 +155,67 @@ export class IndexedDBStorage extends Storage { throw new Error('Method not implemented.') } - getPrefixedKey(key: K): string { - logger.debug('getPrefixedKey', key) - throw new Error('Method not implemented.') - } - - /** - * @returns all stored values - */ - getAll(): Promise { - return new Promise((resolve, reject) => { - const request = indexedDB.open(this.dbName) - - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result - - const transaction = db.transaction(this.storeName, 'readonly') - const objectStore = transaction.objectStore(this.storeName) - - const getAllRequest = objectStore.getAll() - - getAllRequest.onsuccess = () => { - const results = getAllRequest.result - resolve(results) - } - - getAllRequest.onerror = (getAllEvent) => { - logger.error(`Error getting all records:`, getAllEvent.target) - reject(getAllEvent.target) - } - } - - request.onerror = (event) => { - logger.error('Error opening database:', event.target) - reject(event.target) - } - }) - } - - /** - * @returns all stored keys in store - */ - getAllKeys(): Promise { - return new Promise((resolve, reject) => { - const request = indexedDB.open(this.dbName) - - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result - - const transaction = db.transaction(this.storeName, 'readonly') - const objectStore = transaction.objectStore(this.storeName) - - const getAllRequest = objectStore.getAllKeys() - - getAllRequest.onsuccess = () => { - const results = getAllRequest.result - resolve(results) - } - - getAllRequest.onerror = (getAllEvent) => { - logger.error(`Error getting all records:`, getAllEvent.target) - reject(getAllEvent.target) - } - } - - request.onerror = (event) => { - logger.error('Error opening database:', event.target) - reject(event.target) - } - }) - } - - /** - * @returns clears all stored entries in store - */ - clearStore(): Promise { - return new Promise((resolve, reject) => { - const request = indexedDB.open(this.dbName) - - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result - const transaction = db.transaction(this.storeName, 'readwrite') - const objectStore = transaction.objectStore(this.storeName) - - const clearRequest = objectStore.clear() - - clearRequest.onsuccess = () => { - logger.log(`All entries in ${this.storeName} cleared successfully`) - resolve() - } - - clearRequest.onerror = (clearEvent) => { - logger.error(`Error clearing entries in ${this.storeName}:`, clearEvent.target) - reject(clearEvent.target) - } - } - - request.onerror = (event) => { - logger.error('Error opening database:', event.target) - reject(event.target) - } - }) - } /** * it copies over all key value pairs from a source store into a target one * @param targetDBName the name of the target DB * @param targetStoreName the name of the target store * @param skipKeys all the keys to ignore */ - populateStore( + public async fillStore( targetDBName: string, targetStoreName: string, skipKeys: string[] = [] ): Promise { - return new Promise((resolve, reject) => { - // Open the source database - const openRequest = indexedDB.open(this.dbName) - - openRequest.onsuccess = (e: Event) => { - const db = (e.target as IDBOpenDBRequest).result - if (!db) { - reject(new Error('Failed to open source database.')) - return - } - - const transaction = db.transaction(this.storeName, 'readonly') - const store = transaction.objectStore(this.storeName) - - // Get all keys and values from the source store - const allRecordsRequest = store.getAll() - const allKeysRequest = store.getAllKeys() + if (!this.isSupported) { + logger.error('fillStore', 'IndexedDB not supported.') + return + } - allRecordsRequest.onsuccess = () => { - allKeysRequest.onsuccess = () => { - const records = allRecordsRequest.result - const keys = allKeysRequest.result + const targetDBRequest = indexedDB.open(targetDBName) - // Open the target database - const targetDBRequest = indexedDB.open(targetDBName) + targetDBRequest.onerror = (event: any) => { + throw new Error(`Failed to open target database: ${event.target.error}`) + } - targetDBRequest.onupgradeneeded = (event: any) => { - const db = event.target?.result + const targetDB = await new Promise((resolve, reject) => { + targetDBRequest.onsuccess = (event) => resolve((event.target as IDBOpenDBRequest).result) + targetDBRequest.onerror = (event: any) => reject(event.target.error) + }) - if (!db.objectStoreNames.contains(targetStoreName)) { - db.createObjectStore(targetStoreName) - } - } + // Copy all items from the source store to the target store, skipping specified keys + await this.transaction('readonly', async (sourceStore) => { + const getAllRequest = sourceStore.getAll() + const getAllKeysRequest = sourceStore.getAllKeys() - targetDBRequest.onsuccess = (e: Event) => { - const targetDB = (e.target as IDBOpenDBRequest).result - const targetTransaction = targetDB.transaction(targetStoreName, 'readwrite') - const targetStore = targetTransaction.objectStore(targetStoreName) + getAllRequest.onsuccess = async () => { + getAllKeysRequest.onsuccess = async () => { + const items = getAllRequest.result + const keys = getAllKeysRequest.result - // Copy each key-value pair to the target store - keys - .filter((key) => !skipKeys.includes(key.toString())) - .forEach((key, index) => { - targetStore.put(records[index], key) - }) + if (!targetDB.objectStoreNames.contains(targetStoreName)) { + logger.error(`${this.storeName} not found. ${new Error().stack}`) + return + } - targetTransaction.oncomplete = () => { - logger.log( - `Key-value pairs copied to ${targetStoreName} in ${targetDBName} successfully.` - ) - resolve() - } + const targetTransaction = targetDB.transaction(targetStoreName, 'readwrite') + const targetStore = targetTransaction.objectStore(targetStoreName) - targetTransaction.onerror = () => { - reject(new Error('Error copying key-value pairs to the new database.')) - } - } + keys + .filter((key) => !skipKeys.includes(key.toString())) + .forEach((key, index) => { + targetStore.put(items[index], key) + }) - targetDBRequest.onerror = () => { - reject(new Error('Error opening target database.')) - } + targetTransaction.onerror = (event: any) => { + logger.error('Transaction error: ', event.target.error) } } } - - openRequest.onerror = () => { - reject(new Error('Error opening source database.')) + getAllKeysRequest.onerror = () => { + logger.error('Failed to getAllKeys from source:', getAllKeysRequest.error) + } + getAllRequest.onerror = () => { + logger.error('Failed to getAll from source:', getAllRequest.error) } }) } diff --git a/packages/beacon-core/src/storage/WCStorage.ts b/packages/beacon-core/src/storage/WCStorage.ts index f28d5266..a5e2187a 100644 --- a/packages/beacon-core/src/storage/WCStorage.ts +++ b/packages/beacon-core/src/storage/WCStorage.ts @@ -56,7 +56,7 @@ export class WCStorage { backup() { this.indexedDB - .populateStore('beacon', 'bug_report', [StorageKey.WC_2_CORE_KEYCHAIN]) + .fillStore('beacon', 'bug_report', [StorageKey.WC_2_CORE_KEYCHAIN]) .catch((error) => console.error(error.message)) } diff --git a/packages/beacon-dapp/package.json b/packages/beacon-dapp/package.json index 81199f85..9b9718af 100644 --- a/packages/beacon-dapp/package.json +++ b/packages/beacon-dapp/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-dapp", - "version": "4.2.1", + "version": "4.2.2", "description": "Use this package on your dApp to instanciate a DAppClient object and communicate to wallets.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -35,10 +35,10 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-transport-matrix": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1", - "@airgap/beacon-transport-walletconnect": "4.2.1", - "@airgap/beacon-ui": "4.2.1" + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-transport-matrix": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2", + "@airgap/beacon-transport-walletconnect": "4.2.2", + "@airgap/beacon-ui": "4.2.2" } } diff --git a/packages/beacon-dapp/src/dapp-client/DAppClient.ts b/packages/beacon-dapp/src/dapp-client/DAppClient.ts index ef3b5db2..ca91a955 100644 --- a/packages/beacon-dapp/src/dapp-client/DAppClient.ts +++ b/packages/beacon-dapp/src/dapp-client/DAppClient.ts @@ -221,6 +221,10 @@ export class DAppClient extends Client { private readonly bugReportStorage = new IndexedDBStorage('beacon', 'bug_report') + private debounceEventResponse: boolean = false + + private debounceSetActiveAccount: boolean = false + constructor(config: DAppClientOptions) { super({ storage: config && config.storage ? config.storage : new LocalStorage(), @@ -303,7 +307,6 @@ export class DAppClient extends Client { if (openRequest && typedMessage.message?.type === BeaconMessageType.Acknowledge) { this.analytics.track('event', 'DAppClient', 'Acknowledge received from Wallet') logger.log('handleResponse', `acknowledge message received for ${message.id}`) - logger.timeLog('handleResponse', message.id, 'acknowledge') this.events .emit(BeaconEvent.ACKNOWLEDGE_RECEIVED, { @@ -320,9 +323,6 @@ export class DAppClient extends Client { await this.appMetadataManager.addAppMetadata(appMetadata) } - logger.timeLog('handleResponse', typedMessage.id, 'response') - logger.time(false, typedMessage.id) - if (typedMessage.message?.type === BeaconMessageType.Error) { openRequest.reject(typedMessage.message as ErrorResponse) } else { @@ -365,8 +365,6 @@ export class DAppClient extends Client { logger.log('handleResponse', `acknowledge message received for ${message.id}`) this.analytics.track('event', 'DAppClient', 'Acknowledge received from Wallet') - logger.timeLog('handleResponse', message.id, 'acknowledge') - this.events .emit(BeaconEvent.ACKNOWLEDGE_RECEIVED, { message: typedMessage, @@ -382,9 +380,6 @@ export class DAppClient extends Client { await this.appMetadataManager.addAppMetadata(typedMessage.appMetadata) } - logger.timeLog('handleResponse', typedMessage.id, 'response') - logger.time(false, typedMessage.id) - if (typedMessage.type === BeaconMessageType.Error || (message as any).errorType) { // TODO: Remove "any" once we remove support for v1 wallets openRequest.reject(typedMessage as any) @@ -419,12 +414,27 @@ export class DAppClient extends Client { await this.events.emit(BeaconEvent.CHANNEL_CLOSED) } } else if (typedMessage.type === BeaconMessageType.ChangeAccountRequest) { - await this.onNewAccount(typedMessage, connectionInfo) + if (!this.debounceEventResponse) { + this.debounceEventResponse = true + await this.onNewAccount(typedMessage, connectionInfo) + this.debounceEventResponse = false + } } else { logger.error('handleResponse', 'no request found for id ', message.id, message) } } } + + if (this._transport.isResolved()) { + const transport = await this.transport + + if ( + transport instanceof WalletConnectTransport && + !this.openRequests.has('session_update') + ) { + this.openRequests.set('session_update', new ExposedPromise()) + } + } } this.storageValidator @@ -481,15 +491,19 @@ export class DAppClient extends Client { } private async createStateSnapshot() { - if (!localStorage) { + if (!localStorage || !this.enableMetrics) { return } const keys = Object.values(StorageKey).filter( (key) => !key.includes('wc@2') && !key.includes('secret') && !key.includes('account') ) as unknown as StorageKey[] - for (const key of keys) { - this.bugReportStorage.set(key, await this.storage.get(key)) + try { + for (const key of keys) { + await this.bugReportStorage.set(key, await this.storage.get(key)) + } + } catch (err: any) { + logger.error('createStateSnapshot', err.message) } } @@ -599,9 +613,16 @@ export class DAppClient extends Client { await this.events.emit(BeaconEvent.CHANNEL_CLOSED) this.setActiveAccount(undefined) - await this.destroy() + await this.disconnect() } + /** + * Destroy the instance. + * + * WARNING: Call `destroy` whenever you no longer need dAppClient + * as it frees internal subscriptions to the transport and therefore the instance may no longer work properly. + * If you wish to disconnect your dApp, use `disconnect` instead. + */ async destroy(): Promise { await this.createStateSnapshot() await super.destroy() @@ -744,6 +765,10 @@ export class DAppClient extends Client { // p2pTransport.disconnect(), do not abort connection manually walletConnectTransport.disconnect() ]) + this.postMessageTransport = + this.walletConnectTransport = + this.p2pTransport = + undefined this._activeAccount.isResolved() && this.clearActiveAccount() this._initPromise = undefined }, @@ -820,8 +845,12 @@ export class DAppClient extends Client { return } - if (transport instanceof WalletConnectTransport) { - await transport.closeActiveSession(activeAccount) + if (!this.debounceSetActiveAccount && transport instanceof WalletConnectTransport) { + this.debounceSetActiveAccount = true + this._initPromise = undefined + this.postMessageTransport = this.p2pTransport = this.walletConnectTransport = undefined + await transport.disconnect() + this.debounceSetActiveAccount = false } } @@ -854,6 +883,13 @@ export class DAppClient extends Client { await this.setTransport(this.walletConnectTransport) this.walletConnectTransport?.forceUpdate('INIT') } + if (this._transport.isResolved()) { + const transport = await this.transport + + if (transport.connectionStatus === TransportStatus.NOT_CONNECTED) { + await transport.connect() + } + } const peer = await this.getPeer(account) await this.setActivePeer(peer) } else { @@ -1180,6 +1216,8 @@ export class DAppClient extends Client { this.sendMetrics('performance-metrics/save', await this.buildPayload('connect', 'start')) + const logId = `makeRequestV3 ${Date.now()}` + logger.time(true, logId) const { message: response, connectionInfo } = await this.makeRequestV3< PermissionRequestV3, BeaconMessageWrapper> @@ -1187,9 +1225,11 @@ export class DAppClient extends Client { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw new Error('TODO') // throw await this.handleRequestError(request, requestError) }) + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('connect', 'start')) @@ -1263,6 +1303,8 @@ export class DAppClient extends Client { this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'start')) + const logId = `makeRequestV3 ${Date.now()}` + logger.time(true, logId) const { message: response, connectionInfo } = await this.makeRequestV3< BlockchainRequestV3, BeaconMessageWrapper> @@ -1271,10 +1313,11 @@ export class DAppClient extends Client { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw new Error('TODO') // throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'success')) await blockchain.handleResponse({ @@ -1321,6 +1364,8 @@ export class DAppClient extends Client { this.sendMetrics('performance-metrics/save', await this.buildPayload('connect', 'start')) + const logId = `makeRequest ${Date.now()}` + logger.time(true, logId) const { message, connectionInfo } = await this.makeRequest< PermissionRequest, PermissionResponse @@ -1328,9 +1373,10 @@ export class DAppClient extends Client { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('connect', 'success')) logger.log('requestPermissions', '######## MESSAGE #######') @@ -1393,7 +1439,8 @@ export class DAppClient extends Client { } this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'start')) - + const logId = `makeRequest ${Date.now()}` + logger.time(true, logId) const { message, connectionInfo } = await this.makeRequest< ProofOfEventChallengeRequest, ProofOfEventChallengeResponse @@ -1401,9 +1448,10 @@ export class DAppClient extends Client { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'success')) this.analytics.track( @@ -1452,14 +1500,16 @@ export class DAppClient extends Client { contractAddress: activeAccount.address, ...input } - + const logId = `makeRequest ${Date.now()}` + logger.time(true, logId) const { message, connectionInfo } = await this.makeRequest< SimulatedProofOfEventChallengeRequest, SimulatedProofOfEventChallengeResponse >(request).catch(async (requestError: ErrorResponse) => { + logger.time(false, logId) throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.analytics.track( 'event', 'DAppClient', @@ -1537,7 +1587,8 @@ export class DAppClient extends Client { } this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'start')) - + const logId = `makeRequest ${Date.now()}` + logger.time(true, logId) const { message, connectionInfo } = await this.makeRequest< SignPayloadRequest, SignPayloadResponse @@ -1545,9 +1596,10 @@ export class DAppClient extends Client { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'success')) await this.notifySuccess(request, { @@ -1646,16 +1698,18 @@ export class DAppClient extends Client { this.analytics.track('event', 'DAppClient', 'Operation requested') this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'start')) - + const logId = `makeRequest ${Date.now()}` + logger.time(true, logId) const { message, connectionInfo } = await this.makeRequest( request ).catch(async (requestError: ErrorResponse) => { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'success')) await this.notifySuccess(request, { @@ -1699,16 +1753,18 @@ export class DAppClient extends Client { this.analytics.track('event', 'DAppClient', 'Broadcast requested') this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'start')) - + const logId = `makeRequest ${Date.now()}` + logger.time(true, logId) const { message, connectionInfo } = await this.makeRequest( request ).catch(async (requestError: ErrorResponse) => { requestError.errorType === BeaconErrorType.ABORTED_ERROR ? this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'abort')) : this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'error')) + logger.time(false, logId) throw await this.handleRequestError(request, requestError) }) - + logger.time(false, logId) this.sendMetrics('performance-metrics/save', await this.buildPayload('message', 'success')) await this.notifySuccess(request, { @@ -1755,7 +1811,17 @@ export class DAppClient extends Client { const result = super.setTransport(transport) - await this.events.emit(BeaconEvent.ACTIVE_TRANSPORT_SET, transport) + const event = transport ? { ...(transport as any) } : undefined + + // remove keyPair, to prevent dApps from accidentaly leaking the privateKey + if (event) { + event.client = { + ...event.client, + keyPair: undefined + } + } + + await this.events.emit(BeaconEvent.ACTIVE_TRANSPORT_SET, event) return result } @@ -2105,12 +2171,10 @@ export class DAppClient extends Client { this.hideUI(['toast']) } - logger.time(true, messageId) logger.log('makeRequest', 'starting') this.isInitPending = true await this.init() this.isInitPending = false - logger.timeLog(messageId, 'init done') logger.log('makeRequest', 'after init') if (await this.addRequestAndCheckIfRateLimited()) { @@ -2162,7 +2226,6 @@ export class DAppClient extends Client { const walletInfo = await this.getWalletInfo(peer, account) logger.log('makeRequest', 'sending message', request) - logger.timeLog('makeRequest', messageId, 'sending') try { ;(await this.transport).send(payload, peer) if ( @@ -2184,10 +2247,8 @@ export class DAppClient extends Client { } ] }) - logger.timeLog('makeRequest', messageId, 'send error') throw sendError } - logger.timeLog('makeRequest', messageId, 'sent') this.events .emit(messageEvents[requestInput.type].sent, { @@ -2234,12 +2295,10 @@ export class DAppClient extends Client { } const messageId = await generateGUID() - logger.time(true, messageId) logger.log('makeRequest', 'starting') this.isInitPending = true await this.init() this.isInitPending = false - logger.timeLog('makeRequest', messageId, 'init done') logger.log('makeRequest', 'after init') if (await this.addRequestAndCheckIfRateLimited()) { @@ -2280,7 +2339,6 @@ export class DAppClient extends Client { const walletInfo = await this.getWalletInfo(peer, account) logger.log('makeRequest', 'sending message', request) - logger.timeLog('makeRequest', messageId, 'sending') try { ;(await this.transport).send(payload, peer) if ( @@ -2302,10 +2360,8 @@ export class DAppClient extends Client { } ] }) - logger.timeLog('makeRequest', messageId, 'send error') throw sendError } - logger.timeLog('makeRequest', messageId, 'sent') const index = requestInput.type as any as BeaconMessageType @@ -2340,11 +2396,13 @@ export class DAppClient extends Client { await this.createStateSnapshot() this.sendMetrics('performance-metrics/save', await this.buildPayload('disconnect', 'start')) + await this.clearActiveAccount() + if (!(transport instanceof WalletConnectTransport)) { + await transport.disconnect() + } this.postMessageTransport = undefined this.p2pTransport = undefined this.walletConnectTransport = undefined - await this.clearActiveAccount() - await transport.disconnect() this.sendMetrics('performance-metrics/save', await this.buildPayload('disconnect', 'success')) } @@ -2430,7 +2488,7 @@ export class DAppClient extends Client { const tempPK: string | undefined = message.publicKey || (message as any).pubkey || (message as any).pubKey - const publicKey = !!tempPK ? await prefixPublicKey(tempPK) : undefined + const publicKey = !!tempPK ? prefixPublicKey(tempPK) : undefined if (!publicKey && !message.address) { throw new Error('PublicKey or Address must be defined') diff --git a/packages/beacon-dapp/src/utils/tzkt-blockexplorer.ts b/packages/beacon-dapp/src/utils/tzkt-blockexplorer.ts index 5ce86064..ffae6fe4 100644 --- a/packages/beacon-dapp/src/utils/tzkt-blockexplorer.ts +++ b/packages/beacon-dapp/src/utils/tzkt-blockexplorer.ts @@ -20,7 +20,8 @@ export class TzktBlockExplorer extends BlockExplorer { [NetworkType.MUMBAINET]: 'https://mumbainet.tzkt.io', [NetworkType.NAIROBINET]: 'https://nairobinet.tzkt.io', [NetworkType.OXFORDNET]: 'https://oxfordnet.tzkt.io', - [NetworkType.CUSTOM]: 'https://oxfordnet.tzkt.io' + [NetworkType.PARISNET]: 'https://parisnet.tzkt.io', + [NetworkType.CUSTOM]: 'https://parisnet.tzkt.io' } ) { super(rpcUrls) diff --git a/packages/beacon-sdk/package.json b/packages/beacon-sdk/package.json index b848d3da..5dfe3133 100644 --- a/packages/beacon-sdk/package.json +++ b/packages/beacon-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-sdk", - "version": "4.2.1", + "version": "4.2.2", "description": "The `beacon-sdk` simplifies and abstracts the communication between dApps and wallets over different transport layers.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -35,15 +35,15 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-blockchain-substrate": "4.2.1", - "@airgap/beacon-blockchain-tezos": "4.2.1", - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-dapp": "4.2.1", - "@airgap/beacon-transport-matrix": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-ui": "4.2.1", - "@airgap/beacon-utils": "4.2.1", - "@airgap/beacon-wallet": "4.2.1" + "@airgap/beacon-blockchain-substrate": "4.2.2", + "@airgap/beacon-blockchain-tezos": "4.2.2", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-dapp": "4.2.2", + "@airgap/beacon-transport-matrix": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-ui": "4.2.2", + "@airgap/beacon-utils": "4.2.2", + "@airgap/beacon-wallet": "4.2.2" } } diff --git a/packages/beacon-transport-matrix/package.json b/packages/beacon-transport-matrix/package.json index 9e95ba23..31799b77 100644 --- a/packages/beacon-transport-matrix/package.json +++ b/packages/beacon-transport-matrix/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-transport-matrix", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains methods to facilitate communication over the Beacon network, a decentralised P2P network that is based on the matrix protocol.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,8 +34,8 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "axios": "^1.6.2" } } diff --git a/packages/beacon-transport-matrix/src/communication-client/P2PCommunicationClient.ts b/packages/beacon-transport-matrix/src/communication-client/P2PCommunicationClient.ts index 032359db..eec92668 100644 --- a/packages/beacon-transport-matrix/src/communication-client/P2PCommunicationClient.ts +++ b/packages/beacon-transport-matrix/src/communication-client/P2PCommunicationClient.ts @@ -541,7 +541,7 @@ export class P2PCommunicationClient extends CommunicationClient { const roomId = await this.getRelevantRoom(recipient) // Before we send the message, we have to wait for the join to be accepted. - await this.waitForJoin(roomId) // TODO: This can probably be removed because we are now waiting inside the get room method + // await this.waitForJoin(roomId) // TODO: This can probably be removed because we are now waiting inside the get room method const encryptedMessage = await encryptCryptoboxPayload(message, sharedKey.send) diff --git a/packages/beacon-transport-postmessage/package.json b/packages/beacon-transport-postmessage/package.json index cf3f1a7a..1d110c27 100644 --- a/packages/beacon-transport-postmessage/package.json +++ b/packages/beacon-transport-postmessage/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-transport-postmessage", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains methods to facilitate communication over the postmessage interface of the browser to talk to browser extensions.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,8 +34,8 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1" + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2" } } diff --git a/packages/beacon-transport-walletconnect/package.json b/packages/beacon-transport-walletconnect/package.json index 93b53f6f..f2e0293f 100644 --- a/packages/beacon-transport-walletconnect/package.json +++ b/packages/beacon-transport-walletconnect/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-transport-walletconnect", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains methods to facilitate communication over the WalletConnect network.", "author": "Papers AG", "homepage": "https://walletbeacon.io", @@ -34,9 +34,9 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "@walletconnect/sign-client": "2.11.2" } } diff --git a/packages/beacon-transport-walletconnect/src/WalletConnectTransport.ts b/packages/beacon-transport-walletconnect/src/WalletConnectTransport.ts index 0b1e3640..93094e3d 100644 --- a/packages/beacon-transport-walletconnect/src/WalletConnectTransport.ts +++ b/packages/beacon-transport-walletconnect/src/WalletConnectTransport.ts @@ -9,7 +9,7 @@ import { StorageKey, WalletConnectPairingRequest, NetworkType, - AccountInfo + TransportType } from '@airgap/beacon-types' import { Transport, PeerManager } from '@airgap/beacon-core' import { SignClientTypes } from '@walletconnect/types' @@ -24,7 +24,7 @@ export class WalletConnectTransport< T extends WalletConnectPairingRequest | ExtendedWalletConnectPairingResponse, K extends StorageKey.TRANSPORT_WALLETCONNECT_PEERS_DAPP > extends Transport { - // public readonly type: TransportType = TransportType.WALLETCONNECT + public readonly type: TransportType = TransportType.WALLETCONNECT constructor( name: string, @@ -89,16 +89,6 @@ export class WalletConnectTransport< this.client.storage.notify(type) } - public async closeActiveSession(account: AccountInfo) { - if (!(await this.hasPairings()) || !(await this.hasPairings())) { - await this.disconnect() - } else { - await this.client.closeActiveSession(account.address) - } - - this.forceUpdate('CLEAR_ACTIVE_ACCOUNT') - } - public async getPeers(): Promise { const client = WalletConnectCommunicationClient.getInstance(this.wcOptions) const session = client.currentSession() @@ -128,6 +118,10 @@ export class WalletConnectTransport< // } + async doClientCleanup() { + await this.client.unsubscribeFromEncryptedMessages() + } + public getPairingRequestInfo(): Promise { return this.client.getPairingRequestInfo() } diff --git a/packages/beacon-transport-walletconnect/src/communication-client/WalletConnectCommunicationClient.ts b/packages/beacon-transport-walletconnect/src/communication-client/WalletConnectCommunicationClient.ts index 4df3a18c..52c3ef20 100644 --- a/packages/beacon-transport-walletconnect/src/communication-client/WalletConnectCommunicationClient.ts +++ b/packages/beacon-transport-walletconnect/src/communication-client/WalletConnectCommunicationClient.ts @@ -162,16 +162,13 @@ export class WalletConnectCommunicationClient extends CommunicationClient { * differ from a wallet state */ private async refreshState() { - this.clearEvents() - this.signClient = undefined + await this.closeSignClient() const client = (await this.getSignClient())! const lastIndex = client.session.keys.length - 1 if (lastIndex > -1) { this.session = client.session.get(client.session.keys[lastIndex]) - - this.subscribeToSessionEvents(client) this.updateStorageWallet(this.session) this.setDefaultAccountAndNetwork() } else { @@ -188,25 +185,34 @@ export class WalletConnectCommunicationClient extends CommunicationClient { this.signClient?.core.pairing.events.removeAllListeners('pairing_expire') } + private abortErrorBuilder() { + if (!this.messageIds.length) { + return + } + + const errorResponse: any = { + type: BeaconMessageType.Disconnect, + id: this.messageIds.pop(), + errorType: BeaconErrorType.ABORTED_ERROR + } + this.session && this.notifyListeners(this.getTopicFromSession(this.session), errorResponse) + this.messageIds = [] // reset + } + private onStorageMessageHandler(type: string) { logger.debug('onStorageMessageHandler', type) - this.refreshState() + if (type === 'RESET') { + this.abortErrorBuilder() + this.clearEvents() + // no need to invoke `closeSignClinet` as the other tab already closed the connection + this.signClient = undefined + this.clearState() - if (type === 'CLEAR_ACTIVE_ACCOUNT') { - if (this.messageIds.length) { - const errorResponse: any = { - type: BeaconMessageType.Disconnect, - id: this.messageIds.pop(), - errorType: BeaconErrorType.ABORTED_ERROR - } - this.session && this.notifyListeners(this.getTopicFromSession(this.session), errorResponse) - this.messageIds = [] // reset - } - this.session = undefined - this.activeAccount = undefined return } + + this.refreshState() } private onStorageErrorHandler(data: any) { @@ -214,13 +220,32 @@ export class WalletConnectCommunicationClient extends CommunicationClient { } async unsubscribeFromEncryptedMessages(): Promise { - // implementation + this.activeListeners.clear() + this.channelOpeningListeners.clear() } async unsubscribeFromEncryptedMessage(_senderPublicKey: string): Promise { // implementation } + private async closeSignClient() { + if (!this.signClient) { + logger.error('No client active') + return + } + + await this.signClient.core.relayer.transportClose() + this.signClient.core.events.removeAllListeners() + this.signClient.core.relayer.events.removeAllListeners() + this.signClient.core.heartbeat.stop() + this.signClient.core.relayer.provider.events.removeAllListeners() + this.signClient.core.relayer.subscriber.events.removeAllListeners() + this.signClient.core.relayer.provider.connection.events.removeAllListeners() + this.clearEvents() + + this.signClient = undefined + } + private async ping() { const client = await this.getSignClient() @@ -306,7 +331,8 @@ export class WalletConnectCommunicationClient extends CommunicationClient { private async notifyListenersWithPermissionResponse( session: SessionTypes.Struct, - network: Network + network: Network, + sessionEventId?: string ) { let publicKey: string | undefined if ( @@ -361,7 +387,7 @@ export class WalletConnectCommunicationClient extends CommunicationClient { publicKey, network, scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST], - id: this.messageIds.pop() ?? '', + id: sessionEventId ?? this.messageIds.pop() ?? '', walletType: 'implicit' } @@ -564,19 +590,10 @@ export class WalletConnectCommunicationClient extends CommunicationClient { return } - // const sessions = signClient.session.getAll() - // if (sessions && sessions.length > 0) { - // this.session = sessions[0] - // this.setDefaultAccountAndNetwork() - // this.updateStorageWallet(this.session) - // return undefined - // } - const lastIndex = signClient.session.keys.length - 1 if (lastIndex > -1) { this.session = signClient.session.get(signClient.session.keys[lastIndex]) - this.updateStorageWallet(this.session) this.setDefaultAccountAndNetwork() @@ -707,7 +724,9 @@ export class WalletConnectCommunicationClient extends CommunicationClient { public async close() { this.storage.backup() + this.abortErrorBuilder() await this.closePairings() + this.unsubscribeFromEncryptedMessages() } private subscribeToSessionEvents(signClient: Client): void { @@ -731,10 +750,7 @@ export class WalletConnectCommunicationClient extends CommunicationClient { this.session = session - this.updateActiveAccount(event.params.namespaces) - this.notifyListenersWithPermissionResponse(this.session, { - type: this.wcOptions.network - }) + this.updateActiveAccount(event.params.namespaces, session) }) signClient.on('session_delete', (event) => { @@ -766,7 +782,10 @@ export class WalletConnectCommunicationClient extends CommunicationClient { this.notifyListeners(this.getTopicFromSession(session), acknowledgeResponse) } - private async updateActiveAccount(namespaces: SessionTypes.Namespaces) { + private async updateActiveAccount( + namespaces: SessionTypes.Namespaces, + session: SessionTypes.Struct + ) { try { const accounts = this.getTezosNamespace(namespaces).accounts if (accounts.length) { @@ -798,6 +817,14 @@ export class WalletConnectCommunicationClient extends CommunicationClient { scopes: [PermissionScope.SIGN, PermissionScope.OPERATION_REQUEST], walletType: 'implicit' }) + } else { + this.notifyListenersWithPermissionResponse( + session, + { + type: this.wcOptions.network + }, + 'session_update' + ) } } catch {} } @@ -929,6 +956,7 @@ export class WalletConnectCommunicationClient extends CommunicationClient { )) } + await this.closeSignClient() await this.storage.resetState() this.storage.notify('RESET') } diff --git a/packages/beacon-types/package.json b/packages/beacon-types/package.json index 051e3f8c..a32e9656 100644 --- a/packages/beacon-types/package.json +++ b/packages/beacon-types/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-types", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains types that are used throughout the Beacon SDK.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", diff --git a/packages/beacon-types/src/index.ts b/packages/beacon-types/src/index.ts index 2f6468f9..ac0c0650 100644 --- a/packages/beacon-types/src/index.ts +++ b/packages/beacon-types/src/index.ts @@ -99,7 +99,7 @@ import { BroadcastRequestOutput, BeaconRequestOutputMessage, ProofOfEventChallengeRequestOutput, - SimulatedProofOfEventChallengeRequestOutput, + SimulatedProofOfEventChallengeRequestOutput } from './types/beacon/messages/BeaconRequestOutputMessage' import { PermissionInfo } from './types/PermissionInfo' import { ConnectionContext } from './types/ConnectionContext' @@ -109,7 +109,21 @@ import { PartialTezosOperation, PartialTezosDelegationOperation, PartialTezosOriginationOperation, - PartialTezosRevealOperation + PartialTezosRevealOperation, + PartialTezosSmartRollupOriginateOperation, + PartialTezosSmartRollupAddMessagesOperation, + PartialTezosSmartRollupExecuteOutboxMessageOperation, + PartialTezosSmartRollupPublishOperation, + PartialTezosSmartRollupCementOperation, + PartialTezosSmartRollupRecoverBondOperation, + PartialTezosSmartRollupRefuteOperation, + PartialTezosSmartRollupTimeoutOperation, + PartialTezosDalPublishCommitmentOperation, + PartialTezosIncreasePaidStorageOperation, + PartialTezosRegisterGlobalConstantOperation, + PartialTezosTransferTicketOperation, + PartialTezosUpdateConsensusKeyOperation, + PartialTezosSetDepositsLimitOperation } from './types/tezos/PartialTezosOperation' import { ExtendedPeerInfo, PeerInfo, PeerInfoType } from './types/PeerInfo' import { AcknowledgeResponse } from './types/beacon/messages/AcknowledgeResponse' @@ -163,6 +177,7 @@ import { TezosVdfRevelationOperation } from './types/tezos/operations/VdfRevelat import { TezosDoublePreAttestationEvidenceOperation } from './types/tezos/operations/DoublePreAttestationEvidence' import { TezosSmartRollupCementOperation } from './types/tezos/operations/SmartRollupCement' import { TezosSmartRollupOriginateOperation } from './types/tezos/operations/SmartRollupOriginate' +import { TezosDalPublishCommitmentOperation } from './types/tezos/operations/DalPublishCommitment' export * from './types/AnalyticsInterface' @@ -201,6 +216,20 @@ export { PartialTezosDelegationOperation, PartialTezosOriginationOperation, PartialTezosRevealOperation, + PartialTezosSmartRollupOriginateOperation, + PartialTezosSmartRollupAddMessagesOperation, + PartialTezosSmartRollupExecuteOutboxMessageOperation, + PartialTezosSmartRollupPublishOperation, + PartialTezosSmartRollupCementOperation, + PartialTezosSmartRollupRecoverBondOperation, + PartialTezosSmartRollupRefuteOperation, + PartialTezosSmartRollupTimeoutOperation, + PartialTezosDalPublishCommitmentOperation, + PartialTezosRegisterGlobalConstantOperation, + PartialTezosTransferTicketOperation, + PartialTezosIncreasePaidStorageOperation, + PartialTezosUpdateConsensusKeyOperation, + PartialTezosSetDepositsLimitOperation, TezosAttestationOperation, TezosPreAttestationOperation, TezosSetDepositsLimitOperation, @@ -223,7 +252,8 @@ export { TezosSmartRollupCementOperation, TezosSmartRollupRecoverBondOperation, TezosSmartRollupRefuteOperation, - TezosSmartRollupTimeoutOperation + TezosSmartRollupTimeoutOperation, + TezosDalPublishCommitmentOperation } // Beacon diff --git a/packages/beacon-types/src/types/beacon/NetworkType.ts b/packages/beacon-types/src/types/beacon/NetworkType.ts index 3b6381f0..bc7dfc3c 100644 --- a/packages/beacon-types/src/types/beacon/NetworkType.ts +++ b/packages/beacon-types/src/types/beacon/NetworkType.ts @@ -15,5 +15,6 @@ export enum NetworkType { MUMBAINET = 'mumbainet', NAIROBINET = 'nairobinet', OXFORDNET = 'oxfordnet', + PARISNET = 'parisnet', CUSTOM = 'custom' } diff --git a/packages/beacon-types/src/types/tezos/OperationTypes.ts b/packages/beacon-types/src/types/tezos/OperationTypes.ts index ab14b925..e646fd24 100644 --- a/packages/beacon-types/src/types/tezos/OperationTypes.ts +++ b/packages/beacon-types/src/types/tezos/OperationTypes.ts @@ -14,7 +14,6 @@ export enum TezosOperationType { DOUBLE_BAKING_EVIDENCE = 'double_baking_evidence', PROPOSALS = 'proposals', BALLOT = 'ballot', - // --- ATTESTATION = 'attestation', PREATTESTATION = 'preattestation', PREENDORSEMENT = 'preendorsement', @@ -40,5 +39,6 @@ export enum TezosOperationType { SMART_ROLLUP_CEMENT = 'smart_rollup_cement', SMART_ROLLUP_RECOVER_BOND = 'smart_rollup_recover_bond', SMART_ROLLUP_REFUTE = 'smart_rollup_refute', - SMART_ROLLUP_TIMEOUT = 'smart_rollup_timeout' + SMART_ROLLUP_TIMEOUT = 'smart_rollup_timeout', + DAL_PUBLISH_COMMITMENT = 'dal_publish_commitment' } diff --git a/packages/beacon-types/src/types/tezos/PartialTezosOperation.ts b/packages/beacon-types/src/types/tezos/PartialTezosOperation.ts index 23fe7790..40a9013a 100644 --- a/packages/beacon-types/src/types/tezos/PartialTezosOperation.ts +++ b/packages/beacon-types/src/types/tezos/PartialTezosOperation.ts @@ -34,6 +34,7 @@ import { TezosRevealOperation } from './operations/Reveal' import { TezosSeedNonceRevelationOperation } from './operations/SeedNonceRevelation' import { TezosTransactionOperation } from './operations/Transaction' import { TezosPreEndorsementOperation } from './operations/PreEndorsement' +import { TezosDalPublishCommitmentOperation } from './operations/DalPublishCommitment' /** * @publicapi @@ -172,6 +173,11 @@ export type PartialTezosSmartRollupTimeoutOperation = Optional< omittedProperties > +export type PartialTezosDalPublishCommitmentOperation = Optional< + TezosDalPublishCommitmentOperation, + omittedProperties +> + /** * @publicapi * @category Tezos @@ -211,3 +217,4 @@ export type PartialTezosOperation = | PartialTezosSmartRollupRecoverBondOperation | PartialTezosSmartRollupRefuteOperation | PartialTezosSmartRollupTimeoutOperation + | PartialTezosDalPublishCommitmentOperation diff --git a/packages/beacon-types/src/types/tezos/operations/DalPublishCommitment.ts b/packages/beacon-types/src/types/tezos/operations/DalPublishCommitment.ts new file mode 100644 index 00000000..23abbf29 --- /dev/null +++ b/packages/beacon-types/src/types/tezos/operations/DalPublishCommitment.ts @@ -0,0 +1,15 @@ +import { TezosOperationType } from '../OperationTypes' + +export interface TezosDalPublishCommitmentOperation { + kind: TezosOperationType.DAL_PUBLISH_COMMITMENT + source: string + fee: string + counter: string + gas_limit: string + storage_limit: string + slot_header: { + slot_index: number + commitment: string + commitment_proof: string + } +} diff --git a/packages/beacon-types/src/types/ui.ts b/packages/beacon-types/src/types/ui.ts index 88c45d5a..5e3b064e 100644 --- a/packages/beacon-types/src/types/ui.ts +++ b/packages/beacon-types/src/types/ui.ts @@ -32,6 +32,7 @@ export interface WebApp extends AppBase { [NetworkType.MUMBAINET]?: string [NetworkType.NAIROBINET]?: string [NetworkType.OXFORDNET]?: string + [NetworkType.PARISNET]?: string [NetworkType.CUSTOM]?: string } } diff --git a/packages/beacon-ui/package.json b/packages/beacon-ui/package.json index a8fcffee..60b32bf5 100644 --- a/packages/beacon-ui/package.json +++ b/packages/beacon-ui/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-ui", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains the UI part (alerts and toasts) of the Beacon SDK.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -34,10 +34,10 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1", - "@airgap/beacon-types": "4.2.1", - "@airgap/beacon-utils": "4.2.1", + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2", + "@airgap/beacon-types": "4.2.2", + "@airgap/beacon-utils": "4.2.2", "@walletconnect/utils": "2.11.2", "qrcode-svg": "^1.1.0", "solid-js": "^1.7.11" diff --git a/packages/beacon-ui/src/components/bug-report-form/index.tsx b/packages/beacon-ui/src/components/bug-report-form/index.tsx index d328edd0..fc06ec53 100644 --- a/packages/beacon-ui/src/components/bug-report-form/index.tsx +++ b/packages/beacon-ui/src/components/bug-report-form/index.tsx @@ -1,9 +1,11 @@ -import { IndexedDBStorage, SDK_VERSION } from '@airgap/beacon-core' +import { IndexedDBStorage, Logger, SDK_VERSION } from '@airgap/beacon-core' import { StorageKey } from '@airgap/beacon-types' import { For, createEffect, createSignal } from 'solid-js' import styles from './styles.css' import { currentBrowser, currentOS } from '../../utils/platform' +const logger = new Logger('BugReport') + interface StorageObject { [key: string]: string | null } @@ -35,6 +37,7 @@ const BugReportForm = (props: any) => { const [didUserAllow, setDidUserAllow] = createSignal(false) const [status, setStatus] = createSignal<'success' | 'error' | null>(null) const [showThankYou, setShowThankYou] = createSignal(false) + const db = new IndexedDBStorage('beacon', 'bug_report') const isTitleValid = () => { const check = title().replace(/ /gi, '').length > 10 @@ -62,19 +65,21 @@ const BugReportForm = (props: any) => { const indexDBToMetadata = async () => { const wcResult: StorageObject = {} const beaconResult: StorageObject = {} - const db = new IndexedDBStorage('beacon', 'bug_report') + let keys: string[] = [] + let values: string[] = [] try { - const keys = (await db.getAllKeys()).map((key) => key.toString()) - for (const key of keys) { - if (key.includes('beacon')) { - beaconResult[key] = (await db.get(key as StorageKey)) as string - } else { - wcResult[key] = (await db.get(key as StorageKey)) as string - } - } + keys = (await db.getAllKeys()).map((key) => key.toString()) + values = await db.getAll() } catch (error: any) { - console.error(error.message) + logger.error('indexDBToMetadata', 'getAll failed: ', error.message) + return [beaconResult, wcResult] + } + + if (keys.length && values.length && keys.length === values.length) { + keys.forEach( + (key, i) => ((key.includes('beacon') ? beaconResult : wcResult)[key] = values[i]) + ) } return [beaconResult, wcResult] diff --git a/packages/beacon-utils/package.json b/packages/beacon-utils/package.json index d9aabcfe..77dd8592 100644 --- a/packages/beacon-utils/package.json +++ b/packages/beacon-utils/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-utils", - "version": "4.2.1", + "version": "4.2.2", "description": "This package contains utility functions that are used throughout the beacon-sdk", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", diff --git a/packages/beacon-utils/src/utils/crypto.ts b/packages/beacon-utils/src/utils/crypto.ts index 141d16fe..f8fb8145 100644 --- a/packages/beacon-utils/src/utils/crypto.ts +++ b/packages/beacon-utils/src/utils/crypto.ts @@ -204,7 +204,7 @@ export async function getAddressFromPublicKey(publicKey: string): Promise { +export function prefixPublicKey(publicKey: string): string { if (publicKey.length !== 64) { return publicKey } diff --git a/packages/beacon-wallet/package.json b/packages/beacon-wallet/package.json index 9849b68e..1bd6c128 100644 --- a/packages/beacon-wallet/package.json +++ b/packages/beacon-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@airgap/beacon-wallet", - "version": "4.2.1", + "version": "4.2.2", "description": "Use this package in your wallet to instanciate a WalletClient object and communicate to dApps.", "author": "Andreas Gassmann ", "homepage": "https://walletbeacon.io", @@ -35,8 +35,8 @@ "url": "https://github.com/airgap-it/beacon-sdk/issues" }, "dependencies": { - "@airgap/beacon-core": "4.2.1", - "@airgap/beacon-transport-matrix": "4.2.1", - "@airgap/beacon-transport-postmessage": "4.2.1" + "@airgap/beacon-core": "4.2.2", + "@airgap/beacon-transport-matrix": "4.2.2", + "@airgap/beacon-transport-postmessage": "4.2.2" } } diff --git a/packages/beacon-wallet/src/client/WalletClient.ts b/packages/beacon-wallet/src/client/WalletClient.ts index eb2bac25..b34e9622 100644 --- a/packages/beacon-wallet/src/client/WalletClient.ts +++ b/packages/beacon-wallet/src/client/WalletClient.ts @@ -465,6 +465,8 @@ export class WalletClient extends Client { await this.removePeer(peer as any) } + await transport.disconnect() + return } } diff --git a/scripts/blockchains/tezos-sapling.ts b/scripts/blockchains/tezos-sapling.ts index 38e8b958..70cdba84 100644 --- a/scripts/blockchains/tezos-sapling.ts +++ b/scripts/blockchains/tezos-sapling.ts @@ -18,6 +18,7 @@ export enum NetworkType { MUMBAINET = 'mumbainet', NAIROBINET = 'nairobinet', OXFORDNET = 'oxfordnet', + PARISNET = 'parisnet', CUSTOM = 'custom' } diff --git a/scripts/blockchains/tezos.ts b/scripts/blockchains/tezos.ts index f174681e..2980ef7d 100644 --- a/scripts/blockchains/tezos.ts +++ b/scripts/blockchains/tezos.ts @@ -18,6 +18,7 @@ export enum NetworkType { MUMBAINET = 'mumbainet', NAIROBINET = 'nairobinet', OXFORDNET = 'oxfordnet', + PARISNET = 'parisnet', CUSTOM = 'custom' } @@ -74,7 +75,8 @@ export const tezosWebList: WebApp[] = [ [NetworkType.LIMANET]: 'https://metamask.tezos.com/', [NetworkType.MUMBAINET]: 'https://metamask.tezos.com/', [NetworkType.NAIROBINET]: 'https://metamask.tezos.com/', - [NetworkType.OXFORDNET]: 'https://metamask.tezos.com/' + [NetworkType.OXFORDNET]: 'https://metamask.tezos.com/', + [NetworkType.PARISNET]: 'https://metamask.tezos.com/' } }, { @@ -100,7 +102,8 @@ export const tezosWebList: WebApp[] = [ [NetworkType.LIMANET]: 'https://limanet.kukai.app', [NetworkType.MUMBAINET]: 'https://mumbainet.kukai.app', [NetworkType.NAIROBINET]: 'https://nairobinet.kukai.app', - [NetworkType.OXFORDNET]: 'https://oxfordnet.kukai.app' + [NetworkType.OXFORDNET]: 'https://oxfordnet.kukai.app', + [NetworkType.PARISNET]: 'https://parisnet.kukai.app' } }, @@ -126,7 +129,8 @@ export const tezosWebList: WebApp[] = [ [NetworkType.LIMANET]: 'https://ghostnet.tzsafe.marigold.dev', [NetworkType.MUMBAINET]: 'https://ghostnet.tzsafe.marigold.dev', [NetworkType.NAIROBINET]: 'https://ghostnet.tzsafe.marigold.dev', - [NetworkType.OXFORDNET]: 'https://ghostnet.tzsafe.marigold.dev' + [NetworkType.OXFORDNET]: 'https://ghostnet.tzsafe.marigold.dev', + [NetworkType.PARISNET]: 'https://ghostnet.tzsafe.marigold.dev' } } ]