@tezos-x/octez.connect-wallet 4.8.1 → 4.8.3
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.
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
\***********************************************************************/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 BeaconClient_1 = __webpack_require__(/*! ../beacon-client/BeaconClient */ "./packages/octez.connect-core/dist/cjs/clients/beacon-client/BeaconClient.js");\nconst AccountManager_1 = __webpack_require__(/*! ../../managers/AccountManager */ "./packages/octez.connect-core/dist/cjs/managers/AccountManager.js");\nconst get_sender_id_1 = __webpack_require__(/*! ../../utils/get-sender-id */ "./packages/octez.connect-core/dist/cjs/utils/get-sender-id.js");\nconst Logger_1 = __webpack_require__(/*! ../../utils/Logger */ "./packages/octez.connect-core/dist/cjs/utils/Logger.js");\nconst Serializer_1 = __webpack_require__(/*! ../../Serializer */ "./packages/octez.connect-core/dist/cjs/Serializer.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 /**\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 * 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 const deserializedMessage = (yield new Serializer_1.Serializer().deserialize(message));\n this.handleResponse(deserializedMessage, connectionInfo);\n }\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 request = {\n id: yield (0, octez_connect_utils_1.generateGUID)(),\n version: peer.version,\n senderId: yield (0, get_sender_id_1.getSenderId)(yield this.beaconId),\n type: octez_connect_types_1.BeaconMessageType.Disconnect\n };\n const payload = yield new Serializer_1.Serializer().serialize(request);\n const selectedTransport = transport !== null && transport !== void 0 ? transport : (yield this.transport);\n yield selectedTransport.send(payload, peer);\n });\n }\n}\nexports.Client = Client;\n//# sourceMappingURL=Client.js.map\n\n//# sourceURL=webpack://beacon/./packages/octez.connect-core/dist/cjs/clients/client/Client.js?\n}')},"./packages/octez.connect-core/dist/cjs/constants.js":
|
|
173
173
|
/*!***********************************************************!*\
|
|
174
174
|
!*** ./packages/octez.connect-core/dist/cjs/constants.js ***!
|
|
175
|
-
\***********************************************************/(__unused_webpack_module,exports)=>{"use strict";eval("{\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.BACKEND_URL = exports.NOTIFICATION_ORACLE_URL = exports.BEACON_VERSION = exports.SDK_VERSION = void 0;\nexports.SDK_VERSION = '4.8.
|
|
175
|
+
\***********************************************************/(__unused_webpack_module,exports)=>{"use strict";eval("{\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.BACKEND_URL = exports.NOTIFICATION_ORACLE_URL = exports.BEACON_VERSION = exports.SDK_VERSION = void 0;\nexports.SDK_VERSION = '4.8.3';\nexports.BEACON_VERSION = '3';\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/constants.js?\n}")},"./packages/octez.connect-core/dist/cjs/debug.js":
|
|
176
176
|
/*!*******************************************************!*\
|
|
177
177
|
!*** ./packages/octez.connect-core/dist/cjs/debug.js ***!
|
|
178
178
|
\*******************************************************/(__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/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/debug.js?\n}')},"./packages/octez.connect-core/dist/cjs/errors/AbortedBeaconError.js":
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
\**************************************************************************/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/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":
|
|
284
284
|
/*!*********************************************************************************************************!*\
|
|
285
285
|
!*** ./packages/octez.connect-transport-matrix/dist/cjs/communication-client/P2PCommunicationClient.js ***!
|
|
286
|
-
\*********************************************************************************************************/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};\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 = __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/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);\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);\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 });\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 (yield this.client.promise).sendTextMessage(roomId, encryptedMessage).catch((error) => __awaiter(this, void 0, void 0, function* () {\n if (error.errcode === 'M_FORBIDDEN') {\n // Room doesn't exist\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 (yield this.client.promise)\n .sendTextMessage(newRoomId, encryptedMessage)\n .catch((error2) => __awaiter(this, void 0, void 0, function* () {\n logger.log(`sendMessage`, `inner error`, newRoomId, error2);\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 pairingResponse = JSON.parse(yield (0, octez_connect_utils_1.openCryptobox)(payload, this.keyPair.publicKey, this.keyPair.secretKey));\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 <= 200) {\n // On mobile, due to app switching, we potentially have to wait for a long time\n logger.log(`Waiting for join... Try: ${retry}`);\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(this.waitForJoin(roomId, retry + 1));\n }, 100 * (retry > 50 ? 10 : 1)); // After the initial 5 seconds, retry only once per second\n });\n }\n else {\n throw new Error(`No one joined after ${retry} tries.`);\n }\n }\n });\n }\n sendPairingResponse(pairingRequest) {\n return __awaiter(this, void 0, void 0, function* () {\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 const roomId = yield (yield this.client.promise).createTrustedPrivateRoom(recipient);\n logger.debug(`sendPairingResponse`, `Connecting to room \"${roomId}\"`);\n yield this.updatePeerRoom(recipient, roomId);\n // Before we send the message, we have to wait for the join to be accepted.\n yield this.waitForJoin(roomId); // TODO: This can probably be removed because we are now waiting inside the get room method\n logger.debug(`sendPairingResponse`, `Successfully joined room.`);\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 (yield this.client.promise).sendTextMessage(roomId, msg).catch((error) => __awaiter(this, void 0, void 0, function* () {\n if (error.errcode === 'M_FORBIDDEN') {\n // Room doesn't exist\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 (yield this.client.promise).sendTextMessage(newRoomId, msg).catch((error2) => __awaiter(this, void 0, void 0, function* () {\n logger.log(`sendPairingResponse`, `inner error`, newRoomId, error2);\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 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 // We always create a new room if one has been ignored. This is because if we ignore one, we know the server state changed.\n // So we cannot trust the current sync state. This can be removed once we have a method to properly clear and refresh the sync state.\n if (relevantRooms.length === 0 || this.ignoredRooms.length > 0) {\n logger.log(`getRelevantJoinedRoom`, `no relevant rooms found, creating new one`);\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 else {\n room = relevantRooms[0];\n logger.log(`getRelevantJoinedRoom`, `channel already open, reusing room ${room.id}`);\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":
|
|
286
|
+
\*********************************************************************************************************/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};\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 = __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/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);\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);\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 });\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 (yield this.client.promise).sendTextMessage(roomId, encryptedMessage).catch((error) => __awaiter(this, void 0, void 0, function* () {\n if (error.errcode === 'M_FORBIDDEN') {\n // Room doesn't exist\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 (yield this.client.promise)\n .sendTextMessage(newRoomId, encryptedMessage)\n .catch((error2) => __awaiter(this, void 0, void 0, function* () {\n logger.log(`sendMessage`, `inner error`, newRoomId, error2);\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 pairingResponse = JSON.parse(yield (0, octez_connect_utils_1.openCryptobox)(payload, this.keyPair.publicKey, this.keyPair.secretKey));\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 <= 200) {\n // On mobile, due to app switching, we potentially have to wait for a long time\n logger.log(`Waiting for join... Try: ${retry}`);\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(this.waitForJoin(roomId, retry + 1));\n }, 100 * (retry > 50 ? 10 : 1)); // After the initial 5 seconds, retry only once per second\n });\n }\n else {\n throw new Error(`No one joined after ${retry} tries.`);\n }\n }\n });\n }\n sendPairingResponse(pairingRequest) {\n return __awaiter(this, void 0, void 0, function* () {\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 const roomId = yield (yield this.client.promise).createTrustedPrivateRoom(recipient);\n logger.debug(`sendPairingResponse`, `Connecting to room \"${roomId}\"`);\n yield this.updatePeerRoom(recipient, roomId);\n // Before we send the message, we have to wait for the join to be accepted.\n yield this.waitForJoin(roomId); // TODO: This can probably be removed because we are now waiting inside the get room method\n logger.debug(`sendPairingResponse`, `Successfully joined room.`);\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 (yield this.client.promise).sendTextMessage(roomId, msg).catch((error) => __awaiter(this, void 0, void 0, function* () {\n if (error.errcode === 'M_FORBIDDEN') {\n // Room doesn't exist\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 (yield this.client.promise).sendTextMessage(newRoomId, msg).catch((error2) => __awaiter(this, void 0, void 0, function* () {\n logger.log(`sendPairingResponse`, `inner error`, newRoomId, error2);\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 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 // We always create a new room if one has been ignored. This is because if we ignore one, we know the server state changed.\n // So we cannot trust the current sync state. This can be removed once we have a method to properly clear and refresh the sync state.\n if (relevantRooms.length === 0 || this.ignoredRooms.length > 0) {\n logger.log(`getRelevantJoinedRoom`, `no relevant rooms found, creating new one`);\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 else {\n room = relevantRooms[0];\n logger.log(`getRelevantJoinedRoom`, `channel already open, reusing room ${room.id}`);\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":
|
|
287
287
|
/*!*******************************************************************!*\
|
|
288
288
|
!*** ./packages/octez.connect-transport-matrix/dist/cjs/index.js ***!
|
|
289
289
|
\*******************************************************************/(__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": "4.8.
|
|
3
|
+
"version": "4.8.3",
|
|
4
4
|
"description": "Use this package in your wallet to instanciate a WalletClient object and communicate to dApps.",
|
|
5
5
|
"author": "Andreas Gassmann <a.gassmann@papers.ch>",
|
|
6
6
|
"license": "ISC",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"url": "https://github.com/trilitech/octez.connect-sdk/issues"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@tezos-x/octez.connect-core": "4.8.
|
|
38
|
-
"@tezos-x/octez.connect-transport-matrix": "4.8.
|
|
39
|
-
"@tezos-x/octez.connect-transport-postmessage": "4.8.
|
|
37
|
+
"@tezos-x/octez.connect-core": "4.8.3",
|
|
38
|
+
"@tezos-x/octez.connect-transport-matrix": "4.8.3",
|
|
39
|
+
"@tezos-x/octez.connect-transport-postmessage": "4.8.3"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "c3bee29569f7de3fc686944f392c67999027b1a1"
|
|
42
42
|
}
|