@tezos-x/octez.connect-wallet 5.0.0-beta.4 → 5.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -157,7 +157,7 @@
157
157
  \*********************************************/(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addNode: () => (/* binding */ addNode)\n/* harmony export */ });\nfunction addNode(fn) {\n process.on('exit', function () {\n return fn();\n });\n\n /**\n * on the following events,\n * the process will not end if there are\n * event-handlers attached,\n * therefore we have to call process.exit()\n */\n process.on('beforeExit', function () {\n return fn().then(function () {\n return process.exit();\n });\n });\n // catches ctrl+c event\n process.on('SIGINT', function () {\n return fn().then(function () {\n return process.exit();\n });\n });\n // catches uncaught exceptions\n process.on('uncaughtException', function (err) {\n return fn().then(function () {\n console.trace(err);\n process.exit(101);\n });\n });\n}\n\n//# sourceURL=webpack://beacon/./node_modules/unload/dist/es/node.js?\n}")},"./packages/octez.connect-core/dist/cjs/package.json":
158
158
  /*!***********************************************************!*\
159
159
  !*** ./packages/octez.connect-core/dist/cjs/package.json ***!
160
- \***********************************************************/module=>{"use strict";eval('{module.exports = /*#__PURE__*/JSON.parse(\'{"name":"@tezos-x/octez.connect-core","version":"5.0.0-beta.4","description":"This package contains internal methods that are used by both the dApp and wallet client.","author":"Blockchain Infra <blockchain.infra@trili.tech>","homepage":"https://octez-connect.tezos.com","license":"ISC","main":"dist/cjs/src/index.js","module":"dist/esm/src/index.js","types":"dist/esm/src/index.d.ts","exports":{"require":"./dist/cjs/src/index.js","import":"./dist/esm/src/index.js"},"directories":{"lib":"dist/esm","test":"__tests__"},"files":["dist"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/trilitech/octez.connect.git"},"scripts":{"tsc":"tsc -p tsconfig.json && tsc -p tsconfig-cjs.json","test":"jest"},"bugs":{"url":"https://github.com/trilitech/octez.connect/issues"},"dependencies":{"@stablelib/ed25519":"^2.0.2","@stablelib/nacl":"^2.0.1","@stablelib/utf8":"^2.0.1","@stablelib/x25519-session":"^2.0.1","@tezos-x/octez.connect-types":"5.0.0-beta.4","@tezos-x/octez.connect-utils":"5.0.0-beta.4","broadcast-channel":"^7.1.0","bs58check":"4.0.0"}}\');\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/package.json?\n}')},"./packages/octez.connect-core/dist/cjs/src/MockAnalytics.js":
160
+ \***********************************************************/module=>{"use strict";eval('{module.exports = /*#__PURE__*/JSON.parse(\'{"name":"@tezos-x/octez.connect-core","version":"5.0.0-beta.5","description":"This package contains internal methods that are used by both the dApp and wallet client.","author":"Blockchain Infra <blockchain.infra@trili.tech>","homepage":"https://octez-connect.tezos.com","license":"ISC","main":"dist/cjs/src/index.js","module":"dist/esm/src/index.js","types":"dist/esm/src/index.d.ts","exports":{"require":"./dist/cjs/src/index.js","import":"./dist/esm/src/index.js"},"directories":{"lib":"dist/esm","test":"__tests__"},"files":["dist"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/trilitech/octez.connect.git"},"scripts":{"tsc":"tsc -p tsconfig.json && tsc -p tsconfig-cjs.json","test":"jest"},"bugs":{"url":"https://github.com/trilitech/octez.connect/issues"},"dependencies":{"@stablelib/ed25519":"^2.0.2","@stablelib/nacl":"^2.0.1","@stablelib/utf8":"^2.0.1","@stablelib/x25519-session":"^2.0.1","@tezos-x/octez.connect-types":"5.0.0-beta.5","@tezos-x/octez.connect-utils":"5.0.0-beta.5","broadcast-channel":"^7.1.0","bs58check":"4.0.0"}}\');\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/package.json?\n}')},"./packages/octez.connect-core/dist/cjs/src/MockAnalytics.js":
161
161
  /*!*******************************************************************!*\
162
162
  !*** ./packages/octez.connect-core/dist/cjs/src/MockAnalytics.js ***!
163
163
  \*******************************************************************/(__unused_webpack_module,exports)=>{"use strict";eval("{\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.MockAnalytics = void 0;\nclass MockAnalytics {\n track(_trigger, _section, _label, _data) {\n // console.log('##### TRACK', trigger, section, label, data)\n // noop\n }\n}\nexports.MockAnalytics = MockAnalytics;\n//# sourceMappingURL=MockAnalytics.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/src/MockAnalytics.js?\n}")},"./packages/octez.connect-core/dist/cjs/src/MockWindow.js":
@@ -175,7 +175,7 @@
175
175
  \***************************************************************************/function(__unused_webpack_module,exports,__webpack_require__){"use strict";eval('{\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, "__esModule", ({ value: true }));\nexports.Client = void 0;\nconst octez_connect_utils_1 = __webpack_require__(/*! @tezos-x/octez.connect-utils */ "./packages/octez.connect-utils/dist/cjs/index.js");\nconst octez_connect_types_1 = __webpack_require__(/*! @tezos-x/octez.connect-types */ "./packages/octez.connect-types/dist/cjs/index.js");\nconst constants_1 = __webpack_require__(/*! ../../constants */ "./packages/octez.connect-core/dist/cjs/src/constants.js");\nconst BeaconClient_1 = __webpack_require__(/*! ../beacon-client/BeaconClient */ "./packages/octez.connect-core/dist/cjs/src/clients/beacon-client/BeaconClient.js");\nconst AccountManager_1 = __webpack_require__(/*! ../../managers/AccountManager */ "./packages/octez.connect-core/dist/cjs/src/managers/AccountManager.js");\nconst get_sender_id_1 = __webpack_require__(/*! ../../utils/get-sender-id */ "./packages/octez.connect-core/dist/cjs/src/utils/get-sender-id.js");\nconst Logger_1 = __webpack_require__(/*! ../../utils/Logger */ "./packages/octez.connect-core/dist/cjs/src/utils/Logger.js");\nconst Serializer_1 = __webpack_require__(/*! ../../Serializer */ "./packages/octez.connect-core/dist/cjs/src/Serializer.js");\nconst message_utils_1 = __webpack_require__(/*! ../../utils/message-utils */ "./packages/octez.connect-core/dist/cjs/src/utils/message-utils.js");\nconst message_protocol_1 = __webpack_require__(/*! ../../message-protocol */ "./packages/octez.connect-core/dist/cjs/src/message-protocol.js");\nconst logger = new Logger_1.Logger(\'Client\');\n/**\n * @internalapi\n *\n * This abstract class handles the a big part of the logic that is shared between the dapp and wallet client.\n * For example, it selects and manages the transport and accounts.\n */\nclass Client extends BeaconClient_1.BeaconClient {\n get transport() {\n return this._transport.promise;\n }\n /**\n * Returns the connection status of the Client\n */\n get connectionStatus() {\n var _a, _b;\n return (_b = (_a = this._transport.promiseResult) === null || _a === void 0 ? void 0 : _a.connectionStatus) !== null && _b !== void 0 ? _b : octez_connect_types_1.TransportStatus.NOT_CONNECTED;\n }\n /**\n * Returns whether or not the transaport is ready\n */\n get ready() {\n return this.transport.then(() => undefined);\n }\n constructor(config) {\n var _a;\n super(config);\n this.blockchains = new Map();\n /**\n * How many requests can be sent after another\n */\n this.rateLimit = 2;\n /**\n * The time window in seconds in which the "rateLimit" is checked\n */\n this.rateLimitWindowInSeconds = 5;\n /**\n * Stores the times when requests have been made to determine if the rate limit has been reached\n */\n this.requestCounter = [];\n this.transportListeners = new Map();\n this._transport = new octez_connect_utils_1.ExposedPromise();\n this.accountManager = new AccountManager_1.AccountManager(config.storage);\n this.matrixNodes = (_a = config.matrixNodes) !== null && _a !== void 0 ? _a : {};\n this.handleResponse = (message, connectionInfo) => {\n throw new Error(`not overwritten${JSON.stringify(message)} - ${JSON.stringify(connectionInfo)}`);\n };\n }\n cleanup() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.transportListeners.size) {\n return;\n }\n if (this._transport.isResolved()) {\n const transport = yield this.transport;\n yield Promise.all(Array.from(this.transportListeners.values()).map((listener) => transport.removeListener(listener)));\n this.transportListeners.clear();\n }\n });\n }\n /**\n * Register a blockchain to the client\n * @param chain The blockchain to register\n */\n addBlockchain(chain) {\n this.blockchains.set(chain.identifier, chain);\n }\n /**\n * Remove a blockchain from the client by its identifier\n * @param chainIdentifier The identifier of the blockchain to remove\n */\n removeBlockchain(chainIdentifier) {\n this.blockchains.delete(chainIdentifier);\n }\n /**\n * Return all locally known accounts\n */\n getAccounts() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.accountManager.getAccounts();\n });\n }\n /**\n * Return the account by ID\n * @param accountIdentifier The ID of an account\n */\n getAccount(accountIdentifier) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.accountManager.getAccount(accountIdentifier);\n });\n }\n /**\n * Remove the account by ID\n * @param accountIdentifier The ID of an account\n */\n removeAccount(accountIdentifier) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.accountManager.removeAccount(accountIdentifier);\n });\n }\n /**\n * Remove all locally stored accounts\n */\n removeAllAccounts() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.accountManager.removeAllAccounts();\n });\n }\n /**\n * Add a new request (current timestamp) to the pending requests, remove old ones and check if we are above the limit\n */\n addRequestAndCheckIfRateLimited() {\n return __awaiter(this, void 0, void 0, function* () {\n const now = new Date().getTime();\n this.requestCounter = this.requestCounter.filter((date) => date + this.rateLimitWindowInSeconds * 1000 > now);\n this.requestCounter.push(now);\n return this.requestCounter.length > this.rateLimit;\n });\n }\n /**\n * This method initializes the client. It will check if the connection should be established to a\n * browser extension or if the P2P transport should be used.\n *\n * @param transport A transport that can be provided by the user\n */\n init(transport) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._transport.isResolved()) {\n return (yield this.transport).type;\n }\n yield this.setTransport(transport); // Let users define their own transport\n return transport.type;\n });\n }\n /**\n * Returns the metadata of this DApp\n */\n getOwnAppMetadata() {\n return __awaiter(this, void 0, void 0, function* () {\n return {\n senderId: yield (0, get_sender_id_1.getSenderId)(yield this.beaconId),\n name: this.name,\n icon: this.iconUrl\n };\n });\n }\n /**\n * Return all known peers\n */\n getPeers() {\n return __awaiter(this, void 0, void 0, function* () {\n return (yield this.transport).getPeers();\n });\n }\n /**\n * Add a new peer to the known peers\n * @param peer The new peer to add\n */\n addPeer(peer) {\n return __awaiter(this, void 0, void 0, function* () {\n return (yield this.transport).addPeer(peer);\n });\n }\n destroy() {\n const _super = Object.create(null, {\n destroy: { get: () => super.destroy }\n });\n return __awaiter(this, void 0, void 0, function* () {\n if (this._transport.isResolved()) {\n const transport = yield this.transport;\n yield this.cleanup();\n yield transport.disconnect();\n if (transport.type === octez_connect_types_1.TransportType.WALLETCONNECT) {\n yield transport.doClientCleanup(); // any because I cannot import the type definition\n }\n }\n yield _super.destroy.call(this);\n });\n }\n /**\n * A "setter" for when the transport needs to be changed.\n */\n setTransport(transport) {\n return __awaiter(this, void 0, void 0, function* () {\n if (transport) {\n if (this._transport.isSettled()) {\n // If the promise has already been resolved we need to create a new one.\n this._transport = octez_connect_utils_1.ExposedPromise.resolve(transport);\n }\n else {\n this._transport.resolve(transport);\n }\n }\n else {\n if (this._transport.isSettled()) {\n // If the promise has already been resolved we need to create a new one.\n this._transport = new octez_connect_utils_1.ExposedPromise();\n }\n }\n });\n }\n addListener(transport) {\n return __awaiter(this, void 0, void 0, function* () {\n // in beacon we subscribe to the transport on client init only\n // unsubscribing from the transport is only beneficial when running\n // a single page dApp.\n // However, while running a multiple tabs setup, if one of the dApps disconnects\n // the others wont\'t recover until after a page refresh\n if (this.transportListeners.has(transport.type)) {\n yield transport.removeListener(this.transportListeners.get(transport.type));\n }\n const subscription = (message, connectionInfo) => __awaiter(this, void 0, void 0, function* () {\n if (typeof message !== \'string\') {\n return;\n }\n const peer = yield this.findPeer(connectionInfo.id);\n const protocolVersion = this.getPeerProtocolVersion(peer);\n const deserializedMessage = (yield new Serializer_1.Serializer(protocolVersion).deserialize(message));\n this.handleResponse(deserializedMessage, connectionInfo);\n });\n this.transportListeners.set(transport.type, subscription);\n transport.addListener(subscription).catch((error) => logger.error(\'addListener\', error));\n });\n }\n sendDisconnectToPeer(peer, transport) {\n return __awaiter(this, void 0, void 0, function* () {\n const id = yield (0, octez_connect_utils_1.generateGUID)();\n const senderId = yield (0, get_sender_id_1.getSenderId)(yield this.beaconId);\n const disconnectMessage = {\n id,\n version: peer.version,\n senderId,\n type: octez_connect_types_1.BeaconMessageType.Disconnect\n };\n const request = (0, message_utils_1.usesWrappedMessages)(peer.version)\n ? {\n id,\n version: peer.version,\n senderId,\n message: {\n type: disconnectMessage.type\n }\n }\n : disconnectMessage;\n const protocolVersion = this.getPeerProtocolVersion(peer);\n const payload = yield new Serializer_1.Serializer(protocolVersion).serialize(request);\n const selectedTransport = transport !== null && transport !== void 0 ? transport : (yield this.transport);\n yield selectedTransport.send(payload, peer);\n });\n }\n findPeer(publicKey) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!publicKey) {\n return undefined;\n }\n const transport = yield this.transport;\n const peers = yield transport.getPeers();\n return peers.find((peerInfo) => peerInfo.publicKey === publicKey);\n });\n }\n getLocalProtocolVersion() {\n const localPreferredRaw = Number((0, message_protocol_1.getPreferredMessageProtocolVersion)());\n return Number.isFinite(localPreferredRaw) && localPreferredRaw >= constants_1.DEFAULT_PROTOCOL_VERSION\n ? localPreferredRaw\n : constants_1.DEFAULT_PROTOCOL_VERSION;\n }\n extractPeerProtocolVersion(peer) {\n if (!peer) {\n return constants_1.DEFAULT_PROTOCOL_VERSION;\n }\n const peerProtocolRaw = typeof peer.protocolVersion === \'number\' ? peer.protocolVersion : Number(peer.protocolVersion);\n return Number.isFinite(peerProtocolRaw) && peerProtocolRaw >= constants_1.DEFAULT_PROTOCOL_VERSION\n ? peerProtocolRaw\n : constants_1.DEFAULT_PROTOCOL_VERSION;\n }\n getPeerProtocolVersion(peer) {\n const localVersion = this.getLocalProtocolVersion();\n const peerVersion = this.extractPeerProtocolVersion(peer);\n return Math.min(peerVersion, localVersion);\n }\n}\nexports.Client = Client;\n//# sourceMappingURL=Client.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/src/clients/client/Client.js?\n}')},"./packages/octez.connect-core/dist/cjs/src/constants.js":
176
176
  /*!***************************************************************!*\
177
177
  !*** ./packages/octez.connect-core/dist/cjs/src/constants.js ***!
178
- \***************************************************************/(__unused_webpack_module,exports)=>{"use strict";eval("{\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.BACKEND_URL = exports.NOTIFICATION_ORACLE_URL = exports.DEFAULT_PROTOCOL_VERSION = exports.LATEST_PROTOCOL_VERSION = exports.PROTOCOL_VERSION_V2 = exports.PROTOCOL_VERSION_V1 = exports.BEACON_VERSION = exports.SDK_VERSION = void 0;\nexports.SDK_VERSION = '5.0.0-beta.4';\nexports.BEACON_VERSION = '3';\nexports.PROTOCOL_VERSION_V1 = 1;\nexports.PROTOCOL_VERSION_V2 = 2;\nexports.LATEST_PROTOCOL_VERSION = exports.PROTOCOL_VERSION_V2;\nexports.DEFAULT_PROTOCOL_VERSION = exports.PROTOCOL_VERSION_V1;\nexports.NOTIFICATION_ORACLE_URL = 'https://beacon-notification-oracle.dev.gke.papers.tech';\nexports.BACKEND_URL = 'https://beacon-backend.prod.gke.papers.tech';\n//# sourceMappingURL=constants.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/src/constants.js?\n}")},"./packages/octez.connect-core/dist/cjs/src/debug.js":
178
+ \***************************************************************/(__unused_webpack_module,exports)=>{"use strict";eval("{\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.BACKEND_URL = exports.NOTIFICATION_ORACLE_URL = exports.DEFAULT_PROTOCOL_VERSION = exports.LATEST_PROTOCOL_VERSION = exports.PROTOCOL_VERSION_V2 = exports.PROTOCOL_VERSION_V1 = exports.BEACON_VERSION = exports.SDK_VERSION = void 0;\nexports.SDK_VERSION = '5.0.0-beta.5';\nexports.BEACON_VERSION = '3';\nexports.PROTOCOL_VERSION_V1 = 1;\nexports.PROTOCOL_VERSION_V2 = 2;\nexports.LATEST_PROTOCOL_VERSION = exports.PROTOCOL_VERSION_V2;\nexports.DEFAULT_PROTOCOL_VERSION = exports.PROTOCOL_VERSION_V1;\nexports.NOTIFICATION_ORACLE_URL = 'https://beacon-notification-oracle.dev.gke.papers.tech';\nexports.BACKEND_URL = 'https://beacon-backend.prod.gke.papers.tech';\n//# sourceMappingURL=constants.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/src/constants.js?\n}")},"./packages/octez.connect-core/dist/cjs/src/debug.js":
179
179
  /*!***********************************************************!*\
180
180
  !*** ./packages/octez.connect-core/dist/cjs/src/debug.js ***!
181
181
  \***********************************************************/(__unused_webpack_module,exports,__webpack_require__)=>{"use strict";eval('{\nObject.defineProperty(exports, "__esModule", ({ value: true }));\nexports.getDebugEnabled = exports.setDebugEnabled = void 0;\nconst MockWindow_1 = __webpack_require__(/*! ./MockWindow */ "./packages/octez.connect-core/dist/cjs/src/MockWindow.js");\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet debug = MockWindow_1.windowRef.beaconSdkDebugEnabled ? true : false;\nif (debug) {\n // eslint-disable-next-line no-console\n console.log(\'[BEACON]: Debug mode is ON (turned on either by the developer or a browser extension)\');\n}\nconst setDebugEnabled = (enabled) => {\n debug = enabled;\n};\nexports.setDebugEnabled = setDebugEnabled;\nconst getDebugEnabled = () => debug;\nexports.getDebugEnabled = getDebugEnabled;\n//# sourceMappingURL=debug.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/src/debug.js?\n}')},"./packages/octez.connect-core/dist/cjs/src/errors/AbortedBeaconError.js":
@@ -298,7 +298,7 @@
298
298
  \**************************************************************************/function(__unused_webpack_module,exports,__webpack_require__){"use strict";eval('{\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, "__esModule", ({ value: true }));\nexports.P2PTransport = void 0;\nconst octez_connect_core_1 = __webpack_require__(/*! @tezos-x/octez.connect-core */ "./packages/octez.connect-core/dist/cjs/src/index.js");\nconst octez_connect_types_1 = __webpack_require__(/*! @tezos-x/octez.connect-types */ "./packages/octez.connect-types/dist/cjs/index.js");\nconst octez_connect_transport_matrix_1 = __webpack_require__(/*! @tezos-x/octez.connect-transport-matrix */ "./packages/octez.connect-transport-matrix/dist/cjs/index.js");\nconst logger = new octez_connect_core_1.Logger(\'P2PTransport\');\n/**\n * @internalapi\n *\n *\n */\nclass P2PTransport extends octez_connect_core_1.Transport {\n constructor(name, keyPair, storage, matrixNodes, storageKey, iconUrl, appUrl) {\n super(name, new octez_connect_transport_matrix_1.P2PCommunicationClient(name, keyPair, 1, storage, matrixNodes, iconUrl, appUrl), new octez_connect_core_1.PeerManager(storage, storageKey));\n this.type = octez_connect_types_1.TransportType.P2P;\n }\n static isAvailable() {\n return __awaiter(this, void 0, void 0, function* () {\n return Promise.resolve(true);\n });\n }\n connect() {\n const _super = Object.create(null, {\n connect: { get: () => super.connect }\n });\n return __awaiter(this, void 0, void 0, function* () {\n if (this._isConnected !== octez_connect_types_1.TransportStatus.NOT_CONNECTED) {\n return;\n }\n logger.log(\'connect\');\n this._isConnected = octez_connect_types_1.TransportStatus.CONNECTING;\n yield this.client.start();\n const knownPeers = yield this.getPeers();\n if (knownPeers.length > 0) {\n logger.log(\'connect\', `connecting to ${knownPeers.length} peers`);\n const connectionPromises = knownPeers.map((peer) => __awaiter(this, void 0, void 0, function* () { return this.listen(peer.publicKey); }));\n Promise.all(connectionPromises).catch((error) => logger.error(\'connect\', error));\n }\n yield this.startOpenChannelListener();\n return _super.connect.call(this);\n });\n }\n disconnect() {\n const _super = Object.create(null, {\n disconnect: { get: () => super.disconnect }\n });\n return __awaiter(this, void 0, void 0, function* () {\n yield this.client.stop();\n return _super.disconnect.call(this);\n });\n }\n startOpenChannelListener() {\n return __awaiter(this, void 0, void 0, function* () {\n //\n });\n }\n getPairingRequestInfo() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.client.getPairingRequestInfo();\n });\n }\n listen(publicKey) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this.client\n .listenForEncryptedMessage(publicKey, (message) => {\n const connectionContext = {\n origin: octez_connect_types_1.Origin.P2P,\n id: publicKey\n };\n this.notifyListeners(message, connectionContext).catch((error) => {\n throw error;\n });\n })\n .catch((error) => {\n throw error;\n });\n });\n }\n}\nexports.P2PTransport = P2PTransport;\n//# sourceMappingURL=P2PTransport.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-transport-matrix/dist/cjs/P2PTransport.js?\n}')},"./packages/octez.connect-transport-matrix/dist/cjs/communication-client/P2PCommunicationClient.js":
299
299
  /*!*********************************************************************************************************!*\
300
300
  !*** ./packages/octez.connect-transport-matrix/dist/cjs/communication-client/P2PCommunicationClient.js ***!
301
- \*********************************************************************************************************/function(__unused_webpack_module,exports,__webpack_require__){"use strict";eval("{/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\")[\"Buffer\"];\n\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.P2PCommunicationClient = void 0;\nconst ed25519_1 = __webpack_require__(/*! @stablelib/ed25519 */ \"./node_modules/@stablelib/ed25519/lib/ed25519.js\");\nconst axios_1 = __importDefault(__webpack_require__(/*! axios */ \"./node_modules/axios/dist/browser/axios.cjs\"));\nconst octez_connect_utils_1 = __webpack_require__(/*! @tezos-x/octez.connect-utils */ \"./packages/octez.connect-utils/dist/cjs/index.js\");\nconst MatrixClient_1 = __webpack_require__(/*! ../matrix-client/MatrixClient */ \"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/MatrixClient.js\");\nconst MatrixClientEvent_1 = __webpack_require__(/*! ../matrix-client/models/MatrixClientEvent */ \"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/models/MatrixClientEvent.js\");\nconst MatrixMessage_1 = __webpack_require__(/*! ../matrix-client/models/MatrixMessage */ \"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/models/MatrixMessage.js\");\nconst octez_connect_types_1 = __webpack_require__(/*! @tezos-x/octez.connect-types */ \"./packages/octez.connect-types/dist/cjs/index.js\");\nconst octez_connect_core_1 = __webpack_require__(/*! @tezos-x/octez.connect-core */ \"./packages/octez.connect-core/dist/cjs/src/index.js\");\nconst octez_connect_utils_2 = __webpack_require__(/*! @tezos-x/octez.connect-utils */ \"./packages/octez.connect-utils/dist/cjs/index.js\");\nconst blake2b_1 = __webpack_require__(/*! @stablelib/blake2b */ \"./node_modules/@stablelib/blake2b/lib/blake2b.js\");\nconst utf8_1 = __webpack_require__(/*! @stablelib/utf8 */ \"./node_modules/@stablelib/utf8/lib/utf8.js\");\nconst logger = new octez_connect_core_1.Logger('P2PCommunicationClient');\nconst RESPONSE_WAIT_TIME_MS = 60000; // total wait time for all the probes\nconst REGIONS_AND_SERVERS = {\n [octez_connect_types_1.Regions.EUROPE_WEST]: [\n 'beacon-node-1.octez.io',\n 'beacon-node-2.octez.io',\n 'beacon-node-3.octez.io',\n 'beacon-node-4.octez.io',\n 'beacon-node-5.octez.io',\n 'beacon-node-6.octez.io',\n 'beacon-node-7.octez.io',\n 'beacon-node-8.octez.io'\n ],\n [octez_connect_types_1.Regions.NORTH_AMERICA_EAST]: [],\n [octez_connect_types_1.Regions.NORTH_AMERICA_WEST]: [],\n [octez_connect_types_1.Regions.ASIA_EAST]: [],\n [octez_connect_types_1.Regions.AUSTRALIA]: []\n};\nconst sleep = (time) => {\n return new Promise((resolve) => setTimeout(resolve, time));\n};\n/**\n * @internalapi\n */\nclass P2PCommunicationClient extends octez_connect_core_1.CommunicationClient {\n constructor(name, keyPair, replicationCount, storage, matrixNodes, iconUrl, appUrl) {\n super(keyPair);\n this.name = name;\n this.replicationCount = replicationCount;\n this.storage = storage;\n this.iconUrl = iconUrl;\n this.appUrl = appUrl;\n this.client = new octez_connect_utils_2.ExposedPromise();\n this.activeListeners = new Map();\n this.ignoredRooms = [];\n this.loginCounter = 0;\n logger.log('constructor', 'P2PCommunicationClient created');\n this.ENABLED_RELAY_SERVERS = REGIONS_AND_SERVERS;\n if (matrixNodes) {\n this.ENABLED_RELAY_SERVERS = Object.assign(Object.assign({}, REGIONS_AND_SERVERS), matrixNodes);\n }\n }\n getPairingRequestInfo() {\n return __awaiter(this, void 0, void 0, function* () {\n const info = new octez_connect_types_1.P2PPairingRequest(yield (0, octez_connect_utils_2.generateGUID)(), this.name, yield this.getPublicKey(), octez_connect_core_1.BEACON_VERSION, (yield this.getRelayServer()).server, (0, octez_connect_core_1.getPreferredMessageProtocolVersion)());\n if (this.iconUrl) {\n info.icon = this.iconUrl;\n }\n if (this.appUrl) {\n info.appUrl = this.appUrl;\n }\n return info;\n });\n }\n getPairingResponseInfo(request) {\n return __awaiter(this, void 0, void 0, function* () {\n const info = new octez_connect_types_1.P2PPairingResponse(request.id, this.name, yield this.getPublicKey(), request.version, (yield this.getRelayServer()).server, (0, octez_connect_core_1.getPreferredMessageProtocolVersion)());\n if (this.iconUrl) {\n info.icon = this.iconUrl;\n }\n if (this.appUrl) {\n info.appUrl = this.appUrl;\n }\n return info;\n });\n }\n /**\n * To get the fastest region, we can't simply do one request, because sometimes,\n * DNS and SSL handshakes make \"faster\" connections slower. So we need to do 2 requests\n * and check which request was the fastest after 1s.\n */\n findBestRegionAndGetServer() {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n if (this.selectedRegion) {\n return (_a = this.relayServer) === null || _a === void 0 ? void 0 : _a.promiseResult;\n }\n const probes = Object.entries(this.ENABLED_RELAY_SERVERS)\n .flatMap(([region, servers]) => servers.map((server) => ({ server, region: region })))\n .sort(() => Math.random() - 0.5);\n const results = [];\n const probePromises = probes.map(({ server, region }) => (() => __awaiter(this, void 0, void 0, function* () {\n const start = Date.now();\n try {\n const info = yield this.getBeaconInfo(server);\n results.push({\n server,\n region,\n time: Date.now() - start,\n timestamp: info.timestamp\n });\n }\n catch (err) {\n logger.warn(`probe for ${server} failed:`, err);\n // swallow the error so Promise.all never rejects\n }\n }))());\n // 3) Wait until either:\n // • all probes settle (fast regions), or\n // • we hit our global timeout\n yield Promise.race([Promise.all(probePromises), sleep(RESPONSE_WAIT_TIME_MS)]);\n // 4) If nobody replied, bail out\n if (results.length === 0) {\n throw new Error('No server responded.');\n }\n // 5) Pick the lowest-latency reply\n const best = results.reduce((a, b) => (b.time < a.time ? b : a));\n this.selectedRegion = best.region;\n return { server: best.server, timestamp: best.timestamp };\n });\n }\n getRelayServer() {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.relayServer) {\n const relayServer = yield this.relayServer.promise;\n // We make sure the locally cached timestamp is not older than 1 minute, if it is, we refresh it\n if (Date.now() - relayServer.localTimestamp < 60 * 1000) {\n return { server: relayServer.server, timestamp: relayServer.timestamp };\n }\n const info = yield this.getBeaconInfo(relayServer.server);\n this.relayServer.resolve({\n server: relayServer.server,\n timestamp: info.timestamp,\n localTimestamp: new Date().getTime()\n });\n return { server: relayServer.server, timestamp: info.timestamp };\n }\n else {\n this.relayServer = new octez_connect_utils_2.ExposedPromise();\n }\n const node = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE);\n if (node && node.length > 0) {\n const info = yield this.getBeaconInfo(node);\n this.relayServer.resolve({\n server: node,\n timestamp: info.timestamp,\n localTimestamp: new Date().getTime()\n });\n return { server: node, timestamp: info.timestamp };\n }\n const server = yield this.findBestRegionAndGetServer();\n if (!server) {\n throw new Error(`No servers found`);\n }\n this.storage\n .set(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE, server.server)\n .catch((error) => logger.log(error));\n this.relayServer.resolve({\n server: server.server,\n timestamp: server.timestamp,\n localTimestamp: new Date().getTime()\n });\n return { server: server.server, timestamp: server.timestamp };\n });\n }\n getBeaconInfo(server) {\n return __awaiter(this, void 0, void 0, function* () {\n return axios_1.default\n .get(`https://${server}/_synapse/client/beacon/info`)\n .then((res) => ({\n region: res.data.region,\n known_servers: res.data.known_servers,\n timestamp: Math.floor(res.data.timestamp)\n }));\n });\n }\n tryJoinRooms(roomId_1) {\n return __awaiter(this, arguments, void 0, function* (roomId, retry = 1) {\n try {\n yield (yield this.client.promise).joinRooms(roomId);\n }\n catch (error) {\n if (retry <= 10 && error.errcode === 'M_FORBIDDEN') {\n // If we join the room too fast after receiving the invite, the server can accidentally reject our join. This seems to be a problem only when using a federated multi-node setup. Usually waiting for a couple milliseconds solves the issue, but to handle lag, we will keep retrying for 2 seconds.\n logger.log(`Retrying to join...`, error);\n setTimeout(() => __awaiter(this, void 0, void 0, function* () {\n yield this.tryJoinRooms(roomId, retry + 1);\n }), 200);\n }\n else {\n logger.log(`Failed to join after ${retry} tries.`, error);\n }\n }\n });\n }\n start() {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b;\n logger.log('start', 'starting client');\n logger.log('start', `connecting to server`);\n const relayServer = yield this.getRelayServer();\n const client = MatrixClient_1.MatrixClient.create({\n baseUrl: `https://${relayServer.server}`,\n storage: this.storage\n });\n this.initialListener = (event) => __awaiter(this, void 0, void 0, function* () {\n if (this.initialEvent && this.initialEvent.timestamp && event && event.timestamp) {\n if (this.initialEvent.timestamp < event.timestamp) {\n this.initialEvent = event;\n }\n }\n else {\n this.initialEvent = event;\n }\n });\n client.subscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, this.initialListener);\n client.subscribe(MatrixClientEvent_1.MatrixClientEventType.INVITE, (event) => __awaiter(this, void 0, void 0, function* () {\n let member;\n if (event.content.members.length === 1) {\n // If there is only one member we know it's a new room\n // TODO: Use the \"sender\" of the event instead\n member = event.content.members[0];\n }\n yield this.tryJoinRooms(event.content.roomId);\n if (member) {\n yield this.updateRelayServer(member);\n yield this.updatePeerRoom(member, event.content.roomId);\n }\n }));\n if (!relayServer.timestamp) {\n throw new Error('No timestamp received from relay server');\n }\n const time = Math.floor(relayServer.timestamp);\n const loginString = `login:${Math.floor(time / (5 * 60))}`;\n logger.log('start', `login ${loginString}, ${yield this.getPublicKeyHash()} on ${relayServer.server}`);\n const loginRawDigest = (0, blake2b_1.hash)((0, utf8_1.encode)(loginString), 32);\n const secretKey = (_a = this.keyPair.secretKey) !== null && _a !== void 0 ? _a : this.keyPair.privateKey;\n const rawSignature = (0, ed25519_1.sign)(secretKey, loginRawDigest);\n try {\n yield client.start({\n id: yield this.getPublicKeyHash(),\n password: `ed:${(0, octez_connect_utils_1.toHex)(rawSignature)}:${yield this.getPublicKey()}`,\n deviceId: (0, octez_connect_utils_1.toHex)(this.keyPair.publicKey)\n });\n }\n catch (error) {\n logger.error('start', 'Could not log in, retrying', error);\n if (error.errcode === 'M_USER_DEACTIVATED') {\n yield this.generateNewKeyPair();\n yield this.reset();\n throw new Error('The account is deactivated.');\n }\n yield this.reset(); // If we can't log in, let's reset\n if (!this.selectedRegion) {\n throw new Error('No region selected.');\n }\n if (this.loginCounter <= ((_b = this.ENABLED_RELAY_SERVERS[this.selectedRegion]) !== null && _b !== void 0 ? _b : []).length) {\n this.loginCounter++;\n this.start();\n return;\n }\n else {\n logger.error('start', 'Tried to log in to every known beacon node, but no login was successful.');\n throw new Error('Could not connect to any beacon nodes. Try again later.');\n }\n }\n logger.log('start', 'login successful, client is ready');\n this.client.resolve(client);\n // Check for any pending invites that we may have missed during the initial sync\n logger.log('start', 'checking for pending invites');\n const invites = yield client.invitedRooms;\n logger.log('start', `found ${invites.length} pending invites`);\n const myUserId = `@${yield this.getPublicKeyHash()}:${relayServer.server}`;\n for (const invite of invites) {\n logger.log('start', `joining invited room: ${invite.id}`);\n yield this.tryJoinRooms(invite.id);\n // Update the peer room mapping for this invite\n if (invite.members.length > 0) {\n const member = invite.members.find((m) => m !== myUserId);\n if (member) {\n yield this.updateRelayServer(member);\n yield this.updatePeerRoom(member, invite.id);\n }\n }\n }\n });\n }\n stop() {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log('stop', 'stopping client');\n if (this.client.isResolved()) {\n yield (yield this.client.promise).stop().catch((error) => logger.error(error));\n }\n yield this.reset();\n });\n }\n reset() {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log('reset', 'resetting connection');\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS).catch((error) => logger.log(error));\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PRESERVED_STATE).catch((error) => logger.log(error));\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE).catch((error) => logger.log(error));\n // Instead of resetting everything, maybe we should make sure a new instance is created?\n this.relayServer = undefined;\n this.client = new octez_connect_utils_2.ExposedPromise();\n this.initialEvent = undefined;\n this.initialListener = undefined;\n });\n }\n listenForEncryptedMessage(senderPublicKey, messageCallback) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.activeListeners.has(senderPublicKey)) {\n return;\n }\n logger.log('listenForEncryptedMessage', `start listening for encrypted messages from publicKey ${senderPublicKey}`);\n const sharedKey = yield this.createCryptoBoxServer(senderPublicKey, this.keyPair);\n const callbackFunction = (event) => __awaiter(this, void 0, void 0, function* () {\n if (this.isTextMessage(event.content) && (yield this.isSender(event, senderPublicKey))) {\n let payload;\n yield this.updateRelayServer(event.content.message.sender);\n yield this.updatePeerRoom(event.content.message.sender, event.content.roomId);\n try {\n payload = Buffer.from(event.content.message.content, 'hex');\n // content can be non-hex if it's a connection open request\n }\n catch (_a) {\n /* */\n }\n if (payload && payload.length >= octez_connect_utils_1.secretbox_NONCEBYTES + octez_connect_utils_1.secretbox_MACBYTES) {\n try {\n const decryptedMessage = yield (0, octez_connect_utils_1.decryptCryptoboxPayload)(payload, sharedKey.receive);\n logger.log('listenForEncryptedMessage', `received a message from ${senderPublicKey}`, decryptedMessage);\n // logger.log(\n // 'listenForEncryptedMessage',\n // 'encrypted message received',\n // decryptedMessage,\n // await new Serializer().deserialize(decryptedMessage)\n // )\n // console.log('calculated sender ID', await getSenderId(senderPublicKey))\n // TODO: Add check for correct decryption key / sender ID\n messageCallback(decryptedMessage);\n }\n catch (decryptionError) {\n /* NO-OP. We try to decode every message, but some might not be addressed to us. */\n }\n }\n }\n });\n this.activeListeners.set(senderPublicKey, callbackFunction);\n (yield this.client.promise).subscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, callbackFunction);\n const lastEvent = this.initialEvent;\n if (lastEvent &&\n lastEvent.timestamp &&\n new Date().getTime() - lastEvent.timestamp < 5 * 60 * 1000) {\n logger.log('listenForEncryptedMessage', 'Handling previous event');\n yield callbackFunction(lastEvent);\n }\n else {\n logger.log('listenForEncryptedMessage', 'No previous event found');\n }\n const initialListener = this.initialListener;\n if (initialListener) {\n ;\n (yield this.client.promise).unsubscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, initialListener);\n }\n this.initialListener = undefined;\n this.initialEvent = undefined;\n });\n }\n unsubscribeFromEncryptedMessage(senderPublicKey) {\n return __awaiter(this, void 0, void 0, function* () {\n const listener = this.activeListeners.get(senderPublicKey);\n if (!listener) {\n return;\n }\n ;\n (yield this.client.promise).unsubscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, listener);\n this.activeListeners.delete(senderPublicKey);\n });\n }\n unsubscribeFromEncryptedMessages() {\n return __awaiter(this, void 0, void 0, function* () {\n ;\n (yield this.client.promise).unsubscribeAll(MatrixClientEvent_1.MatrixClientEventType.MESSAGE);\n this.activeListeners.clear();\n });\n }\n sendMessage(message, peer) {\n return __awaiter(this, void 0, void 0, function* () {\n const sharedKey = yield this.createCryptoBoxClient(peer.publicKey, this.keyPair);\n const recipientHash = yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(peer.publicKey, 'hex'));\n const recipient = (0, octez_connect_utils_1.recipientString)(recipientHash, peer.relayServer);\n const roomId = yield this.getRelevantRoom(recipient);\n // Before we send the message, we have to wait for the join to be accepted.\n // await this.waitForJoin(roomId) // TODO: This can probably be removed because we are now waiting inside the get room method\n const encryptedMessage = yield (0, octez_connect_utils_1.encryptCryptoboxPayload)(message, sharedKey.send);\n logger.log('sendMessage', 'sending encrypted message', peer.publicKey, roomId, message);\n try {\n yield (yield this.client.promise).sendTextMessage(roomId, encryptedMessage);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.code) === 'ERR_CANCELED') {\n logger.log('sendMessage', 'request cancelled while stopping transport');\n return;\n }\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN') {\n logger.log(`sendMessage`, `M_FORBIDDEN`, roomId, error);\n yield this.deleteRoomIdFromRooms(roomId);\n const newRoomId = yield this.getRelevantRoom(recipient);\n logger.log(`sendMessage`, `Old room deleted, new room created`, newRoomId);\n try {\n yield (yield this.client.promise).sendTextMessage(newRoomId, encryptedMessage);\n }\n catch (innerError) {\n if ((innerError === null || innerError === void 0 ? void 0 : innerError.code) === 'ERR_CANCELED') {\n logger.log('sendMessage', 'inner request cancelled while stopping transport');\n return;\n }\n logger.log(`sendMessage`, `inner error`, newRoomId, innerError);\n }\n }\n else {\n logger.log(`sendMessage`, `unexpected error`, error);\n }\n }\n });\n }\n updatePeerRoom(sender, roomId) {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log(`updatePeerRoom`, sender, roomId);\n // Sender is in the format \"@pubkeyhash:relayserver.tld\"\n const split = sender.split(':');\n if (split.length < 2 || !split[0].startsWith('@')) {\n throw new Error('Invalid sender');\n }\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n const room = roomIds[sender];\n if (room === roomId) {\n logger.debug(`updatePeerRoom`, `rooms are the same, not updating`);\n }\n logger.debug(`updatePeerRoom`, `current room`, room, 'new room', roomId);\n if (room && room[1]) {\n // If we have a room already, let's ignore it. We need to do this, otherwise it will be loaded from the matrix cache.\n logger.log(`updatePeerRoom`, `adding room \"${room[1]}\" to ignored array`);\n this.ignoredRooms.push(room[1]);\n }\n roomIds[sender] = roomId;\n yield this.storage.set(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS, roomIds);\n // TODO: We also need to delete the room from the sync state\n // If we need to delete a room, we can assume the local state is not up to date anymore, so we can reset the state\n });\n }\n deleteRoomIdFromRooms(roomId) {\n return __awaiter(this, void 0, void 0, function* () {\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n const newRoomIds = Object.entries(roomIds)\n .filter((entry) => entry[1] !== roomId)\n .reduce((pv, cv) => (Object.assign(Object.assign({}, pv), { [cv[0]]: cv[1] })), {});\n yield this.storage.set(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS, newRoomIds);\n // TODO: We also need to delete the room from the sync state\n // If we need to delete a room, we can assume the local state is not up to date anymore, so we can reset the state\n this.ignoredRooms.push(roomId);\n });\n }\n listenForChannelOpening(messageCallback) {\n return __awaiter(this, void 0, void 0, function* () {\n logger.debug(`listenForChannelOpening`);\n (yield this.client.promise).subscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, (event) => __awaiter(this, void 0, void 0, function* () {\n if (this.isTextMessage(event.content) && (yield this.isChannelOpenMessage(event.content))) {\n logger.log(`listenForChannelOpening`, `channel opening received, trying to decrypt`, JSON.stringify(event));\n yield this.updateRelayServer(event.content.message.sender);\n yield this.updatePeerRoom(event.content.message.sender, event.content.roomId);\n const splits = event.content.message.content.split(':');\n const payload = Buffer.from(splits[splits.length - 1], 'hex');\n if (payload.length >= octez_connect_utils_1.secretbox_NONCEBYTES + octez_connect_utils_1.secretbox_MACBYTES) {\n try {\n const rawResponse = JSON.parse(yield (0, octez_connect_utils_1.openCryptobox)(payload, this.keyPair.publicKey, this.keyPair.secretKey));\n const normalizedProtocol = Number(rawResponse.protocolVersion);\n const pairingResponse = Object.assign(Object.assign({}, rawResponse), { protocolVersion: Number.isFinite(normalizedProtocol) ? normalizedProtocol : undefined });\n logger.log(`listenForChannelOpening`, `channel opening received and decrypted`, JSON.stringify(pairingResponse));\n messageCallback(Object.assign(Object.assign({}, pairingResponse), { senderId: yield (0, octez_connect_core_1.getSenderId)(pairingResponse.publicKey) }));\n }\n catch (decryptionError) {\n /* NO-OP. We try to decode every message, but some might not be addressed to us. */\n }\n }\n }\n }));\n });\n }\n waitForJoin(roomId_1) {\n return __awaiter(this, arguments, void 0, function* (roomId, retry = 0) {\n // Rooms are updated as new events come in. `client.getRoomById` only accesses memory, it does not do any network requests.\n // TODO: Improve to listen to \"JOIN\" event\n const room = yield (yield this.client.promise).getRoomById(roomId);\n logger.log(`waitForJoin`, `Currently ${room.members.length} members, we need at least 2`);\n if (room.members.length >= 2) {\n return;\n }\n else {\n if (retry < 10) {\n logger.log(`Waiting for join... Try: ${retry}`);\n return new Promise((resolve) => {\n // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s, 512s\n const backoffMs = 1000 * Math.pow(2, retry);\n setTimeout(() => {\n resolve(this.waitForJoin(roomId, retry + 1));\n }, backoffMs);\n });\n }\n else {\n throw new Error(`No one joined after ${retry} tries. Room may be orphaned.`);\n }\n }\n });\n }\n sendPairingResponse(pairingRequest) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b;\n logger.log(`sendPairingResponse`);\n const recipientHash = yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(pairingRequest.publicKey, 'hex'));\n const recipient = (0, octez_connect_utils_1.recipientString)(recipientHash, pairingRequest.relayServer);\n // We force room creation here because if we \"re-pair\", we need to make sure that we don't send it to an old room.\n let roomId;\n let roomWasReused = false;\n try {\n roomId = yield (yield this.client.promise).createTrustedPrivateRoom(recipient);\n logger.debug(`sendPairingResponse`, `Connecting to room \"${roomId}\"`);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN' && ((_a = error === null || error === void 0 ? void 0 : error.error) === null || _a === void 0 ? void 0 : _a.includes('already in the room'))) {\n logger.log(`sendPairingResponse`, `M_FORBIDDEN during room creation, finding existing room instead`, error);\n roomWasReused = true;\n // Handle 403 response when invite was sent. Find the existing room, but first, clear our local state to force a fresh lookup\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n const oldRoomId = roomIds[recipient];\n if (oldRoomId) {\n logger.log(`sendPairingResponse`, `Clearing old room \"${oldRoomId}\" from local cache`);\n yield this.deleteRoomIdFromRooms(oldRoomId);\n }\n // Now use getRelevantJoinedRoom which will find the existing room from the server\n // or clear state if we're in an unrecoverable situation with orphaned rooms\n try {\n const room = yield this.getRelevantJoinedRoom(recipient);\n roomId = room.id;\n logger.log(`sendPairingResponse`, `Using existing room \"${roomId}\" from server`);\n }\n catch (innerError) {\n // If we still get M_FORBIDDEN here, it means we have orphaned rooms and the state was cleared\n // We need to stop the client and reconnect to get a fresh sync\n if ((innerError === null || innerError === void 0 ? void 0 : innerError.errcode) === 'M_FORBIDDEN' && ((_b = innerError === null || innerError === void 0 ? void 0 : innerError.error) === null || _b === void 0 ? void 0 : _b.includes('already in the room'))) {\n logger.log(`sendPairingResponse`, `Still getting M_FORBIDDEN after state clear, stopping and restarting client`);\n yield this.stop();\n yield this.start();\n // Try one more time with fresh state\n try {\n const room = yield this.getRelevantJoinedRoom(recipient);\n roomId = room.id;\n logger.log(`sendPairingResponse`, `Successfully found room \"${roomId}\" after restart`);\n }\n catch (finalError) {\n logger.error(`sendPairingResponse`, `Failed to recover after restart`, finalError);\n throw new Error('Unable to pair. Please clear your browser storage and try again.');\n }\n }\n else {\n logger.log(`sendPairingResponse`, `Failed to find existing room`, innerError);\n throw error; // Re-throw original error if we can't recover\n }\n }\n }\n else {\n throw error; // Re-throw if it's not the specific error we're handling\n }\n }\n yield this.updatePeerRoom(recipient, roomId);\n // Check if the other party is in the room\n const room = yield (yield this.client.promise).getRoomById(roomId);\n const hasRecipient = room.members.some((member) => member === recipient);\n if (!hasRecipient) {\n logger.log(`sendPairingResponse`, `Recipient not in room, inviting them to \"${roomId}\"`);\n // The recipient is not in the room. We need to invite them.\n // Since we're reusing a room, the recipient might have been invited before but never joined.\n // Try to invite them again.\n try {\n yield (yield this.client.promise).inviteToRooms(recipient, roomId);\n logger.log(`sendPairingResponse`, `Invited recipient to room, waiting for join`);\n yield this.waitForJoin(roomId);\n }\n catch (inviteError) {\n logger.error(`sendPairingResponse`, `Failed to invite recipient to room`, inviteError);\n // If invite fails, we're in a bad state. The user should clear storage.\n throw new Error('Unable to invite dApp to room. Please clear your browser storage and try again.');\n }\n }\n else if (!roomWasReused) {\n // Room was newly created, wait for the other party to join\n yield this.waitForJoin(roomId);\n logger.debug(`sendPairingResponse`, `Successfully joined room.`);\n }\n else {\n // Room was reused and recipient is already in it\n logger.log(`sendPairingResponse`, `Room was reused and recipient is already a member. Sending message immediately.`);\n }\n // TODO: remove v1 backwards-compatibility\n const message = typeof pairingRequest.version === 'undefined'\n ? yield this.getPublicKey() // v1\n : JSON.stringify(yield this.getPairingResponseInfo(pairingRequest)); // v2\n logger.debug(`sendPairingResponse`, `Sending pairing response`, message);\n const encryptedMessage = yield this.encryptMessageAsymmetric(pairingRequest.publicKey, message);\n const msg = ['@channel-open', recipient, encryptedMessage].join(':');\n try {\n yield (yield this.client.promise).sendTextMessage(roomId, msg);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.code) === 'ERR_CANCELED') {\n logger.log('sendPairingResponse', 'request cancelled while stopping transport');\n return;\n }\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN') {\n logger.log(`sendPairingResponse`, `M_FORBIDDEN`, roomId, error);\n yield this.deleteRoomIdFromRooms(roomId);\n const newRoomId = yield this.getRelevantRoom(recipient);\n logger.log(`sendPairingResponse`, `Old room deleted, new room created`, newRoomId);\n try {\n yield (yield this.client.promise).sendTextMessage(newRoomId, msg);\n }\n catch (innerError) {\n if ((innerError === null || innerError === void 0 ? void 0 : innerError.code) === 'ERR_CANCELED') {\n logger.log('sendPairingResponse', 'inner request cancelled while stopping transport');\n return;\n }\n logger.log(`sendPairingResponse`, `inner error`, newRoomId, innerError);\n }\n }\n else {\n logger.log(`sendPairingResponse`, `unexpected error`, error);\n }\n }\n });\n }\n isTextMessage(content) {\n return content.message.type === MatrixMessage_1.MatrixMessageType.TEXT;\n }\n updateRelayServer(sender) {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log(`updateRelayServer`, sender);\n // Sender is in the format \"@pubkeyhash:relayserver.tld\"\n const split = sender.split(':');\n if (split.length < 2 || !split[0].startsWith('@')) {\n throw new Error('Invalid sender');\n }\n const senderHash = split.shift();\n const relayServer = split.join(':');\n const manager = localStorage.getItem('beacon:communication-peers-dapp')\n ? new octez_connect_core_1.PeerManager(this.storage, octez_connect_types_1.StorageKey.TRANSPORT_P2P_PEERS_DAPP)\n : new octez_connect_core_1.PeerManager(this.storage, octez_connect_types_1.StorageKey.TRANSPORT_P2P_PEERS_WALLET);\n const peers = yield manager.getPeers();\n const promiseArray = peers.map((peer) => __awaiter(this, void 0, void 0, function* () {\n const hash = `@${yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(peer.publicKey, 'hex'))}`;\n if (hash === senderHash) {\n if (peer.relayServer !== relayServer) {\n peer.relayServer = relayServer;\n yield manager.addPeer(peer);\n }\n }\n }));\n yield Promise.all(promiseArray);\n });\n }\n isChannelOpenMessage(content) {\n return __awaiter(this, void 0, void 0, function* () {\n return content.message.content.startsWith(`@channel-open:@${yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(yield this.getPublicKey(), 'hex'))}`);\n });\n }\n isSender(event, senderPublicKey) {\n return __awaiter(this, void 0, void 0, function* () {\n return event.content.message.sender.startsWith(`@${yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(senderPublicKey, 'hex'))}`);\n });\n }\n generateNewKeyPair() {\n return __awaiter(this, void 0, void 0, function* () {\n const newSeed = yield (0, octez_connect_utils_2.generateGUID)();\n console.warn(`The current user ID has been deactivated. Generating new ID: ${newSeed}`);\n this.storage.set(octez_connect_types_1.StorageKey.BEACON_SDK_SECRET_SEED, newSeed);\n this.keyPair = yield (0, octez_connect_utils_1.getKeypairFromSeed)(newSeed);\n });\n }\n getRelevantRoom(recipient) {\n return __awaiter(this, void 0, void 0, function* () {\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n let roomId = roomIds[recipient];\n if (!roomId) {\n logger.log(`getRelevantRoom`, `No room found for peer ${recipient}, checking joined ones.`);\n const room = yield this.getRelevantJoinedRoom(recipient);\n roomId = room.id;\n roomIds[recipient] = room.id;\n yield this.storage.set(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS, roomIds);\n }\n logger.log(`getRelevantRoom`, `Using room ${roomId}`);\n return roomId;\n });\n }\n getRelevantJoinedRoom(recipient) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const joinedRooms = yield (yield this.client.promise).joinedRooms;\n logger.log('checking joined rooms', joinedRooms, recipient);\n const relevantRooms = joinedRooms\n .filter((roomElement) => !this.ignoredRooms.some((id) => roomElement.id === id))\n .filter((roomElement) => roomElement.members.some((member) => member === recipient));\n let room;\n // If we found relevant rooms, use them even if there are ignored rooms\n if (relevantRooms.length > 0) {\n room = relevantRooms[0];\n logger.log(`getRelevantJoinedRoom`, `channel already open, reusing room ${room.id}`);\n }\n else {\n // No relevant rooms found. If we have ignored rooms, we're in a bad state and need to reset.\n if (this.ignoredRooms.length > 0) {\n logger.log(`getRelevantJoinedRoom`, `no relevant rooms found but have ${this.ignoredRooms.length} ignored rooms, clearing Matrix state`);\n // Clear the Matrix preserved state to force a fresh sync on next connection\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PRESERVED_STATE).catch((error) => logger.log(error));\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS).catch((error) => logger.log(error));\n // Clear ignored rooms list since we're resetting\n this.ignoredRooms.length = 0;\n }\n logger.log(`getRelevantJoinedRoom`, `no relevant rooms found, creating new one`);\n try {\n const roomId = yield (yield this.client.promise).createTrustedPrivateRoom(recipient);\n room = yield (yield this.client.promise).getRoomById(roomId);\n logger.log(`getRelevantJoinedRoom`, `waiting for other party to join room: ${room.id}`);\n yield this.waitForJoin(roomId);\n logger.log(`getRelevantJoinedRoom`, `new room created and peer invited: ${room.id}`);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN' && ((_a = error === null || error === void 0 ? void 0 : error.error) === null || _a === void 0 ? void 0 : _a.includes('already in the room'))) {\n // Server knows about a room we don't have locally\n // Clear preserved state so next reconnect gets a fresh sync\n logger.log(`getRelevantJoinedRoom`, `M_FORBIDDEN on room creation, clearing preserved state for fresh sync on reconnect`);\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PRESERVED_STATE).catch((e) => logger.log(e));\n // Re-throw the error so caller (sendPairingResponse) can handle the restart\n throw error;\n }\n throw error;\n }\n }\n return room;\n });\n }\n}\nexports.P2PCommunicationClient = P2PCommunicationClient;\n//# sourceMappingURL=P2PCommunicationClient.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-transport-matrix/dist/cjs/communication-client/P2PCommunicationClient.js?\n}")},"./packages/octez.connect-transport-matrix/dist/cjs/index.js":
301
+ \*********************************************************************************************************/function(__unused_webpack_module,exports,__webpack_require__){"use strict";eval("{/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\")[\"Buffer\"];\n\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.P2PCommunicationClient = void 0;\nconst ed25519_1 = __webpack_require__(/*! @stablelib/ed25519 */ \"./node_modules/@stablelib/ed25519/lib/ed25519.js\");\nconst axios_1 = __importDefault(__webpack_require__(/*! axios */ \"./node_modules/axios/dist/browser/axios.cjs\"));\nconst octez_connect_utils_1 = __webpack_require__(/*! @tezos-x/octez.connect-utils */ \"./packages/octez.connect-utils/dist/cjs/index.js\");\nconst MatrixClient_1 = __webpack_require__(/*! ../matrix-client/MatrixClient */ \"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/MatrixClient.js\");\nconst MatrixClientEvent_1 = __webpack_require__(/*! ../matrix-client/models/MatrixClientEvent */ \"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/models/MatrixClientEvent.js\");\nconst MatrixMessage_1 = __webpack_require__(/*! ../matrix-client/models/MatrixMessage */ \"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/models/MatrixMessage.js\");\nconst octez_connect_types_1 = __webpack_require__(/*! @tezos-x/octez.connect-types */ \"./packages/octez.connect-types/dist/cjs/index.js\");\nconst octez_connect_core_1 = __webpack_require__(/*! @tezos-x/octez.connect-core */ \"./packages/octez.connect-core/dist/cjs/src/index.js\");\nconst octez_connect_utils_2 = __webpack_require__(/*! @tezos-x/octez.connect-utils */ \"./packages/octez.connect-utils/dist/cjs/index.js\");\nconst blake2b_1 = __webpack_require__(/*! @stablelib/blake2b */ \"./node_modules/@stablelib/blake2b/lib/blake2b.js\");\nconst utf8_1 = __webpack_require__(/*! @stablelib/utf8 */ \"./node_modules/@stablelib/utf8/lib/utf8.js\");\nconst logger = new octez_connect_core_1.Logger('P2PCommunicationClient');\nconst RESPONSE_WAIT_TIME_MS = 60000; // total wait time for all the probes\nconst REGIONS_AND_SERVERS = {\n [octez_connect_types_1.Regions.EUROPE_WEST]: [\n 'beacon-node-1.octez.io',\n 'beacon-node-2.octez.io',\n 'beacon-node-3.octez.io',\n 'beacon-node-4.octez.io',\n 'beacon-node-5.octez.io',\n 'beacon-node-6.octez.io',\n 'beacon-node-7.octez.io',\n 'beacon-node-8.octez.io'\n ],\n [octez_connect_types_1.Regions.NORTH_AMERICA_EAST]: [],\n [octez_connect_types_1.Regions.NORTH_AMERICA_WEST]: [],\n [octez_connect_types_1.Regions.ASIA_EAST]: [],\n [octez_connect_types_1.Regions.AUSTRALIA]: []\n};\nconst sleep = (time) => {\n return new Promise((resolve) => setTimeout(resolve, time));\n};\n/**\n * @internalapi\n */\nclass P2PCommunicationClient extends octez_connect_core_1.CommunicationClient {\n constructor(name, keyPair, replicationCount, storage, matrixNodes, iconUrl, appUrl) {\n super(keyPair);\n this.name = name;\n this.replicationCount = replicationCount;\n this.storage = storage;\n this.iconUrl = iconUrl;\n this.appUrl = appUrl;\n this.client = new octez_connect_utils_2.ExposedPromise();\n this.activeListeners = new Map();\n this.ignoredRooms = [];\n this.loginCounter = 0;\n logger.log('constructor', 'P2PCommunicationClient created');\n this.ENABLED_RELAY_SERVERS = REGIONS_AND_SERVERS;\n if (matrixNodes) {\n this.ENABLED_RELAY_SERVERS = Object.assign(Object.assign({}, REGIONS_AND_SERVERS), matrixNodes);\n }\n }\n getPairingRequestInfo() {\n return __awaiter(this, void 0, void 0, function* () {\n const info = new octez_connect_types_1.P2PPairingRequest(yield (0, octez_connect_utils_2.generateGUID)(), this.name, yield this.getPublicKey(), octez_connect_core_1.BEACON_VERSION, (yield this.getRelayServer()).server, (0, octez_connect_core_1.getPreferredMessageProtocolVersion)());\n if (this.iconUrl) {\n info.icon = this.iconUrl;\n }\n if (this.appUrl) {\n info.appUrl = this.appUrl;\n }\n return info;\n });\n }\n getPairingResponseInfo(request) {\n return __awaiter(this, void 0, void 0, function* () {\n const info = new octez_connect_types_1.P2PPairingResponse(request.id, this.name, yield this.getPublicKey(), request.version, (yield this.getRelayServer()).server, (0, octez_connect_core_1.getPreferredMessageProtocolVersion)());\n if (this.iconUrl) {\n info.icon = this.iconUrl;\n }\n if (this.appUrl) {\n info.appUrl = this.appUrl;\n }\n return info;\n });\n }\n /**\n * To get the fastest region, we can't simply do one request, because sometimes,\n * DNS and SSL handshakes make \"faster\" connections slower. So we need to do 2 requests\n * and check which request was the fastest after 1s.\n */\n findBestRegionAndGetServer() {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n if (this.selectedRegion) {\n return (_a = this.relayServer) === null || _a === void 0 ? void 0 : _a.promiseResult;\n }\n const probes = Object.entries(this.ENABLED_RELAY_SERVERS)\n .flatMap(([region, servers]) => servers.map((server) => ({ server, region: region })))\n .sort(() => Math.random() - 0.5);\n const results = [];\n const probePromises = probes.map(({ server, region }) => (() => __awaiter(this, void 0, void 0, function* () {\n const start = Date.now();\n try {\n const info = yield this.getBeaconInfo(server);\n results.push({\n server,\n region,\n time: Date.now() - start,\n timestamp: info.timestamp\n });\n }\n catch (err) {\n logger.warn(`probe for ${server} failed:`, err);\n // swallow the error so Promise.all never rejects\n }\n }))());\n // 3) Wait until either:\n // • all probes settle (fast regions), or\n // • we hit our global timeout\n yield Promise.race([Promise.all(probePromises), sleep(RESPONSE_WAIT_TIME_MS)]);\n // 4) If nobody replied, bail out\n if (results.length === 0) {\n throw new Error('No server responded.');\n }\n // 5) Pick the lowest-latency reply\n const best = results.reduce((a, b) => (b.time < a.time ? b : a));\n this.selectedRegion = best.region;\n return { server: best.server, timestamp: best.timestamp };\n });\n }\n getRelayServer() {\n return __awaiter(this, void 0, void 0, function* () {\n // Fast path: in-memory cached relay server that's still fresh\n if (this.relayServer) {\n const currentPromise = this.relayServer;\n const relayServer = yield this.relayServer.promise;\n if (Date.now() - relayServer.localTimestamp < 60 * 1000) {\n return { server: relayServer.server, timestamp: relayServer.timestamp };\n }\n try {\n const info = yield this.getBeaconInfo(relayServer.server);\n const refreshedPromise = octez_connect_utils_2.ExposedPromise.resolve({\n server: relayServer.server,\n timestamp: info.timestamp,\n localTimestamp: new Date().getTime()\n });\n if (this.relayServer === currentPromise) {\n this.relayServer = refreshedPromise;\n }\n return { server: relayServer.server, timestamp: info.timestamp };\n }\n catch (error) {\n logger.log('getRelayServer', `cached server ${relayServer.server} is unreachable, resetting`);\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE).catch((e) => logger.log(e));\n // Only reset if this promise instance is still current (not replaced by another caller)\n const replacementRelayPromise = this.relayServer;\n if (replacementRelayPromise === currentPromise) {\n this.relayServer = undefined;\n this.selectedRegion = undefined;\n }\n else if (replacementRelayPromise) {\n // Another caller replaced the promise while we were waiting.\n // Reuse that result instead of racing into a second discovery.\n const latestRelayServer = yield replacementRelayPromise.promise;\n return { server: latestRelayServer.server, timestamp: latestRelayServer.timestamp };\n }\n // Fall through to discovery below\n }\n }\n // Another caller may have created a new in-flight promise while we were handling stale cache.\n // Reuse it instead of replacing it with a new promise.\n if (this.relayServer) {\n const relayServer = yield this.relayServer.promise;\n return { server: relayServer.server, timestamp: relayServer.timestamp };\n }\n // First caller creates the promise; concurrent callers will await it above\n const discoveryPromise = new octez_connect_utils_2.ExposedPromise();\n this.relayServer = discoveryPromise;\n try {\n // Try the localStorage-cached node first\n const node = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE);\n if (node && node.length > 0) {\n try {\n const info = yield this.getBeaconInfo(node);\n discoveryPromise.resolve({\n server: node,\n timestamp: info.timestamp,\n localTimestamp: new Date().getTime()\n });\n return { server: node, timestamp: info.timestamp };\n }\n catch (error) {\n logger.log('getRelayServer', `stored node ${node} is unreachable, falling through to discovery`);\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE).catch((e) => logger.log(e));\n }\n }\n // Full discovery: probe all servers, pick the fastest\n const server = yield this.findBestRegionAndGetServer();\n if (!server) {\n throw new Error('No servers found');\n }\n this.storage\n .set(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE, server.server)\n .catch((error) => logger.log(error));\n discoveryPromise.resolve({\n server: server.server,\n timestamp: server.timestamp,\n localTimestamp: new Date().getTime()\n });\n return { server: server.server, timestamp: server.timestamp };\n }\n catch (error) {\n // Always settle the ExposedPromise so concurrent callers don't hang forever\n discoveryPromise.reject(error);\n if (this.relayServer === discoveryPromise) {\n this.relayServer = undefined;\n }\n throw error;\n }\n });\n }\n getBeaconInfo(server) {\n return __awaiter(this, void 0, void 0, function* () {\n return axios_1.default\n .get(`https://${server}/_synapse/client/beacon/info`, { timeout: 10000 })\n .then((res) => ({\n region: res.data.region,\n known_servers: res.data.known_servers,\n timestamp: Math.floor(res.data.timestamp)\n }));\n });\n }\n tryJoinRooms(roomId_1) {\n return __awaiter(this, arguments, void 0, function* (roomId, retry = 1) {\n try {\n yield (yield this.client.promise).joinRooms(roomId);\n }\n catch (error) {\n if (retry <= 10 && error.errcode === 'M_FORBIDDEN') {\n // If we join the room too fast after receiving the invite, the server can accidentally reject our join. This seems to be a problem only when using a federated multi-node setup. Usually waiting for a couple milliseconds solves the issue, but to handle lag, we will keep retrying for 2 seconds.\n logger.log(`Retrying to join...`, error);\n setTimeout(() => __awaiter(this, void 0, void 0, function* () {\n yield this.tryJoinRooms(roomId, retry + 1);\n }), 200);\n }\n else {\n logger.log(`Failed to join after ${retry} tries.`, error);\n }\n }\n });\n }\n start() {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b;\n logger.log('start', 'starting client');\n logger.log('start', `connecting to server`);\n const relayServer = yield this.getRelayServer();\n const client = MatrixClient_1.MatrixClient.create({\n baseUrl: `https://${relayServer.server}`,\n storage: this.storage\n });\n this.initialListener = (event) => __awaiter(this, void 0, void 0, function* () {\n if (this.initialEvent && this.initialEvent.timestamp && event && event.timestamp) {\n if (this.initialEvent.timestamp < event.timestamp) {\n this.initialEvent = event;\n }\n }\n else {\n this.initialEvent = event;\n }\n });\n client.subscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, this.initialListener);\n client.subscribe(MatrixClientEvent_1.MatrixClientEventType.INVITE, (event) => __awaiter(this, void 0, void 0, function* () {\n let member;\n if (event.content.members.length === 1) {\n // If there is only one member we know it's a new room\n // TODO: Use the \"sender\" of the event instead\n member = event.content.members[0];\n }\n yield this.tryJoinRooms(event.content.roomId);\n if (member) {\n yield this.updateRelayServer(member);\n yield this.updatePeerRoom(member, event.content.roomId);\n }\n }));\n if (!relayServer.timestamp) {\n throw new Error('No timestamp received from relay server');\n }\n const time = Math.floor(relayServer.timestamp);\n const loginString = `login:${Math.floor(time / (5 * 60))}`;\n logger.log('start', `login ${loginString}, ${yield this.getPublicKeyHash()} on ${relayServer.server}`);\n const loginRawDigest = (0, blake2b_1.hash)((0, utf8_1.encode)(loginString), 32);\n const secretKey = (_a = this.keyPair.secretKey) !== null && _a !== void 0 ? _a : this.keyPair.privateKey;\n const rawSignature = (0, ed25519_1.sign)(secretKey, loginRawDigest);\n try {\n yield client.start({\n id: yield this.getPublicKeyHash(),\n password: `ed:${(0, octez_connect_utils_1.toHex)(rawSignature)}:${yield this.getPublicKey()}`,\n deviceId: (0, octez_connect_utils_1.toHex)(this.keyPair.publicKey)\n });\n }\n catch (error) {\n logger.error('start', 'Could not log in, retrying', error);\n if (error.errcode === 'M_USER_DEACTIVATED') {\n yield this.generateNewKeyPair();\n yield this.reset();\n throw new Error('The account is deactivated.');\n }\n yield this.reset(); // If we can't log in, let's reset\n if (!this.selectedRegion) {\n throw new Error('No region selected.');\n }\n if (this.loginCounter <= ((_b = this.ENABLED_RELAY_SERVERS[this.selectedRegion]) !== null && _b !== void 0 ? _b : []).length) {\n this.loginCounter++;\n this.start();\n return;\n }\n else {\n logger.error('start', 'Tried to log in to every known beacon node, but no login was successful.');\n throw new Error('Could not connect to any beacon nodes. Try again later.');\n }\n }\n logger.log('start', 'login successful, client is ready');\n this.client.resolve(client);\n // Check for any pending invites that we may have missed during the initial sync\n logger.log('start', 'checking for pending invites');\n const invites = yield client.invitedRooms;\n logger.log('start', `found ${invites.length} pending invites`);\n const myUserId = `@${yield this.getPublicKeyHash()}:${relayServer.server}`;\n for (const invite of invites) {\n logger.log('start', `joining invited room: ${invite.id}`);\n yield this.tryJoinRooms(invite.id);\n // Update the peer room mapping for this invite\n if (invite.members.length > 0) {\n const member = invite.members.find((m) => m !== myUserId);\n if (member) {\n yield this.updateRelayServer(member);\n yield this.updatePeerRoom(member, invite.id);\n }\n }\n }\n });\n }\n stop() {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log('stop', 'stopping client');\n if (this.client.isResolved()) {\n yield (yield this.client.promise).stop().catch((error) => logger.error(error));\n }\n yield this.reset();\n });\n }\n reset() {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log('reset', 'resetting connection');\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS).catch((error) => logger.log(error));\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PRESERVED_STATE).catch((error) => logger.log(error));\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_SELECTED_NODE).catch((error) => logger.log(error));\n // Instead of resetting everything, maybe we should make sure a new instance is created?\n this.relayServer = undefined;\n this.client = new octez_connect_utils_2.ExposedPromise();\n this.initialEvent = undefined;\n this.initialListener = undefined;\n });\n }\n listenForEncryptedMessage(senderPublicKey, messageCallback) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.activeListeners.has(senderPublicKey)) {\n return;\n }\n logger.log('listenForEncryptedMessage', `start listening for encrypted messages from publicKey ${senderPublicKey}`);\n const sharedKey = yield this.createCryptoBoxServer(senderPublicKey, this.keyPair);\n const callbackFunction = (event) => __awaiter(this, void 0, void 0, function* () {\n if (this.isTextMessage(event.content) && (yield this.isSender(event, senderPublicKey))) {\n let payload;\n yield this.updateRelayServer(event.content.message.sender);\n yield this.updatePeerRoom(event.content.message.sender, event.content.roomId);\n try {\n payload = Buffer.from(event.content.message.content, 'hex');\n // content can be non-hex if it's a connection open request\n }\n catch (_a) {\n /* */\n }\n if (payload && payload.length >= octez_connect_utils_1.secretbox_NONCEBYTES + octez_connect_utils_1.secretbox_MACBYTES) {\n try {\n const decryptedMessage = yield (0, octez_connect_utils_1.decryptCryptoboxPayload)(payload, sharedKey.receive);\n logger.log('listenForEncryptedMessage', `received a message from ${senderPublicKey}`, decryptedMessage);\n // logger.log(\n // 'listenForEncryptedMessage',\n // 'encrypted message received',\n // decryptedMessage,\n // await new Serializer().deserialize(decryptedMessage)\n // )\n // console.log('calculated sender ID', await getSenderId(senderPublicKey))\n // TODO: Add check for correct decryption key / sender ID\n messageCallback(decryptedMessage);\n }\n catch (decryptionError) {\n /* NO-OP. We try to decode every message, but some might not be addressed to us. */\n }\n }\n }\n });\n this.activeListeners.set(senderPublicKey, callbackFunction);\n (yield this.client.promise).subscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, callbackFunction);\n const lastEvent = this.initialEvent;\n if (lastEvent &&\n lastEvent.timestamp &&\n new Date().getTime() - lastEvent.timestamp < 5 * 60 * 1000) {\n logger.log('listenForEncryptedMessage', 'Handling previous event');\n yield callbackFunction(lastEvent);\n }\n else {\n logger.log('listenForEncryptedMessage', 'No previous event found');\n }\n const initialListener = this.initialListener;\n if (initialListener) {\n ;\n (yield this.client.promise).unsubscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, initialListener);\n }\n this.initialListener = undefined;\n this.initialEvent = undefined;\n });\n }\n unsubscribeFromEncryptedMessage(senderPublicKey) {\n return __awaiter(this, void 0, void 0, function* () {\n const listener = this.activeListeners.get(senderPublicKey);\n if (!listener) {\n return;\n }\n ;\n (yield this.client.promise).unsubscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, listener);\n this.activeListeners.delete(senderPublicKey);\n });\n }\n unsubscribeFromEncryptedMessages() {\n return __awaiter(this, void 0, void 0, function* () {\n ;\n (yield this.client.promise).unsubscribeAll(MatrixClientEvent_1.MatrixClientEventType.MESSAGE);\n this.activeListeners.clear();\n });\n }\n sendMessage(message, peer) {\n return __awaiter(this, void 0, void 0, function* () {\n const sharedKey = yield this.createCryptoBoxClient(peer.publicKey, this.keyPair);\n const recipientHash = yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(peer.publicKey, 'hex'));\n const recipient = (0, octez_connect_utils_1.recipientString)(recipientHash, peer.relayServer);\n const roomId = yield this.getRelevantRoom(recipient);\n // Before we send the message, we have to wait for the join to be accepted.\n // await this.waitForJoin(roomId) // TODO: This can probably be removed because we are now waiting inside the get room method\n const encryptedMessage = yield (0, octez_connect_utils_1.encryptCryptoboxPayload)(message, sharedKey.send);\n logger.log('sendMessage', 'sending encrypted message', peer.publicKey, roomId, message);\n try {\n yield (yield this.client.promise).sendTextMessage(roomId, encryptedMessage);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.code) === 'ERR_CANCELED') {\n logger.log('sendMessage', 'request cancelled while stopping transport');\n return;\n }\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN') {\n logger.log(`sendMessage`, `M_FORBIDDEN`, roomId, error);\n yield this.deleteRoomIdFromRooms(roomId);\n const newRoomId = yield this.getRelevantRoom(recipient);\n logger.log(`sendMessage`, `Old room deleted, new room created`, newRoomId);\n try {\n yield (yield this.client.promise).sendTextMessage(newRoomId, encryptedMessage);\n }\n catch (innerError) {\n if ((innerError === null || innerError === void 0 ? void 0 : innerError.code) === 'ERR_CANCELED') {\n logger.log('sendMessage', 'inner request cancelled while stopping transport');\n return;\n }\n logger.log(`sendMessage`, `inner error`, newRoomId, innerError);\n }\n }\n else {\n logger.log(`sendMessage`, `unexpected error`, error);\n }\n }\n });\n }\n updatePeerRoom(sender, roomId) {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log(`updatePeerRoom`, sender, roomId);\n // Sender is in the format \"@pubkeyhash:relayserver.tld\"\n const split = sender.split(':');\n if (split.length < 2 || !split[0].startsWith('@')) {\n throw new Error('Invalid sender');\n }\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n const room = roomIds[sender];\n if (room === roomId) {\n logger.debug(`updatePeerRoom`, `rooms are the same, not updating`);\n }\n logger.debug(`updatePeerRoom`, `current room`, room, 'new room', roomId);\n if (room && room[1]) {\n // If we have a room already, let's ignore it. We need to do this, otherwise it will be loaded from the matrix cache.\n logger.log(`updatePeerRoom`, `adding room \"${room[1]}\" to ignored array`);\n this.ignoredRooms.push(room[1]);\n }\n roomIds[sender] = roomId;\n yield this.storage.set(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS, roomIds);\n // TODO: We also need to delete the room from the sync state\n // If we need to delete a room, we can assume the local state is not up to date anymore, so we can reset the state\n });\n }\n deleteRoomIdFromRooms(roomId) {\n return __awaiter(this, void 0, void 0, function* () {\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n const newRoomIds = Object.entries(roomIds)\n .filter((entry) => entry[1] !== roomId)\n .reduce((pv, cv) => (Object.assign(Object.assign({}, pv), { [cv[0]]: cv[1] })), {});\n yield this.storage.set(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS, newRoomIds);\n // TODO: We also need to delete the room from the sync state\n // If we need to delete a room, we can assume the local state is not up to date anymore, so we can reset the state\n this.ignoredRooms.push(roomId);\n });\n }\n listenForChannelOpening(messageCallback) {\n return __awaiter(this, void 0, void 0, function* () {\n logger.debug(`listenForChannelOpening`);\n (yield this.client.promise).subscribe(MatrixClientEvent_1.MatrixClientEventType.MESSAGE, (event) => __awaiter(this, void 0, void 0, function* () {\n if (this.isTextMessage(event.content) && (yield this.isChannelOpenMessage(event.content))) {\n logger.log(`listenForChannelOpening`, `channel opening received, trying to decrypt`, JSON.stringify(event));\n yield this.updateRelayServer(event.content.message.sender);\n yield this.updatePeerRoom(event.content.message.sender, event.content.roomId);\n const splits = event.content.message.content.split(':');\n const payload = Buffer.from(splits[splits.length - 1], 'hex');\n if (payload.length >= octez_connect_utils_1.secretbox_NONCEBYTES + octez_connect_utils_1.secretbox_MACBYTES) {\n try {\n const rawResponse = JSON.parse(yield (0, octez_connect_utils_1.openCryptobox)(payload, this.keyPair.publicKey, this.keyPair.secretKey));\n const normalizedProtocol = Number(rawResponse.protocolVersion);\n const pairingResponse = Object.assign(Object.assign({}, rawResponse), { protocolVersion: Number.isFinite(normalizedProtocol) ? normalizedProtocol : undefined });\n logger.log(`listenForChannelOpening`, `channel opening received and decrypted`, JSON.stringify(pairingResponse));\n messageCallback(Object.assign(Object.assign({}, pairingResponse), { senderId: yield (0, octez_connect_core_1.getSenderId)(pairingResponse.publicKey) }));\n }\n catch (decryptionError) {\n /* NO-OP. We try to decode every message, but some might not be addressed to us. */\n }\n }\n }\n }));\n });\n }\n waitForJoin(roomId_1) {\n return __awaiter(this, arguments, void 0, function* (roomId, retry = 0) {\n // Rooms are updated as new events come in. `client.getRoomById` only accesses memory, it does not do any network requests.\n // TODO: Improve to listen to \"JOIN\" event\n const room = yield (yield this.client.promise).getRoomById(roomId);\n logger.log(`waitForJoin`, `Currently ${room.members.length} members, we need at least 2`);\n if (room.members.length >= 2) {\n return;\n }\n else {\n if (retry < 10) {\n logger.log(`Waiting for join... Try: ${retry}`);\n return new Promise((resolve) => {\n // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s, 512s\n const backoffMs = 1000 * Math.pow(2, retry);\n setTimeout(() => {\n resolve(this.waitForJoin(roomId, retry + 1));\n }, backoffMs);\n });\n }\n else {\n throw new Error(`No one joined after ${retry} tries. Room may be orphaned.`);\n }\n }\n });\n }\n sendPairingResponse(pairingRequest) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b;\n logger.log(`sendPairingResponse`);\n const recipientHash = yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(pairingRequest.publicKey, 'hex'));\n const recipient = (0, octez_connect_utils_1.recipientString)(recipientHash, pairingRequest.relayServer);\n // We force room creation here because if we \"re-pair\", we need to make sure that we don't send it to an old room.\n let roomId;\n let roomWasReused = false;\n try {\n roomId = yield (yield this.client.promise).createTrustedPrivateRoom(recipient);\n logger.debug(`sendPairingResponse`, `Connecting to room \"${roomId}\"`);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN' && ((_a = error === null || error === void 0 ? void 0 : error.error) === null || _a === void 0 ? void 0 : _a.includes('already in the room'))) {\n logger.log(`sendPairingResponse`, `M_FORBIDDEN during room creation, finding existing room instead`, error);\n roomWasReused = true;\n // Handle 403 response when invite was sent. Find the existing room, but first, clear our local state to force a fresh lookup\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n const oldRoomId = roomIds[recipient];\n if (oldRoomId) {\n logger.log(`sendPairingResponse`, `Clearing old room \"${oldRoomId}\" from local cache`);\n yield this.deleteRoomIdFromRooms(oldRoomId);\n }\n // Now use getRelevantJoinedRoom which will find the existing room from the server\n // or clear state if we're in an unrecoverable situation with orphaned rooms\n try {\n const room = yield this.getRelevantJoinedRoom(recipient);\n roomId = room.id;\n logger.log(`sendPairingResponse`, `Using existing room \"${roomId}\" from server`);\n }\n catch (innerError) {\n // If we still get M_FORBIDDEN here, it means we have orphaned rooms and the state was cleared\n // We need to stop the client and reconnect to get a fresh sync\n if ((innerError === null || innerError === void 0 ? void 0 : innerError.errcode) === 'M_FORBIDDEN' &&\n ((_b = innerError === null || innerError === void 0 ? void 0 : innerError.error) === null || _b === void 0 ? void 0 : _b.includes('already in the room'))) {\n logger.log(`sendPairingResponse`, `Still getting M_FORBIDDEN after state clear, stopping and restarting client`);\n yield this.stop();\n yield this.start();\n // Try one more time with fresh state\n try {\n const room = yield this.getRelevantJoinedRoom(recipient);\n roomId = room.id;\n logger.log(`sendPairingResponse`, `Successfully found room \"${roomId}\" after restart`);\n }\n catch (finalError) {\n logger.error(`sendPairingResponse`, `Failed to recover after restart`, finalError);\n throw new Error('Unable to pair. Please clear your browser storage and try again.');\n }\n }\n else {\n logger.log(`sendPairingResponse`, `Failed to find existing room`, innerError);\n throw error; // Re-throw original error if we can't recover\n }\n }\n }\n else {\n throw error; // Re-throw if it's not the specific error we're handling\n }\n }\n yield this.updatePeerRoom(recipient, roomId);\n // Check if the other party is in the room\n const room = yield (yield this.client.promise).getRoomById(roomId);\n const hasRecipient = room.members.some((member) => member === recipient);\n if (!hasRecipient) {\n logger.log(`sendPairingResponse`, `Recipient not in room, inviting them to \"${roomId}\"`);\n // The recipient is not in the room. We need to invite them.\n // Since we're reusing a room, the recipient might have been invited before but never joined.\n // Try to invite them again.\n try {\n yield (yield this.client.promise).inviteToRooms(recipient, roomId);\n logger.log(`sendPairingResponse`, `Invited recipient to room, waiting for join`);\n yield this.waitForJoin(roomId);\n }\n catch (inviteError) {\n logger.error(`sendPairingResponse`, `Failed to invite recipient to room`, inviteError);\n // If invite fails, we're in a bad state. The user should clear storage.\n throw new Error('Unable to invite dApp to room. Please clear your browser storage and try again.');\n }\n }\n else if (!roomWasReused) {\n // Room was newly created, wait for the other party to join\n yield this.waitForJoin(roomId);\n logger.debug(`sendPairingResponse`, `Successfully joined room.`);\n }\n else {\n // Room was reused and recipient is already in it\n logger.log(`sendPairingResponse`, `Room was reused and recipient is already a member. Sending message immediately.`);\n }\n // TODO: remove v1 backwards-compatibility\n const message = typeof pairingRequest.version === 'undefined'\n ? yield this.getPublicKey() // v1\n : JSON.stringify(yield this.getPairingResponseInfo(pairingRequest)); // v2\n logger.debug(`sendPairingResponse`, `Sending pairing response`, message);\n const encryptedMessage = yield this.encryptMessageAsymmetric(pairingRequest.publicKey, message);\n const msg = ['@channel-open', recipient, encryptedMessage].join(':');\n try {\n yield (yield this.client.promise).sendTextMessage(roomId, msg);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.code) === 'ERR_CANCELED') {\n logger.log('sendPairingResponse', 'request cancelled while stopping transport');\n return;\n }\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN') {\n logger.log(`sendPairingResponse`, `M_FORBIDDEN`, roomId, error);\n yield this.deleteRoomIdFromRooms(roomId);\n const newRoomId = yield this.getRelevantRoom(recipient);\n logger.log(`sendPairingResponse`, `Old room deleted, new room created`, newRoomId);\n try {\n yield (yield this.client.promise).sendTextMessage(newRoomId, msg);\n }\n catch (innerError) {\n if ((innerError === null || innerError === void 0 ? void 0 : innerError.code) === 'ERR_CANCELED') {\n logger.log('sendPairingResponse', 'inner request cancelled while stopping transport');\n return;\n }\n logger.log(`sendPairingResponse`, `inner error`, newRoomId, innerError);\n }\n }\n else {\n logger.log(`sendPairingResponse`, `unexpected error`, error);\n }\n }\n });\n }\n isTextMessage(content) {\n return content.message.type === MatrixMessage_1.MatrixMessageType.TEXT;\n }\n updateRelayServer(sender) {\n return __awaiter(this, void 0, void 0, function* () {\n logger.log(`updateRelayServer`, sender);\n // Sender is in the format \"@pubkeyhash:relayserver.tld\"\n const split = sender.split(':');\n if (split.length < 2 || !split[0].startsWith('@')) {\n throw new Error('Invalid sender');\n }\n const senderHash = split.shift();\n const relayServer = split.join(':');\n const manager = localStorage.getItem('beacon:communication-peers-dapp')\n ? new octez_connect_core_1.PeerManager(this.storage, octez_connect_types_1.StorageKey.TRANSPORT_P2P_PEERS_DAPP)\n : new octez_connect_core_1.PeerManager(this.storage, octez_connect_types_1.StorageKey.TRANSPORT_P2P_PEERS_WALLET);\n const peers = yield manager.getPeers();\n const promiseArray = peers.map((peer) => __awaiter(this, void 0, void 0, function* () {\n const hash = `@${yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(peer.publicKey, 'hex'))}`;\n if (hash === senderHash) {\n if (peer.relayServer !== relayServer) {\n peer.relayServer = relayServer;\n yield manager.addPeer(peer);\n }\n }\n }));\n yield Promise.all(promiseArray);\n });\n }\n isChannelOpenMessage(content) {\n return __awaiter(this, void 0, void 0, function* () {\n return content.message.content.startsWith(`@channel-open:@${yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(yield this.getPublicKey(), 'hex'))}`);\n });\n }\n isSender(event, senderPublicKey) {\n return __awaiter(this, void 0, void 0, function* () {\n return event.content.message.sender.startsWith(`@${yield (0, octez_connect_utils_1.getHexHash)(Buffer.from(senderPublicKey, 'hex'))}`);\n });\n }\n generateNewKeyPair() {\n return __awaiter(this, void 0, void 0, function* () {\n const newSeed = yield (0, octez_connect_utils_2.generateGUID)();\n console.warn(`The current user ID has been deactivated. Generating new ID: ${newSeed}`);\n this.storage.set(octez_connect_types_1.StorageKey.BEACON_SDK_SECRET_SEED, newSeed);\n this.keyPair = yield (0, octez_connect_utils_1.getKeypairFromSeed)(newSeed);\n });\n }\n getRelevantRoom(recipient) {\n return __awaiter(this, void 0, void 0, function* () {\n const roomIds = yield this.storage.get(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS);\n let roomId = roomIds[recipient];\n if (!roomId) {\n logger.log(`getRelevantRoom`, `No room found for peer ${recipient}, checking joined ones.`);\n const room = yield this.getRelevantJoinedRoom(recipient);\n roomId = room.id;\n roomIds[recipient] = room.id;\n yield this.storage.set(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS, roomIds);\n }\n logger.log(`getRelevantRoom`, `Using room ${roomId}`);\n return roomId;\n });\n }\n getRelevantJoinedRoom(recipient) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const joinedRooms = yield (yield this.client.promise).joinedRooms;\n logger.log('checking joined rooms', joinedRooms, recipient);\n const relevantRooms = joinedRooms\n .filter((roomElement) => !this.ignoredRooms.some((id) => roomElement.id === id))\n .filter((roomElement) => roomElement.members.some((member) => member === recipient));\n let room;\n // If we found relevant rooms, use them even if there are ignored rooms\n if (relevantRooms.length > 0) {\n room = relevantRooms[0];\n logger.log(`getRelevantJoinedRoom`, `channel already open, reusing room ${room.id}`);\n }\n else {\n // No relevant rooms found. If we have ignored rooms, we're in a bad state and need to reset.\n if (this.ignoredRooms.length > 0) {\n logger.log(`getRelevantJoinedRoom`, `no relevant rooms found but have ${this.ignoredRooms.length} ignored rooms, clearing Matrix state`);\n // Clear the Matrix preserved state to force a fresh sync on next connection\n yield this.storage\n .delete(octez_connect_types_1.StorageKey.MATRIX_PRESERVED_STATE)\n .catch((error) => logger.log(error));\n yield this.storage\n .delete(octez_connect_types_1.StorageKey.MATRIX_PEER_ROOM_IDS)\n .catch((error) => logger.log(error));\n // Clear ignored rooms list since we're resetting\n this.ignoredRooms.length = 0;\n }\n logger.log(`getRelevantJoinedRoom`, `no relevant rooms found, creating new one`);\n try {\n const roomId = yield (yield this.client.promise).createTrustedPrivateRoom(recipient);\n room = yield (yield this.client.promise).getRoomById(roomId);\n logger.log(`getRelevantJoinedRoom`, `waiting for other party to join room: ${room.id}`);\n yield this.waitForJoin(roomId);\n logger.log(`getRelevantJoinedRoom`, `new room created and peer invited: ${room.id}`);\n }\n catch (error) {\n if ((error === null || error === void 0 ? void 0 : error.errcode) === 'M_FORBIDDEN' && ((_a = error === null || error === void 0 ? void 0 : error.error) === null || _a === void 0 ? void 0 : _a.includes('already in the room'))) {\n // Server knows about a room we don't have locally\n // Clear preserved state so next reconnect gets a fresh sync\n logger.log(`getRelevantJoinedRoom`, `M_FORBIDDEN on room creation, clearing preserved state for fresh sync on reconnect`);\n yield this.storage.delete(octez_connect_types_1.StorageKey.MATRIX_PRESERVED_STATE).catch((e) => logger.log(e));\n // Re-throw the error so caller (sendPairingResponse) can handle the restart\n throw error;\n }\n throw error;\n }\n }\n return room;\n });\n }\n}\nexports.P2PCommunicationClient = P2PCommunicationClient;\n//# sourceMappingURL=P2PCommunicationClient.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-transport-matrix/dist/cjs/communication-client/P2PCommunicationClient.js?\n}")},"./packages/octez.connect-transport-matrix/dist/cjs/index.js":
302
302
  /*!*******************************************************************!*\
303
303
  !*** ./packages/octez.connect-transport-matrix/dist/cjs/index.js ***!
304
304
  \*******************************************************************/(__unused_webpack_module,exports,__webpack_require__)=>{"use strict";eval('{\nObject.defineProperty(exports, "__esModule", ({ value: true }));\nexports.P2PTransport = exports.P2PCommunicationClient = void 0;\nvar P2PCommunicationClient_1 = __webpack_require__(/*! ./communication-client/P2PCommunicationClient */ "./packages/octez.connect-transport-matrix/dist/cjs/communication-client/P2PCommunicationClient.js");\nObject.defineProperty(exports, "P2PCommunicationClient", ({ enumerable: true, get: function () { return P2PCommunicationClient_1.P2PCommunicationClient; } }));\nvar P2PTransport_1 = __webpack_require__(/*! ./P2PTransport */ "./packages/octez.connect-transport-matrix/dist/cjs/P2PTransport.js");\nObject.defineProperty(exports, "P2PTransport", ({ enumerable: true, get: function () { return P2PTransport_1.P2PTransport; } }));\n//# sourceMappingURL=index.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-transport-matrix/dist/cjs/index.js?\n}')},"./packages/octez.connect-transport-matrix/dist/cjs/matrix-client/EventEmitter.js":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tezos-x/octez.connect-wallet",
3
- "version": "5.0.0-beta.4",
3
+ "version": "5.0.0-beta.5",
4
4
  "description": "Use this package in your wallet to instanciate a WalletClient object and communicate to dApps.",
5
5
  "author": "Blockchain Infra <blockchain.infra@trili.tech>",
6
6
  "homepage": "https://octez-connect.tezos.com",
@@ -35,9 +35,9 @@
35
35
  "url": "https://github.com/trilitech/octez.connect/issues"
36
36
  },
37
37
  "dependencies": {
38
- "@tezos-x/octez.connect-core": "5.0.0-beta.4",
39
- "@tezos-x/octez.connect-transport-matrix": "5.0.0-beta.4",
40
- "@tezos-x/octez.connect-transport-postmessage": "5.0.0-beta.4"
38
+ "@tezos-x/octez.connect-core": "5.0.0-beta.5",
39
+ "@tezos-x/octez.connect-transport-matrix": "5.0.0-beta.5",
40
+ "@tezos-x/octez.connect-transport-postmessage": "5.0.0-beta.5"
41
41
  },
42
- "gitHead": "7db6bb82726ff255f602661c878e8e2844bba193"
42
+ "gitHead": "703ee5e3ef152e5e56ac56bce3e0869cd374e31f"
43
43
  }