@tezos-x/octez.connect-dapp 0.9.0
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.
- package/LICENCE +19 -0
- package/README.md +16 -0
- package/dist/cjs/beacon-message-events.d.ts +9 -0
- package/dist/cjs/beacon-message-events.js +109 -0
- package/dist/cjs/beacon-message-events.js.map +1 -0
- package/dist/cjs/dapp-client/DAppClient.d.ts +282 -0
- package/dist/cjs/dapp-client/DAppClient.js +2073 -0
- package/dist/cjs/dapp-client/DAppClient.js.map +1 -0
- package/dist/cjs/dapp-client/DAppClientOptions.d.ts +117 -0
- package/dist/cjs/dapp-client/DAppClientOptions.js +3 -0
- package/dist/cjs/dapp-client/DAppClientOptions.js.map +1 -0
- package/dist/cjs/events.d.ts +209 -0
- package/dist/cjs/events.js +718 -0
- package/dist/cjs/events.js.map +1 -0
- package/dist/cjs/index.d.ts +15 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/transports/DappP2PTransport.d.ts +14 -0
- package/dist/cjs/transports/DappP2PTransport.js +53 -0
- package/dist/cjs/transports/DappP2PTransport.js.map +1 -0
- package/dist/cjs/transports/DappPostMessageTransport.d.ts +14 -0
- package/dist/cjs/transports/DappPostMessageTransport.js +53 -0
- package/dist/cjs/transports/DappPostMessageTransport.js.map +1 -0
- package/dist/cjs/transports/DappWalletConnectTransport.d.ts +17 -0
- package/dist/cjs/transports/DappWalletConnectTransport.js +52 -0
- package/dist/cjs/transports/DappWalletConnectTransport.js.map +1 -0
- package/dist/cjs/utils/available-transports.d.ts +4 -0
- package/dist/cjs/utils/available-transports.js +12 -0
- package/dist/cjs/utils/available-transports.js.map +1 -0
- package/dist/cjs/utils/block-explorer.d.ts +24 -0
- package/dist/cjs/utils/block-explorer.js +24 -0
- package/dist/cjs/utils/block-explorer.js.map +1 -0
- package/dist/cjs/utils/get-instance.d.ts +4 -0
- package/dist/cjs/utils/get-instance.js +21 -0
- package/dist/cjs/utils/get-instance.js.map +1 -0
- package/dist/cjs/utils/shorten-string.d.ts +1 -0
- package/dist/cjs/utils/shorten-string.js +11 -0
- package/dist/cjs/utils/shorten-string.js.map +1 -0
- package/dist/cjs/utils/tzkt-blockexplorer.d.ts +12 -0
- package/dist/cjs/utils/tzkt-blockexplorer.js +59 -0
- package/dist/cjs/utils/tzkt-blockexplorer.js.map +1 -0
- package/dist/esm/beacon-message-events.d.ts +9 -0
- package/dist/esm/beacon-message-events.js +106 -0
- package/dist/esm/beacon-message-events.js.map +1 -0
- package/dist/esm/dapp-client/DAppClient.d.ts +282 -0
- package/dist/esm/dapp-client/DAppClient.js +2001 -0
- package/dist/esm/dapp-client/DAppClient.js.map +1 -0
- package/dist/esm/dapp-client/DAppClientOptions.d.ts +117 -0
- package/dist/esm/dapp-client/DAppClientOptions.js +2 -0
- package/dist/esm/dapp-client/DAppClientOptions.js.map +1 -0
- package/dist/esm/events.d.ts +209 -0
- package/dist/esm/events.js +702 -0
- package/dist/esm/events.js.map +1 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/transports/DappP2PTransport.d.ts +14 -0
- package/dist/esm/transports/DappP2PTransport.js +34 -0
- package/dist/esm/transports/DappP2PTransport.js.map +1 -0
- package/dist/esm/transports/DappPostMessageTransport.d.ts +14 -0
- package/dist/esm/transports/DappPostMessageTransport.js +34 -0
- package/dist/esm/transports/DappPostMessageTransport.js.map +1 -0
- package/dist/esm/transports/DappWalletConnectTransport.d.ts +17 -0
- package/dist/esm/transports/DappWalletConnectTransport.js +35 -0
- package/dist/esm/transports/DappWalletConnectTransport.js.map +1 -0
- package/dist/esm/utils/available-transports.d.ts +4 -0
- package/dist/esm/utils/available-transports.js +9 -0
- package/dist/esm/utils/available-transports.js.map +1 -0
- package/dist/esm/utils/block-explorer.d.ts +24 -0
- package/dist/esm/utils/block-explorer.js +10 -0
- package/dist/esm/utils/block-explorer.js.map +1 -0
- package/dist/esm/utils/get-instance.d.ts +4 -0
- package/dist/esm/utils/get-instance.js +17 -0
- package/dist/esm/utils/get-instance.js.map +1 -0
- package/dist/esm/utils/shorten-string.d.ts +1 -0
- package/dist/esm/utils/shorten-string.js +7 -0
- package/dist/esm/utils/shorten-string.js.map +1 -0
- package/dist/esm/utils/tzkt-blockexplorer.d.ts +12 -0
- package/dist/esm/utils/tzkt-blockexplorer.js +43 -0
- package/dist/esm/utils/tzkt-blockexplorer.js.map +1 -0
- package/dist/octez.connect.dapp.min.js +1066 -0
- package/dist/walletbeacon.dapp.min.js +1066 -0
- package/package.json +45 -0
|
@@ -0,0 +1,2073 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DAppClient = void 0;
|
|
13
|
+
const axios_1 = require("axios");
|
|
14
|
+
const bs58check_1 = require("bs58check");
|
|
15
|
+
const events_1 = require("../events");
|
|
16
|
+
const octez_connect_types_1 = require("@tezos-x/octez.connect-types");
|
|
17
|
+
const octez_connect_core_1 = require("@tezos-x/octez.connect-core");
|
|
18
|
+
const octez_connect_utils_1 = require("@tezos-x/octez.connect-utils");
|
|
19
|
+
const beacon_message_events_1 = require("../beacon-message-events");
|
|
20
|
+
const tzkt_blockexplorer_1 = require("../utils/tzkt-blockexplorer");
|
|
21
|
+
const octez_connect_dapp_1 = require("@tezos-x/octez.connect-dapp");
|
|
22
|
+
const DappPostMessageTransport_1 = require("../transports/DappPostMessageTransport");
|
|
23
|
+
const DappP2PTransport_1 = require("../transports/DappP2PTransport");
|
|
24
|
+
const DappWalletConnectTransport_1 = require("../transports/DappWalletConnectTransport");
|
|
25
|
+
const octez_connect_transport_postmessage_1 = require("@tezos-x/octez.connect-transport-postmessage");
|
|
26
|
+
const octez_connect_ui_1 = require("@tezos-x/octez.connect-ui");
|
|
27
|
+
const octez_connect_transport_walletconnect_1 = require("@tezos-x/octez.connect-transport-walletconnect");
|
|
28
|
+
const logger = new octez_connect_core_1.Logger('DAppClient');
|
|
29
|
+
/**
|
|
30
|
+
* @publicapi
|
|
31
|
+
*
|
|
32
|
+
* The DAppClient has to be used in decentralized applications. It handles all the logic related to connecting to beacon-compatible
|
|
33
|
+
* wallets and sending requests.
|
|
34
|
+
*
|
|
35
|
+
* @category DApp
|
|
36
|
+
*/
|
|
37
|
+
class DAppClient extends octez_connect_core_1.Client {
|
|
38
|
+
constructor(config) {
|
|
39
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
40
|
+
super(Object.assign({ storage: config && config.storage ? config.storage : new octez_connect_core_1.LocalStorage() }, config));
|
|
41
|
+
this.events = new octez_connect_dapp_1.BeaconEventHandler();
|
|
42
|
+
this.isGetActiveAccountHandled = false;
|
|
43
|
+
this.openRequestsOtherTabs = new Set();
|
|
44
|
+
/**
|
|
45
|
+
* A map of requests that are currently "open", meaning we have sent them to a wallet and are still awaiting a response.
|
|
46
|
+
*/
|
|
47
|
+
this.openRequests = new Map();
|
|
48
|
+
/**
|
|
49
|
+
* The currently active account. For all requests that are associated to a specific request (operation request, signing request),
|
|
50
|
+
* the active account is used to determine the network and destination wallet
|
|
51
|
+
*/
|
|
52
|
+
this._activeAccount = new octez_connect_utils_1.ExposedPromise();
|
|
53
|
+
/**
|
|
54
|
+
* The currently active peer. This is used to address a peer in case the active account is not set. (Eg. for permission requests)
|
|
55
|
+
*/
|
|
56
|
+
this._activePeer = new octez_connect_utils_1.ExposedPromise();
|
|
57
|
+
this.isInitPending = false;
|
|
58
|
+
this.beaconIDB = new octez_connect_core_1.IndexedDBStorage('beacon', ['bug_report', 'metrics']);
|
|
59
|
+
this.debounceSetActiveAccount = false;
|
|
60
|
+
this.multiTabChannel = new octez_connect_core_1.MultiTabChannel('octez.connect-sdk-channel', this.onBCMessageHandler.bind(this), this.onElectedLeaderhandler.bind(this));
|
|
61
|
+
this.blockchains = new Map();
|
|
62
|
+
this.description = config.description;
|
|
63
|
+
this.wcProjectId = ((_a = config.walletConnectOptions) === null || _a === void 0 ? void 0 : _a.projectId) || '24469fd0a06df227b6e5f7dc7de0ff4f';
|
|
64
|
+
this.wcRelayUrl = (_b = config.walletConnectOptions) === null || _b === void 0 ? void 0 : _b.relayUrl;
|
|
65
|
+
this.featuredWallets = config.featuredWallets;
|
|
66
|
+
this.events = new octez_connect_dapp_1.BeaconEventHandler(config.eventHandlers, (_c = config.disableDefaultEvents) !== null && _c !== void 0 ? _c : false);
|
|
67
|
+
this.blockExplorer = (_d = config.blockExplorer) !== null && _d !== void 0 ? _d : new tzkt_blockexplorer_1.TzktBlockExplorer();
|
|
68
|
+
this.network = (_e = config.network) !== null && _e !== void 0 ? _e : { type: (_f = config.preferredNetwork) !== null && _f !== void 0 ? _f : octez_connect_types_1.NetworkType.MAINNET };
|
|
69
|
+
(0, octez_connect_ui_1.setColorMode)((_g = config.colorMode) !== null && _g !== void 0 ? _g : octez_connect_types_1.ColorMode.LIGHT);
|
|
70
|
+
this.disclaimerText = config.disclaimerText;
|
|
71
|
+
this.errorMessages = (_h = config.errorMessages) !== null && _h !== void 0 ? _h : {};
|
|
72
|
+
this.appMetadataManager = new octez_connect_core_1.AppMetadataManager(this.storage);
|
|
73
|
+
this.storageValidator = new octez_connect_core_1.StorageValidator(this.storage);
|
|
74
|
+
this.enableAppSwitching =
|
|
75
|
+
config.enableAppSwitching === undefined ? true : !!config.enableAppSwitching;
|
|
76
|
+
this.enableMetrics = config.enableMetrics ? true : false;
|
|
77
|
+
// Subscribe to storage changes and update the active account if it changes on other tabs
|
|
78
|
+
this.storage.subscribeToStorageChanged((event) => __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
if (event.eventType === 'storageCleared') {
|
|
80
|
+
this.setActiveAccount(undefined);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (event.eventType === 'entryModified') {
|
|
84
|
+
if (event.key === this.storage.getPrefixedKey(octez_connect_types_1.StorageKey.ACTIVE_ACCOUNT)) {
|
|
85
|
+
const accountIdentifier = event.newValue;
|
|
86
|
+
if (!accountIdentifier || accountIdentifier === 'undefined') {
|
|
87
|
+
this.setActiveAccount(undefined);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const account = yield this.getAccount(accountIdentifier);
|
|
91
|
+
this.setActiveAccount(account);
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (event.key === this.storage.getPrefixedKey(octez_connect_types_1.StorageKey.ENABLE_METRICS)) {
|
|
96
|
+
this.enableMetrics = !!(yield this.storage.get(octez_connect_types_1.StorageKey.ENABLE_METRICS));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (event.key === this.storage.getPrefixedKey(octez_connect_types_1.StorageKey.BEACON_SDK_SECRET_SEED)) {
|
|
100
|
+
this._keyPair = new octez_connect_utils_1.ExposedPromise();
|
|
101
|
+
this._beaconId = new octez_connect_utils_1.ExposedPromise();
|
|
102
|
+
yield this.initSDK();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}));
|
|
107
|
+
this.activeAccountLoaded = this.storage
|
|
108
|
+
.get(octez_connect_types_1.StorageKey.ACTIVE_ACCOUNT)
|
|
109
|
+
.then((activeAccountIdentifier) => __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
if (activeAccountIdentifier) {
|
|
111
|
+
const account = yield this.accountManager.getAccount(activeAccountIdentifier);
|
|
112
|
+
yield this.setActiveAccount(account);
|
|
113
|
+
return account;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
yield this.setActiveAccount(undefined);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
}))
|
|
120
|
+
.catch((storageError) => __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
logger.error(storageError);
|
|
122
|
+
yield this.resetInvalidState(false);
|
|
123
|
+
this.events.emit(events_1.BeaconEvent.INVALID_ACCOUNT_DEACTIVATED);
|
|
124
|
+
return undefined;
|
|
125
|
+
}));
|
|
126
|
+
this.handleResponse = (message, connectionInfo) => __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
var _a;
|
|
128
|
+
const typedMessage = message.version === '3'
|
|
129
|
+
? message.message
|
|
130
|
+
: message;
|
|
131
|
+
let appMetadata = message.version === '3'
|
|
132
|
+
? (_a = typedMessage.blockchainData) === null || _a === void 0 ? void 0 : _a.appMetadata
|
|
133
|
+
: typedMessage.appMetadata;
|
|
134
|
+
if (!appMetadata && message.version === '3') {
|
|
135
|
+
const storedMetadata = yield Promise.all([
|
|
136
|
+
this.storage.get(octez_connect_types_1.StorageKey.TRANSPORT_P2P_PEERS_DAPP),
|
|
137
|
+
this.storage.get(octez_connect_types_1.StorageKey.TRANSPORT_WALLETCONNECT_PEERS_DAPP),
|
|
138
|
+
this.storage.get(octez_connect_types_1.StorageKey.TRANSPORT_POSTMESSAGE_PEERS_DAPP)
|
|
139
|
+
]);
|
|
140
|
+
for (const peers of storedMetadata) {
|
|
141
|
+
const peer = peers.find((peer) => peer.senderId === message.senderId);
|
|
142
|
+
if (!peer) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const wallet = yield this.getWalletInfo();
|
|
146
|
+
appMetadata = {
|
|
147
|
+
name: peer.name,
|
|
148
|
+
senderId: peer.senderId,
|
|
149
|
+
icon: wallet.icon
|
|
150
|
+
};
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (this.openRequestsOtherTabs.has(message.id)) {
|
|
155
|
+
this.multiTabChannel.postMessage({
|
|
156
|
+
type: 'RESPONSE',
|
|
157
|
+
data: {
|
|
158
|
+
message,
|
|
159
|
+
connectionInfo
|
|
160
|
+
},
|
|
161
|
+
id: message.id
|
|
162
|
+
});
|
|
163
|
+
if (typedMessage.type !== octez_connect_types_1.BeaconMessageType.Acknowledge) {
|
|
164
|
+
this.openRequestsOtherTabs.delete(message.id);
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const openRequest = this.openRequests.get(message.id);
|
|
169
|
+
logger.log('### openRequest ###', openRequest);
|
|
170
|
+
logger.log('handleResponse', 'Received message', message, connectionInfo);
|
|
171
|
+
logger.log('### message ###', JSON.stringify(message));
|
|
172
|
+
logger.log('### connectionInfo ###', connectionInfo);
|
|
173
|
+
const handleDisconnect = () => __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
var _a;
|
|
175
|
+
this.analytics.track('event', 'DAppClient', 'Disconnect received from Wallet');
|
|
176
|
+
const relevantTransport = connectionInfo.origin === octez_connect_types_1.Origin.P2P
|
|
177
|
+
? this.p2pTransport
|
|
178
|
+
: connectionInfo.origin === octez_connect_types_1.Origin.WALLETCONNECT
|
|
179
|
+
? this.walletConnectTransport
|
|
180
|
+
: ((_a = this.postMessageTransport) !== null && _a !== void 0 ? _a : (yield this.transport));
|
|
181
|
+
if (relevantTransport) {
|
|
182
|
+
const peers = yield relevantTransport.getPeers();
|
|
183
|
+
const peer = peers.find((peerEl) => peerEl.senderId === message.senderId);
|
|
184
|
+
if (peer) {
|
|
185
|
+
yield relevantTransport.removePeer(peer);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
yield this.removeAccountsForPeerIds([message.senderId]);
|
|
189
|
+
yield this.events.emit(events_1.BeaconEvent.CHANNEL_CLOSED);
|
|
190
|
+
});
|
|
191
|
+
if (openRequest && typedMessage.type === octez_connect_types_1.BeaconMessageType.Acknowledge) {
|
|
192
|
+
this.analytics.track('event', 'DAppClient', 'Acknowledge received from Wallet');
|
|
193
|
+
logger.log('handleResponse', `acknowledge message received for ${message.id}`);
|
|
194
|
+
this.events
|
|
195
|
+
.emit(events_1.BeaconEvent.ACKNOWLEDGE_RECEIVED, {
|
|
196
|
+
message: typedMessage,
|
|
197
|
+
extraInfo: {},
|
|
198
|
+
walletInfo: yield this.getWalletInfo()
|
|
199
|
+
})
|
|
200
|
+
.catch(console.error);
|
|
201
|
+
}
|
|
202
|
+
else if (openRequest) {
|
|
203
|
+
if (typedMessage.type === octez_connect_types_1.BeaconMessageType.PermissionResponse && appMetadata) {
|
|
204
|
+
yield this.appMetadataManager.addAppMetadata(appMetadata);
|
|
205
|
+
}
|
|
206
|
+
if (typedMessage.type === octez_connect_types_1.BeaconMessageType.Error) {
|
|
207
|
+
openRequest.reject(typedMessage);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
openRequest.resolve({ message, connectionInfo });
|
|
211
|
+
}
|
|
212
|
+
this.openRequests.delete(typedMessage.id);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
if (typedMessage.type === octez_connect_types_1.BeaconMessageType.Disconnect) {
|
|
216
|
+
yield handleDisconnect();
|
|
217
|
+
}
|
|
218
|
+
else if (typedMessage.type === octez_connect_types_1.BeaconMessageType.ChangeAccountRequest) {
|
|
219
|
+
yield this.onNewAccount(typedMessage, connectionInfo);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (this._transport.isResolved()) {
|
|
223
|
+
const transport = yield this.transport;
|
|
224
|
+
if (transport instanceof octez_connect_transport_walletconnect_1.WalletConnectTransport &&
|
|
225
|
+
!this.openRequests.has('session_update')) {
|
|
226
|
+
this.openRequests.set('session_update', new octez_connect_utils_1.ExposedPromise());
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
this.storageValidator
|
|
231
|
+
.validate()
|
|
232
|
+
.then((isValid) => __awaiter(this, void 0, void 0, function* () {
|
|
233
|
+
var _a, _b;
|
|
234
|
+
const account = yield this.activeAccountLoaded;
|
|
235
|
+
if (!isValid) {
|
|
236
|
+
const info = yield this.getWalletInfo(undefined, account, false);
|
|
237
|
+
info.type =
|
|
238
|
+
info.type === 'extension' && (account === null || account === void 0 ? void 0 : account.origin.type) === octez_connect_types_1.Origin.P2P ? 'mobile' : info.type;
|
|
239
|
+
yield this.storage.set(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET, {
|
|
240
|
+
icon: (_a = info.icon) !== null && _a !== void 0 ? _a : '',
|
|
241
|
+
key: info.name,
|
|
242
|
+
type: (_b = info.type) !== null && _b !== void 0 ? _b : 'web',
|
|
243
|
+
name: info.name,
|
|
244
|
+
url: info.deeplink
|
|
245
|
+
});
|
|
246
|
+
const nowValid = yield this.storageValidator.validate();
|
|
247
|
+
if (!nowValid) {
|
|
248
|
+
this.resetInvalidState(false);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (account && account.origin.type !== 'p2p') {
|
|
252
|
+
this.init();
|
|
253
|
+
}
|
|
254
|
+
}))
|
|
255
|
+
.catch((err) => logger.error(err.message));
|
|
256
|
+
this.sendMetrics('enable-metrics?' + this.addQueryParam('version', octez_connect_core_1.SDK_VERSION), undefined, (res) => {
|
|
257
|
+
if (!res.ok) {
|
|
258
|
+
res.status === 426
|
|
259
|
+
? console.error('Metrics are no longer supported for this version, please upgrade.')
|
|
260
|
+
: console.warn('Network error encountered. Metrics sharing have been automatically disabled.');
|
|
261
|
+
}
|
|
262
|
+
this.enableMetrics = res.ok;
|
|
263
|
+
this.storage.set(octez_connect_types_1.StorageKey.ENABLE_METRICS, res.ok);
|
|
264
|
+
}, () => {
|
|
265
|
+
this.enableMetrics = false;
|
|
266
|
+
this.storage.set(octez_connect_types_1.StorageKey.ENABLE_METRICS, false);
|
|
267
|
+
});
|
|
268
|
+
this.initUserID().catch((err) => logger.error(err.message));
|
|
269
|
+
}
|
|
270
|
+
checkIfBCLeaderExists() {
|
|
271
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
272
|
+
// broadcast channel does not work on mobile
|
|
273
|
+
if ((0, octez_connect_ui_1.isMobileOS)(window)) {
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
const hasLeader = yield this.multiTabChannel.hasLeader();
|
|
277
|
+
if (hasLeader) {
|
|
278
|
+
return this.multiTabChannel.isLeader();
|
|
279
|
+
}
|
|
280
|
+
yield this.multiTabChannel.getLeadership();
|
|
281
|
+
return this.multiTabChannel.isLeader();
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
onElectedLeaderhandler() {
|
|
285
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
286
|
+
if (!this._transport.isResolved()) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const tranport = yield this.transport;
|
|
290
|
+
if (tranport.type !== octez_connect_types_1.TransportType.WALLETCONNECT) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (tranport.connectionStatus === octez_connect_types_1.TransportStatus.CONNECTED) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
yield tranport.connect();
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
onBCMessageHandler(message) {
|
|
300
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
301
|
+
switch (message.type) {
|
|
302
|
+
case octez_connect_types_1.BeaconMessageType.PermissionRequest:
|
|
303
|
+
case octez_connect_types_1.BeaconMessageType.OperationRequest:
|
|
304
|
+
case octez_connect_types_1.BeaconMessageType.SignPayloadRequest:
|
|
305
|
+
case octez_connect_types_1.BeaconMessageType.BroadcastRequest:
|
|
306
|
+
case octez_connect_types_1.BeaconMessageType.ProofOfEventChallengeRequest:
|
|
307
|
+
case octez_connect_types_1.BeaconMessageType.SimulatedProofOfEventChallengeRequest:
|
|
308
|
+
this.prepareRequest(message);
|
|
309
|
+
break;
|
|
310
|
+
case octez_connect_types_1.BeaconMessageType.BlockchainRequest:
|
|
311
|
+
this.prepareRequest(message, true);
|
|
312
|
+
break;
|
|
313
|
+
case 'RESPONSE':
|
|
314
|
+
this.handleResponse(message.data.message, message.data.connectionInfo);
|
|
315
|
+
break;
|
|
316
|
+
case 'DISCONNECT':
|
|
317
|
+
this._transport.isResolved() && this.disconnect();
|
|
318
|
+
break;
|
|
319
|
+
default:
|
|
320
|
+
logger.error('onBCMessageHandler', 'message type not recognized', message);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
prepareRequest(message_1) {
|
|
325
|
+
return __awaiter(this, arguments, void 0, function* (message, isV3 = false) {
|
|
326
|
+
if (!this.multiTabChannel.isLeader()) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
// block until the transport is ready
|
|
330
|
+
const transport = (yield this._transport.promise);
|
|
331
|
+
yield transport.waitForResolution();
|
|
332
|
+
this.openRequestsOtherTabs.add(message.id);
|
|
333
|
+
isV3
|
|
334
|
+
? this.makeRequestV3(message.data, message.id)
|
|
335
|
+
: this.makeRequest(message.data, false, message.id);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
createStateSnapshot() {
|
|
339
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
340
|
+
if (!localStorage || !this.enableMetrics) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const keys = Object.values(octez_connect_types_1.StorageKey).filter((key) => !key.includes('wc@2') && !key.includes('secret') && !key.includes('account'));
|
|
344
|
+
try {
|
|
345
|
+
for (const key of keys) {
|
|
346
|
+
yield this.beaconIDB.set(key, this.storage.getPrefixedKey(key));
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (err) {
|
|
350
|
+
logger.error('createStateSnapshot', err.message);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
initUserID() {
|
|
355
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
356
|
+
const id = yield this.storage.get(octez_connect_types_1.StorageKey.USER_ID);
|
|
357
|
+
if (id) {
|
|
358
|
+
this.userId = id;
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
this.userId = yield (0, octez_connect_utils_1.generateGUID)();
|
|
362
|
+
this.storage.set(octez_connect_types_1.StorageKey.USER_ID, this.userId);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
initInternalTransports() {
|
|
366
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
367
|
+
var _a, _b;
|
|
368
|
+
const seed = yield this.storage.get(octez_connect_types_1.StorageKey.BEACON_SDK_SECRET_SEED);
|
|
369
|
+
if (!seed) {
|
|
370
|
+
throw new Error('Secret seed not found');
|
|
371
|
+
}
|
|
372
|
+
const keyPair = yield (0, octez_connect_utils_1.getKeypairFromSeed)(seed);
|
|
373
|
+
if (this.postMessageTransport || this.p2pTransport || this.walletConnectTransport) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
this.postMessageTransport = new DappPostMessageTransport_1.DappPostMessageTransport(this.name, keyPair, this.storage);
|
|
377
|
+
yield this.addListener(this.postMessageTransport);
|
|
378
|
+
this.p2pTransport = new DappP2PTransport_1.DappP2PTransport(this.name, keyPair, this.storage, this.matrixNodes, this.iconUrl, this.appUrl);
|
|
379
|
+
yield this.addListener(this.p2pTransport);
|
|
380
|
+
const wcOptions = {
|
|
381
|
+
projectId: this.wcProjectId,
|
|
382
|
+
relayUrl: this.wcRelayUrl,
|
|
383
|
+
metadata: {
|
|
384
|
+
name: this.name,
|
|
385
|
+
description: (_a = this.description) !== null && _a !== void 0 ? _a : '',
|
|
386
|
+
url: (_b = this.appUrl) !== null && _b !== void 0 ? _b : '',
|
|
387
|
+
icons: this.iconUrl ? [this.iconUrl] : []
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
this.walletConnectTransport = new DappWalletConnectTransport_1.DappWalletConnectTransport(this.name, keyPair, this.storage, {
|
|
391
|
+
network: this.network.type,
|
|
392
|
+
opts: wcOptions
|
|
393
|
+
}, this.checkIfBCLeaderExists.bind(this));
|
|
394
|
+
this.initEvents();
|
|
395
|
+
yield this.addListener(this.walletConnectTransport);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
initEvents() {
|
|
399
|
+
if (!this.walletConnectTransport) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
this.walletConnectTransport.setEventHandler("CLOSE_ALERT" /* ClientEvents.CLOSE_ALERT */, this.hideUI.bind(this, ['alert', 'toast']));
|
|
403
|
+
this.walletConnectTransport.setEventHandler("RESET_STATE" /* ClientEvents.RESET_STATE */, this.channelClosedHandler.bind(this));
|
|
404
|
+
this.walletConnectTransport.setEventHandler("WC_ACK_NOTIFICATION" /* ClientEvents.WC_ACK_NOTIFICATION */, this.wcToastHandler.bind(this));
|
|
405
|
+
this.walletConnectTransport.setEventHandler("ON_RELAYER_ERROR" /* ClientEvents.ON_RELAYER_ERROR */, this.onRelayerError.bind(this));
|
|
406
|
+
}
|
|
407
|
+
onRelayerError() {
|
|
408
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
+
yield this.resetInvalidState(false);
|
|
410
|
+
this.events.emit(events_1.BeaconEvent.RELAYER_ERROR);
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
wcToastHandler(status) {
|
|
414
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
415
|
+
const walletInfo = yield (() => __awaiter(this, void 0, void 0, function* () {
|
|
416
|
+
try {
|
|
417
|
+
return yield this.getWalletInfo();
|
|
418
|
+
}
|
|
419
|
+
catch (_a) {
|
|
420
|
+
return { name: 'wallet' };
|
|
421
|
+
}
|
|
422
|
+
}))();
|
|
423
|
+
yield this.events.emit(events_1.BeaconEvent.HIDE_UI, ['alert']);
|
|
424
|
+
if (status === 'pending') {
|
|
425
|
+
this.events.emit(events_1.BeaconEvent.ACKNOWLEDGE_RECEIVED, {
|
|
426
|
+
message: {},
|
|
427
|
+
extraInfo: {},
|
|
428
|
+
walletInfo
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
this.events.emit(events_1.BeaconEvent.PERMISSION_REQUEST_ERROR, {
|
|
433
|
+
errorResponse: { errorType: octez_connect_types_1.BeaconErrorType.ABORTED_ERROR },
|
|
434
|
+
walletInfo
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
channelClosedHandler(type) {
|
|
440
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
441
|
+
const transport = yield this.transport;
|
|
442
|
+
if (transport.type !== type) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
yield this.events.emit(events_1.BeaconEvent.CHANNEL_CLOSED);
|
|
446
|
+
this.setActiveAccount(undefined);
|
|
447
|
+
yield this.disconnect();
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Destroy the instance.
|
|
452
|
+
*
|
|
453
|
+
* WARNING: Call `destroy` whenever you no longer need dAppClient
|
|
454
|
+
* as it frees internal subscriptions to the transport and therefore the instance may no longer work properly.
|
|
455
|
+
* If you wish to disconnect your dApp, use `disconnect` instead.
|
|
456
|
+
*/
|
|
457
|
+
destroy() {
|
|
458
|
+
const _super = Object.create(null, {
|
|
459
|
+
destroy: { get: () => super.destroy }
|
|
460
|
+
});
|
|
461
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
462
|
+
yield this.createStateSnapshot();
|
|
463
|
+
yield _super.destroy.call(this);
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
init(transport, substratePairing) {
|
|
467
|
+
const _super = Object.create(null, {
|
|
468
|
+
init: { get: () => super.init }
|
|
469
|
+
});
|
|
470
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
471
|
+
if (this._initPromise) {
|
|
472
|
+
return this._initPromise;
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
yield this.activeAccountLoaded;
|
|
476
|
+
}
|
|
477
|
+
catch (_a) {
|
|
478
|
+
//
|
|
479
|
+
}
|
|
480
|
+
this._initPromise = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
481
|
+
if (transport) {
|
|
482
|
+
yield this.addListener(transport);
|
|
483
|
+
resolve(yield _super.init.call(this, transport));
|
|
484
|
+
}
|
|
485
|
+
else if (this._transport.isSettled()) {
|
|
486
|
+
yield (yield this.transport).connect();
|
|
487
|
+
resolve(yield _super.init.call(this, yield this.transport));
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
const activeAccount = yield this.getActiveAccount();
|
|
491
|
+
const stopListening = () => {
|
|
492
|
+
if (this.postMessageTransport) {
|
|
493
|
+
this.postMessageTransport.stopListeningForNewPeers().catch(console.error);
|
|
494
|
+
}
|
|
495
|
+
if (this.p2pTransport) {
|
|
496
|
+
this.p2pTransport.stopListeningForNewPeers().catch(console.error);
|
|
497
|
+
}
|
|
498
|
+
if (this.walletConnectTransport) {
|
|
499
|
+
this.walletConnectTransport.stopListeningForNewPeers().catch(console.error);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
yield this.initInternalTransports();
|
|
503
|
+
if (!this.postMessageTransport || !this.p2pTransport || !this.walletConnectTransport) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
this.postMessageTransport.connect().then().catch(console.error);
|
|
507
|
+
if (activeAccount && activeAccount.origin) {
|
|
508
|
+
const origin = activeAccount.origin.type;
|
|
509
|
+
// Select the transport that matches the active account
|
|
510
|
+
if (origin === octez_connect_types_1.Origin.EXTENSION) {
|
|
511
|
+
resolve(yield _super.init.call(this, this.postMessageTransport));
|
|
512
|
+
}
|
|
513
|
+
else if (origin === octez_connect_types_1.Origin.P2P) {
|
|
514
|
+
resolve(yield _super.init.call(this, this.p2pTransport));
|
|
515
|
+
}
|
|
516
|
+
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT) {
|
|
517
|
+
resolve(yield _super.init.call(this, this.walletConnectTransport));
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
const p2pTransport = this.p2pTransport;
|
|
522
|
+
const postMessageTransport = this.postMessageTransport;
|
|
523
|
+
const walletConnectTransport = this.walletConnectTransport;
|
|
524
|
+
postMessageTransport
|
|
525
|
+
.listenForNewPeer((peer) => {
|
|
526
|
+
logger.log('init', 'postmessage transport peer connected', peer);
|
|
527
|
+
this.analytics.track('event', 'DAppClient', 'Extension connected', {
|
|
528
|
+
peerName: peer.name
|
|
529
|
+
});
|
|
530
|
+
this.events
|
|
531
|
+
.emit(events_1.BeaconEvent.PAIR_SUCCESS, peer)
|
|
532
|
+
.catch((emitError) => console.warn(emitError));
|
|
533
|
+
this.setActivePeer(peer).catch(console.error);
|
|
534
|
+
this.setTransport(this.postMessageTransport).catch(console.error);
|
|
535
|
+
stopListening();
|
|
536
|
+
resolve(octez_connect_types_1.TransportType.POST_MESSAGE);
|
|
537
|
+
})
|
|
538
|
+
.catch(console.error);
|
|
539
|
+
p2pTransport
|
|
540
|
+
.listenForNewPeer((peer) => {
|
|
541
|
+
logger.log('init', 'p2p transport peer connected', peer);
|
|
542
|
+
this.analytics.track('event', 'DAppClient', 'octez.connect Wallet connected', {
|
|
543
|
+
peerName: peer.name
|
|
544
|
+
});
|
|
545
|
+
this.events
|
|
546
|
+
.emit(events_1.BeaconEvent.PAIR_SUCCESS, peer)
|
|
547
|
+
.catch((emitError) => console.warn(emitError));
|
|
548
|
+
this.setActivePeer(peer).catch(console.error);
|
|
549
|
+
this.setTransport(this.p2pTransport).catch(console.error);
|
|
550
|
+
stopListening();
|
|
551
|
+
resolve(octez_connect_types_1.TransportType.P2P);
|
|
552
|
+
})
|
|
553
|
+
.catch(console.error);
|
|
554
|
+
walletConnectTransport
|
|
555
|
+
.listenForNewPeer((peer) => {
|
|
556
|
+
logger.log('init', 'walletconnect transport peer connected', peer);
|
|
557
|
+
this.analytics.track('event', 'DAppClient', 'WalletConnect Wallet connected', {
|
|
558
|
+
peerName: peer.name
|
|
559
|
+
});
|
|
560
|
+
this.events
|
|
561
|
+
.emit(events_1.BeaconEvent.PAIR_SUCCESS, peer)
|
|
562
|
+
.catch((emitError) => console.warn(emitError));
|
|
563
|
+
this.setActivePeer(peer).catch(console.error);
|
|
564
|
+
this.setTransport(this.walletConnectTransport).catch(console.error);
|
|
565
|
+
stopListening();
|
|
566
|
+
resolve(octez_connect_types_1.TransportType.WALLETCONNECT);
|
|
567
|
+
})
|
|
568
|
+
.catch(console.error);
|
|
569
|
+
octez_connect_transport_postmessage_1.PostMessageTransport.getAvailableExtensions()
|
|
570
|
+
.then((extensions) => __awaiter(this, void 0, void 0, function* () {
|
|
571
|
+
this.analytics.track('event', 'DAppClient', 'Extensions detected', { extensions });
|
|
572
|
+
}))
|
|
573
|
+
.catch((error) => {
|
|
574
|
+
this._initPromise = undefined;
|
|
575
|
+
console.error(error);
|
|
576
|
+
});
|
|
577
|
+
const abortHandler = () => __awaiter(this, void 0, void 0, function* () {
|
|
578
|
+
logger.log('init', 'ABORTED');
|
|
579
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'abort'));
|
|
580
|
+
yield Promise.all([
|
|
581
|
+
postMessageTransport.disconnect(),
|
|
582
|
+
// p2pTransport.disconnect(), do not abort connection manually
|
|
583
|
+
walletConnectTransport.disconnect()
|
|
584
|
+
]);
|
|
585
|
+
this.postMessageTransport = this.walletConnectTransport = this.p2pTransport = undefined;
|
|
586
|
+
this._activeAccount.isResolved() && this.clearActiveAccount();
|
|
587
|
+
this._initPromise = undefined;
|
|
588
|
+
});
|
|
589
|
+
const serializer = new octez_connect_core_1.Serializer();
|
|
590
|
+
const p2pPeerInfo = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
591
|
+
try {
|
|
592
|
+
yield p2pTransport.connect();
|
|
593
|
+
}
|
|
594
|
+
catch (err) {
|
|
595
|
+
logger.error(err);
|
|
596
|
+
yield this.hideUI(['alert']); // hide pairing alert
|
|
597
|
+
setTimeout(() => this.events.emit(events_1.BeaconEvent.GENERIC_ERROR, err.message), 1000);
|
|
598
|
+
abortHandler();
|
|
599
|
+
resolve('');
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
resolve(yield serializer.serialize(yield p2pTransport.getPairingRequestInfo()));
|
|
603
|
+
}));
|
|
604
|
+
const walletConnectPeerInfo = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
605
|
+
resolve((yield walletConnectTransport.getPairingRequestInfo()).uri);
|
|
606
|
+
}));
|
|
607
|
+
const postmessagePeerInfo = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
608
|
+
resolve(yield serializer.serialize(yield postMessageTransport.getPairingRequestInfo()));
|
|
609
|
+
}));
|
|
610
|
+
this.events
|
|
611
|
+
.emit(events_1.BeaconEvent.PAIR_INIT, {
|
|
612
|
+
p2pPeerInfo,
|
|
613
|
+
postmessagePeerInfo,
|
|
614
|
+
walletConnectPeerInfo,
|
|
615
|
+
networkType: this.network.type,
|
|
616
|
+
abortedHandler: abortHandler.bind(this),
|
|
617
|
+
disclaimerText: this.disclaimerText,
|
|
618
|
+
analytics: this.analytics,
|
|
619
|
+
featuredWallets: this.featuredWallets,
|
|
620
|
+
substratePairing
|
|
621
|
+
})
|
|
622
|
+
.catch((emitError) => console.warn(emitError));
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}));
|
|
626
|
+
return this._initPromise;
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Returns the active account
|
|
631
|
+
*/
|
|
632
|
+
getActiveAccount() {
|
|
633
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
634
|
+
return this._activeAccount.promise;
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
isInvalidState(account) {
|
|
638
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
639
|
+
const activeAccount = yield this._activeAccount.promise;
|
|
640
|
+
return !activeAccount
|
|
641
|
+
? false
|
|
642
|
+
: (activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.address) !== (account === null || account === void 0 ? void 0 : account.address) && !this.isGetActiveAccountHandled;
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
resetInvalidState() {
|
|
646
|
+
return __awaiter(this, arguments, void 0, function* (emit = true) {
|
|
647
|
+
var _a, _b;
|
|
648
|
+
this.accountManager.removeAllAccounts();
|
|
649
|
+
this._activeAccount = octez_connect_utils_1.ExposedPromise.resolve(undefined);
|
|
650
|
+
this.storage.set(octez_connect_types_1.StorageKey.ACTIVE_ACCOUNT, undefined);
|
|
651
|
+
emit && this.events.emit(events_1.BeaconEvent.INVALID_ACTIVE_ACCOUNT_STATE);
|
|
652
|
+
!emit && this.hideUI(['alert']);
|
|
653
|
+
yield Promise.all([
|
|
654
|
+
(_a = this.postMessageTransport) === null || _a === void 0 ? void 0 : _a.disconnect(),
|
|
655
|
+
(_b = this.walletConnectTransport) === null || _b === void 0 ? void 0 : _b.disconnect()
|
|
656
|
+
]);
|
|
657
|
+
this.postMessageTransport = this.p2pTransport = this.walletConnectTransport = undefined;
|
|
658
|
+
yield this.setActivePeer(undefined);
|
|
659
|
+
yield this.setTransport(undefined);
|
|
660
|
+
this._initPromise = undefined;
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Sets the active account
|
|
665
|
+
*
|
|
666
|
+
* @param account The account that will be set as the active account
|
|
667
|
+
*/
|
|
668
|
+
setActiveAccount(account) {
|
|
669
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
670
|
+
var _a;
|
|
671
|
+
if (!this.isGetActiveAccountHandled) {
|
|
672
|
+
console.warn(`An active account has been received, but no active subscription was found for BeaconEvent.ACTIVE_ACCOUNT_SET.`);
|
|
673
|
+
}
|
|
674
|
+
if (account && this._activeAccount.isSettled() && (yield this.isInvalidState(account))) {
|
|
675
|
+
const tranport = yield this.transport;
|
|
676
|
+
if (tranport instanceof octez_connect_transport_walletconnect_1.WalletConnectTransport && tranport.wasDisconnectedByWallet()) {
|
|
677
|
+
yield this.resetInvalidState();
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
// when I'm resetting the activeAccount
|
|
682
|
+
if (!account && this._activeAccount.isResolved() && (yield this.getActiveAccount())) {
|
|
683
|
+
const transport = yield this.transport;
|
|
684
|
+
const activeAccount = yield this.getActiveAccount();
|
|
685
|
+
if (!transport || !activeAccount) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (!this.debounceSetActiveAccount && transport instanceof octez_connect_transport_walletconnect_1.WalletConnectTransport) {
|
|
689
|
+
this.debounceSetActiveAccount = true;
|
|
690
|
+
this._initPromise = undefined;
|
|
691
|
+
this.postMessageTransport = this.p2pTransport = this.walletConnectTransport = undefined;
|
|
692
|
+
if (this.multiTabChannel.isLeader() || (0, octez_connect_ui_1.isMobileOS)(window)) {
|
|
693
|
+
yield transport.disconnect();
|
|
694
|
+
this.openRequestsOtherTabs.clear();
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
this.multiTabChannel.postMessage({
|
|
698
|
+
type: 'DISCONNECT'
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
Array.from(this.openRequests.entries())
|
|
702
|
+
.filter(([id, _promise]) => id !== 'session_update')
|
|
703
|
+
.forEach(([id, promise]) => {
|
|
704
|
+
promise.reject({
|
|
705
|
+
type: octez_connect_types_1.BeaconMessageType.Error,
|
|
706
|
+
errorType: octez_connect_types_1.BeaconErrorType.ABORTED_ERROR,
|
|
707
|
+
id,
|
|
708
|
+
senderId: '',
|
|
709
|
+
version: '2'
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
this.openRequests.clear();
|
|
713
|
+
this.debounceSetActiveAccount = false;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (this._activeAccount.isSettled()) {
|
|
717
|
+
// If the promise has already been resolved we need to create a new one.
|
|
718
|
+
this._activeAccount = octez_connect_utils_1.ExposedPromise.resolve(account);
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
this._activeAccount.resolve(account);
|
|
722
|
+
}
|
|
723
|
+
if (!this.isGetActiveAccountHandled && this._transport.isResolved()) {
|
|
724
|
+
const transport = yield this.transport;
|
|
725
|
+
if (transport instanceof octez_connect_transport_walletconnect_1.WalletConnectTransport && transport.wasDisconnectedByWallet()) {
|
|
726
|
+
yield this.resetInvalidState();
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (account) {
|
|
731
|
+
const origin = account.origin.type;
|
|
732
|
+
yield this.initInternalTransports();
|
|
733
|
+
// Select the transport that matches the active account
|
|
734
|
+
if (origin === octez_connect_types_1.Origin.EXTENSION) {
|
|
735
|
+
yield this.setTransport(this.postMessageTransport);
|
|
736
|
+
}
|
|
737
|
+
else if (origin === octez_connect_types_1.Origin.P2P) {
|
|
738
|
+
yield this.setTransport(this.p2pTransport);
|
|
739
|
+
}
|
|
740
|
+
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT) {
|
|
741
|
+
yield this.setTransport(this.walletConnectTransport);
|
|
742
|
+
(_a = this.walletConnectTransport) === null || _a === void 0 ? void 0 : _a.forceUpdate('INIT');
|
|
743
|
+
}
|
|
744
|
+
if (this._transport.isResolved()) {
|
|
745
|
+
const transport = yield this.transport;
|
|
746
|
+
if (transport.connectionStatus === octez_connect_types_1.TransportStatus.NOT_CONNECTED) {
|
|
747
|
+
yield transport.connect();
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
const peer = yield this.getPeer(account);
|
|
751
|
+
yield this.setActivePeer(peer);
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
yield this.setActivePeer(undefined);
|
|
755
|
+
yield this.setTransport(undefined);
|
|
756
|
+
}
|
|
757
|
+
yield this.storage.set(octez_connect_types_1.StorageKey.ACTIVE_ACCOUNT, account ? account.accountIdentifier : undefined);
|
|
758
|
+
yield this.events.emit(events_1.BeaconEvent.ACTIVE_ACCOUNT_SET, account);
|
|
759
|
+
return;
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Clear the active account
|
|
764
|
+
*/
|
|
765
|
+
clearActiveAccount() {
|
|
766
|
+
return this.setActiveAccount();
|
|
767
|
+
}
|
|
768
|
+
setColorMode(colorMode) {
|
|
769
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
770
|
+
return (0, octez_connect_ui_1.setColorMode)(colorMode);
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
getColorMode() {
|
|
774
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
775
|
+
return (0, octez_connect_ui_1.getColorMode)();
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* @deprecated
|
|
780
|
+
*
|
|
781
|
+
* Use getOwnAppMetadata instead
|
|
782
|
+
*/
|
|
783
|
+
getAppMetadata() {
|
|
784
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
785
|
+
return this.getOwnAppMetadata();
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
showPrepare() {
|
|
789
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
790
|
+
const walletInfo = yield (() => __awaiter(this, void 0, void 0, function* () {
|
|
791
|
+
try {
|
|
792
|
+
return yield this.getWalletInfo();
|
|
793
|
+
}
|
|
794
|
+
catch (_a) {
|
|
795
|
+
return undefined;
|
|
796
|
+
}
|
|
797
|
+
}))();
|
|
798
|
+
yield this.events.emit(events_1.BeaconEvent.SHOW_PREPARE, { walletInfo });
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
hideUI(elements) {
|
|
802
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
803
|
+
yield this.events.emit(events_1.BeaconEvent.HIDE_UI, elements);
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
tryToAppSwitch() {
|
|
807
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
808
|
+
if (!(0, octez_connect_ui_1.isMobileOS)(window) || !this.enableAppSwitching) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const wallet = yield this.getWalletInfo();
|
|
812
|
+
if (wallet.type !== 'mobile' || !wallet.deeplink) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const link = (0, octez_connect_ui_1.isIOS)(window) ? wallet.deeplink : `${wallet.deeplink}wc?uri=`;
|
|
816
|
+
if (!(link === null || link === void 0 ? void 0 : link.length)) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
window.location = link;
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
addQueryParam(paramName, paramValue) {
|
|
823
|
+
return paramName + '=' + paramValue;
|
|
824
|
+
}
|
|
825
|
+
buildPayload(action, status) {
|
|
826
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
827
|
+
var _a, _b, _c, _d;
|
|
828
|
+
const wallet = yield this.storage.get(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET);
|
|
829
|
+
const transport = this._activeAccount.isResolved()
|
|
830
|
+
? ((_b = (_a = (yield this.getActiveAccount())) === null || _a === void 0 ? void 0 : _a.origin.type) !== null && _b !== void 0 ? _b : 'UNKNOWN')
|
|
831
|
+
: 'UNKNOWN';
|
|
832
|
+
return {
|
|
833
|
+
method: 'POST',
|
|
834
|
+
headers: {
|
|
835
|
+
'Content-Type': 'application/json'
|
|
836
|
+
},
|
|
837
|
+
body: JSON.stringify({
|
|
838
|
+
userId: this.userId,
|
|
839
|
+
os: (0, octez_connect_ui_1.currentOS)(),
|
|
840
|
+
walletName: (_c = wallet === null || wallet === void 0 ? void 0 : wallet.name) !== null && _c !== void 0 ? _c : 'init',
|
|
841
|
+
walletType: (_d = wallet === null || wallet === void 0 ? void 0 : wallet.type) !== null && _d !== void 0 ? _d : 'init',
|
|
842
|
+
sdkVersion: octez_connect_core_1.SDK_VERSION,
|
|
843
|
+
transport,
|
|
844
|
+
time: new Date(),
|
|
845
|
+
action,
|
|
846
|
+
status
|
|
847
|
+
})
|
|
848
|
+
};
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
updateMetricsStorage(payload) {
|
|
852
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
853
|
+
const queue = yield this.beaconIDB.getAllKeys('metrics');
|
|
854
|
+
if (queue.length >= 1000) {
|
|
855
|
+
const key = queue.shift();
|
|
856
|
+
this.beaconIDB.delete(key.toString(), 'metrics');
|
|
857
|
+
}
|
|
858
|
+
this.beaconIDB.set(String(Date.now()), payload, 'metrics');
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
sendMetrics(uri, options, thenHandler, catchHandler) {
|
|
862
|
+
if (!this.enableMetrics && uri === 'performance-metrics/save') {
|
|
863
|
+
options && this.updateMetricsStorage(options.body);
|
|
864
|
+
}
|
|
865
|
+
if (!this.enableMetrics) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
fetch(`${octez_connect_core_1.BACKEND_URL}/${uri}`, options)
|
|
869
|
+
.then((res) => thenHandler && thenHandler(res))
|
|
870
|
+
.catch((err) => {
|
|
871
|
+
console.warn('Network error encountered. Metrics sharing have been automatically disabled.');
|
|
872
|
+
logger.error(err.message);
|
|
873
|
+
this.enableMetrics = false; // in the event of a network error, stop sending metrics
|
|
874
|
+
catchHandler && catchHandler(err);
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
checkMakeRequest() {
|
|
878
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
879
|
+
const isResolved = this._transport.isResolved();
|
|
880
|
+
const isWCInstance = isResolved && (yield this.transport) instanceof octez_connect_transport_walletconnect_1.WalletConnectTransport;
|
|
881
|
+
yield this.multiTabChannel.init();
|
|
882
|
+
const isLeader = this.multiTabChannel.isLeader();
|
|
883
|
+
return !isResolved || !isWCInstance || isLeader || (0, octez_connect_ui_1.isMobileOS)(window);
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Will remove the account from the local storage and set a new active account if necessary.
|
|
888
|
+
*
|
|
889
|
+
* @param accountIdentifier ID of the account
|
|
890
|
+
*/
|
|
891
|
+
removeAccount(accountIdentifier) {
|
|
892
|
+
const _super = Object.create(null, {
|
|
893
|
+
removeAccount: { get: () => super.removeAccount }
|
|
894
|
+
});
|
|
895
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
896
|
+
const removeAccountResult = _super.removeAccount.call(this, accountIdentifier);
|
|
897
|
+
const activeAccount = yield this.getActiveAccount();
|
|
898
|
+
if (activeAccount && activeAccount.accountIdentifier === accountIdentifier) {
|
|
899
|
+
yield this.setActiveAccount(undefined);
|
|
900
|
+
}
|
|
901
|
+
return removeAccountResult;
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Remove all accounts and set active account to undefined
|
|
906
|
+
*/
|
|
907
|
+
removeAllAccounts() {
|
|
908
|
+
const _super = Object.create(null, {
|
|
909
|
+
removeAllAccounts: { get: () => super.removeAllAccounts }
|
|
910
|
+
});
|
|
911
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
912
|
+
yield _super.removeAllAccounts.call(this);
|
|
913
|
+
yield this.setActiveAccount(undefined);
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Removes a peer and all the accounts that have been connected through that peer
|
|
918
|
+
*
|
|
919
|
+
* @param peer Peer to be removed
|
|
920
|
+
*/
|
|
921
|
+
removePeer(peer_1) {
|
|
922
|
+
return __awaiter(this, arguments, void 0, function* (peer, sendDisconnectToPeer = false) {
|
|
923
|
+
const transport = yield this.transport;
|
|
924
|
+
const removePeerResult = transport.removePeer(peer);
|
|
925
|
+
yield this.removeAccountsForPeers([peer]);
|
|
926
|
+
if (sendDisconnectToPeer) {
|
|
927
|
+
yield this.sendDisconnectToPeer(peer, transport);
|
|
928
|
+
}
|
|
929
|
+
return removePeerResult;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Remove all peers and all accounts that have been connected through those peers
|
|
934
|
+
*/
|
|
935
|
+
removeAllPeers() {
|
|
936
|
+
return __awaiter(this, arguments, void 0, function* (sendDisconnectToPeers = false) {
|
|
937
|
+
const transport = yield this.transport;
|
|
938
|
+
const peers = yield transport.getPeers();
|
|
939
|
+
const removePeerResult = transport.removeAllPeers();
|
|
940
|
+
yield this.removeAccountsForPeers(peers);
|
|
941
|
+
if (sendDisconnectToPeers) {
|
|
942
|
+
const disconnectPromises = peers.map((peer) => this.sendDisconnectToPeer(peer, transport));
|
|
943
|
+
yield Promise.all(disconnectPromises);
|
|
944
|
+
}
|
|
945
|
+
return removePeerResult;
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Allows the user to subscribe to specific events that are fired in the SDK
|
|
950
|
+
*
|
|
951
|
+
* @param internalEvent The event to subscribe to
|
|
952
|
+
* @param eventCallback The callback that will be called when the event occurs
|
|
953
|
+
*/
|
|
954
|
+
subscribeToEvent(internalEvent, eventCallback) {
|
|
955
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
956
|
+
if (internalEvent === events_1.BeaconEvent.ACTIVE_ACCOUNT_SET) {
|
|
957
|
+
this.isGetActiveAccountHandled = true;
|
|
958
|
+
}
|
|
959
|
+
yield this.events.on(internalEvent, eventCallback);
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Check if we have permissions to send the specific message type to the active account.
|
|
964
|
+
* If no active account is set, only permission requests are allowed.
|
|
965
|
+
*
|
|
966
|
+
* @param type The type of the message
|
|
967
|
+
*/
|
|
968
|
+
checkPermissions(type) {
|
|
969
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
970
|
+
if ([
|
|
971
|
+
octez_connect_types_1.BeaconMessageType.PermissionRequest,
|
|
972
|
+
octez_connect_types_1.BeaconMessageType.ProofOfEventChallengeRequest,
|
|
973
|
+
octez_connect_types_1.BeaconMessageType.SimulatedProofOfEventChallengeRequest
|
|
974
|
+
].includes(type)) {
|
|
975
|
+
return true;
|
|
976
|
+
}
|
|
977
|
+
const activeAccount = yield this.getActiveAccount();
|
|
978
|
+
if (!activeAccount) {
|
|
979
|
+
throw yield this.sendInternalError('No active account set!');
|
|
980
|
+
}
|
|
981
|
+
const permissions = activeAccount.scopes;
|
|
982
|
+
switch (type) {
|
|
983
|
+
case octez_connect_types_1.BeaconMessageType.OperationRequest:
|
|
984
|
+
return permissions.includes(octez_connect_types_1.PermissionScope.OPERATION_REQUEST);
|
|
985
|
+
case octez_connect_types_1.BeaconMessageType.SignPayloadRequest:
|
|
986
|
+
return permissions.includes(octez_connect_types_1.PermissionScope.SIGN);
|
|
987
|
+
// TODO: ENCRYPTION
|
|
988
|
+
// case BeaconMessageType.EncryptPayloadRequest:
|
|
989
|
+
// return permissions.includes(PermissionScope.ENCRYPT)
|
|
990
|
+
case octez_connect_types_1.BeaconMessageType.BroadcastRequest:
|
|
991
|
+
return true;
|
|
992
|
+
default:
|
|
993
|
+
return false;
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
sendNotification(title, message, payload, protocolIdentifier) {
|
|
998
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
999
|
+
var _a, _b, _c;
|
|
1000
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1001
|
+
if (!activeAccount ||
|
|
1002
|
+
(activeAccount &&
|
|
1003
|
+
!activeAccount.scopes.includes(octez_connect_types_1.PermissionScope.NOTIFICATION) &&
|
|
1004
|
+
!activeAccount.notification)) {
|
|
1005
|
+
throw new Error('notification permissions not given');
|
|
1006
|
+
}
|
|
1007
|
+
if (!((_a = activeAccount.notification) === null || _a === void 0 ? void 0 : _a.token)) {
|
|
1008
|
+
throw new Error('No AccessToken');
|
|
1009
|
+
}
|
|
1010
|
+
const url = (_b = activeAccount.notification) === null || _b === void 0 ? void 0 : _b.apiUrl;
|
|
1011
|
+
if (!url) {
|
|
1012
|
+
throw new Error('No Push URL set');
|
|
1013
|
+
}
|
|
1014
|
+
return this.sendNotificationWithAccessToken({
|
|
1015
|
+
url,
|
|
1016
|
+
recipient: activeAccount.address,
|
|
1017
|
+
title,
|
|
1018
|
+
body: message,
|
|
1019
|
+
payload,
|
|
1020
|
+
protocolIdentifier,
|
|
1021
|
+
accessToken: (_c = activeAccount.notification) === null || _c === void 0 ? void 0 : _c.token
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
addBlockchain(chain) {
|
|
1026
|
+
this.blockchains.set(chain.identifier, chain);
|
|
1027
|
+
chain.getWalletLists().then((walletLists) => {
|
|
1028
|
+
(0, octez_connect_ui_1.setDesktopList)(walletLists.desktopList);
|
|
1029
|
+
(0, octez_connect_ui_1.setExtensionList)(walletLists.extensionList);
|
|
1030
|
+
(0, octez_connect_ui_1.setWebList)(walletLists.webList);
|
|
1031
|
+
(0, octez_connect_ui_1.setiOSList)(walletLists.iOSList);
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
removeBlockchain(chainIdentifier) {
|
|
1035
|
+
this.blockchains.delete(chainIdentifier);
|
|
1036
|
+
}
|
|
1037
|
+
permissionRequest(input) {
|
|
1038
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1039
|
+
logger.log('permissionRequest', input);
|
|
1040
|
+
const blockchain = this.blockchains.get(input.blockchainIdentifier);
|
|
1041
|
+
if (!blockchain) {
|
|
1042
|
+
throw new Error(`Blockchain "${input.blockchainIdentifier}" not supported by dAppClient`);
|
|
1043
|
+
}
|
|
1044
|
+
const request = Object.assign(Object.assign({}, input), { type: octez_connect_types_1.BeaconMessageType.PermissionRequest, blockchainData: Object.assign(Object.assign({}, input.blockchainData), { appMetadata: yield this.getOwnAppMetadata() }) });
|
|
1045
|
+
logger.log('REQUESTION PERMIMISSION V3', 'xxx', request);
|
|
1046
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'start'));
|
|
1047
|
+
const logId = `makeRequestV3 ${Date.now()}`;
|
|
1048
|
+
logger.time(true, logId);
|
|
1049
|
+
const { message: response, connectionInfo } = yield this.makeRequestV3(request).catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1050
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1051
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1052
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1053
|
+
logger.time(false, logId);
|
|
1054
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1055
|
+
}));
|
|
1056
|
+
logger.time(false, logId);
|
|
1057
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'start'));
|
|
1058
|
+
logger.log('RESPONSE V3', response, connectionInfo);
|
|
1059
|
+
const partialAccountInfos = yield blockchain.getAccountInfosFromPermissionResponse(response.message);
|
|
1060
|
+
const accountInfo = {
|
|
1061
|
+
accountIdentifier: partialAccountInfos[0].accountId,
|
|
1062
|
+
senderId: response.senderId,
|
|
1063
|
+
origin: {
|
|
1064
|
+
type: connectionInfo.origin,
|
|
1065
|
+
id: connectionInfo.id
|
|
1066
|
+
},
|
|
1067
|
+
address: partialAccountInfos[0].address, // Store all addresses
|
|
1068
|
+
publicKey: partialAccountInfos[0].publicKey,
|
|
1069
|
+
scopes: response.message.blockchainData.scopes,
|
|
1070
|
+
connectedAt: new Date().getTime(),
|
|
1071
|
+
chainData: response.message.blockchainData
|
|
1072
|
+
};
|
|
1073
|
+
yield this.accountManager.addAccount(accountInfo);
|
|
1074
|
+
yield this.setActiveAccount(accountInfo);
|
|
1075
|
+
yield blockchain.handleResponse({
|
|
1076
|
+
request,
|
|
1077
|
+
account: accountInfo,
|
|
1078
|
+
output: response,
|
|
1079
|
+
blockExplorer: this.blockExplorer,
|
|
1080
|
+
connectionContext: connectionInfo,
|
|
1081
|
+
walletInfo: yield this.getWalletInfo()
|
|
1082
|
+
});
|
|
1083
|
+
yield this.notifySuccess(request, {
|
|
1084
|
+
account: accountInfo,
|
|
1085
|
+
output: {
|
|
1086
|
+
address: partialAccountInfos[0].address,
|
|
1087
|
+
network: { type: 'substrate' },
|
|
1088
|
+
scopes: []
|
|
1089
|
+
},
|
|
1090
|
+
blockExplorer: this.blockExplorer,
|
|
1091
|
+
connectionContext: connectionInfo,
|
|
1092
|
+
walletInfo: yield this.getWalletInfo()
|
|
1093
|
+
});
|
|
1094
|
+
// return output
|
|
1095
|
+
return response.message;
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
request(input) {
|
|
1099
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1100
|
+
logger.log('request', input);
|
|
1101
|
+
const blockchain = this.blockchains.get(input.blockchainIdentifier);
|
|
1102
|
+
if (!blockchain) {
|
|
1103
|
+
throw new Error(`Blockchain "${blockchain}" not supported by dAppClient`);
|
|
1104
|
+
}
|
|
1105
|
+
yield blockchain.validateRequest(input);
|
|
1106
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1107
|
+
if (!activeAccount) {
|
|
1108
|
+
throw yield this.sendInternalError('No active account!');
|
|
1109
|
+
}
|
|
1110
|
+
const request = Object.assign(Object.assign({}, input), { type: octez_connect_types_1.BeaconMessageType.BlockchainRequest, accountId: activeAccount.accountIdentifier });
|
|
1111
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'start'));
|
|
1112
|
+
const logId = `makeRequestV3 ${Date.now()}`;
|
|
1113
|
+
logger.time(true, logId);
|
|
1114
|
+
const res = (yield this.checkMakeRequest())
|
|
1115
|
+
? this.makeRequestV3(request)
|
|
1116
|
+
: this.makeRequestBC(request);
|
|
1117
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1118
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1119
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1120
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1121
|
+
logger.time(false, logId);
|
|
1122
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1123
|
+
}));
|
|
1124
|
+
const { message: response, connectionInfo } = (yield res);
|
|
1125
|
+
logger.time(false, logId);
|
|
1126
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'success'));
|
|
1127
|
+
yield blockchain.handleResponse({
|
|
1128
|
+
request,
|
|
1129
|
+
account: activeAccount,
|
|
1130
|
+
output: response,
|
|
1131
|
+
blockExplorer: this.blockExplorer,
|
|
1132
|
+
connectionContext: connectionInfo,
|
|
1133
|
+
walletInfo: yield this.getWalletInfo()
|
|
1134
|
+
});
|
|
1135
|
+
yield this.notifySuccess(request, {
|
|
1136
|
+
walletInfo: yield this.getWalletInfo()
|
|
1137
|
+
});
|
|
1138
|
+
return response.message;
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Send a permission request to the DApp. This should be done as the first step. The wallet will respond
|
|
1143
|
+
* with an publicKey and permissions that were given. The account returned will be set as the "activeAccount"
|
|
1144
|
+
* and will be used for the following requests.
|
|
1145
|
+
*
|
|
1146
|
+
* @param input The message details we need to prepare the PermissionRequest message.
|
|
1147
|
+
*/
|
|
1148
|
+
requestPermissions(input) {
|
|
1149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1150
|
+
if (input === null || input === void 0 ? void 0 : input.network) {
|
|
1151
|
+
throw new Error('[BEACON] the "network" property is no longer accepted in input. Please provide it when instantiating DAppClient.');
|
|
1152
|
+
}
|
|
1153
|
+
const request = {
|
|
1154
|
+
appMetadata: yield this.getOwnAppMetadata(),
|
|
1155
|
+
type: octez_connect_types_1.BeaconMessageType.PermissionRequest,
|
|
1156
|
+
network: this.network,
|
|
1157
|
+
scopes: input && input.scopes
|
|
1158
|
+
? input.scopes
|
|
1159
|
+
: [octez_connect_types_1.PermissionScope.OPERATION_REQUEST, octez_connect_types_1.PermissionScope.SIGN]
|
|
1160
|
+
};
|
|
1161
|
+
this.analytics.track('event', 'DAppClient', 'Permission requested');
|
|
1162
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'start'));
|
|
1163
|
+
const logId = `makeRequest ${Date.now()}`;
|
|
1164
|
+
logger.time(true, logId);
|
|
1165
|
+
const res = (yield this.checkMakeRequest()) || !(yield this.getActiveAccount())
|
|
1166
|
+
? this.makeRequest(request, undefined, undefined)
|
|
1167
|
+
: this.makeRequestBC(request);
|
|
1168
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1169
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1170
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1171
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1172
|
+
logger.time(false, logId);
|
|
1173
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1174
|
+
}));
|
|
1175
|
+
const { message, connectionInfo } = (yield res);
|
|
1176
|
+
logger.time(false, logId);
|
|
1177
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'success'));
|
|
1178
|
+
logger.log('requestPermissions', '######## MESSAGE #######');
|
|
1179
|
+
logger.log('requestPermissions', message);
|
|
1180
|
+
const accountInfo = yield this.onNewAccount(message, connectionInfo);
|
|
1181
|
+
logger.log('requestPermissions', '######## ACCOUNT INFO #######');
|
|
1182
|
+
logger.log('requestPermissions', JSON.stringify(accountInfo));
|
|
1183
|
+
yield this.accountManager.addAccount(accountInfo);
|
|
1184
|
+
const output = Object.assign(Object.assign({}, message), { walletKey: accountInfo.walletKey, address: accountInfo.address, accountInfo });
|
|
1185
|
+
yield this.notifySuccess(request, {
|
|
1186
|
+
account: accountInfo,
|
|
1187
|
+
output,
|
|
1188
|
+
blockExplorer: this.blockExplorer,
|
|
1189
|
+
connectionContext: connectionInfo,
|
|
1190
|
+
walletInfo: yield this.getWalletInfo()
|
|
1191
|
+
});
|
|
1192
|
+
this.analytics.track('event', 'DAppClient', 'Permission received', {
|
|
1193
|
+
address: accountInfo.address
|
|
1194
|
+
});
|
|
1195
|
+
return output;
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Send a proof of event request to the wallet. The wallet will either accept or decline the challenge.
|
|
1200
|
+
* If it is accepted, the challenge will be stored, meaning that even if the user refresh the page, the DAppClient will keep checking if the challenge has been fulfilled.
|
|
1201
|
+
* Once the challenge is stored, a challenge stored message will be sent to the wallet.
|
|
1202
|
+
* It's **highly recommended** to run a proof of event challenge to check the identity of an abstracted account
|
|
1203
|
+
*
|
|
1204
|
+
* @param input The message details we need to prepare the ProofOfEventChallenge message.
|
|
1205
|
+
*/
|
|
1206
|
+
requestProofOfEventChallenge(input) {
|
|
1207
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1208
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1209
|
+
if (!activeAccount)
|
|
1210
|
+
throw new Error('Please request permissions before doing a proof of event challenge');
|
|
1211
|
+
if (activeAccount.walletType !== 'abstracted_account' &&
|
|
1212
|
+
activeAccount.verificationType !== 'proof_of_event')
|
|
1213
|
+
throw new Error('This wallet is not an abstracted account and thus cannot perform proof of event');
|
|
1214
|
+
const request = {
|
|
1215
|
+
type: octez_connect_types_1.BeaconMessageType.ProofOfEventChallengeRequest,
|
|
1216
|
+
contractAddress: activeAccount.address,
|
|
1217
|
+
payload: input.payload
|
|
1218
|
+
};
|
|
1219
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'start'));
|
|
1220
|
+
const logId = `makeRequest ${Date.now()}`;
|
|
1221
|
+
logger.time(true, logId);
|
|
1222
|
+
const res = (yield this.checkMakeRequest())
|
|
1223
|
+
? this.makeRequest(request)
|
|
1224
|
+
: this.makeRequestBC(request);
|
|
1225
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1226
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1227
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1228
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1229
|
+
logger.time(false, logId);
|
|
1230
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1231
|
+
}));
|
|
1232
|
+
const { message, connectionInfo } = (yield res);
|
|
1233
|
+
logger.time(false, logId);
|
|
1234
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'success'));
|
|
1235
|
+
this.analytics.track('event', 'DAppClient', `Proof of event challenge ${message.isAccepted ? 'accepted' : 'refused'}`, { address: activeAccount.address });
|
|
1236
|
+
yield this.notifySuccess(request, {
|
|
1237
|
+
account: activeAccount,
|
|
1238
|
+
output: message,
|
|
1239
|
+
blockExplorer: this.blockExplorer,
|
|
1240
|
+
connectionContext: connectionInfo,
|
|
1241
|
+
walletInfo: yield this.getWalletInfo()
|
|
1242
|
+
});
|
|
1243
|
+
return message;
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
/**
|
|
1247
|
+
* Send a simulated proof of event request to the wallet. The wallet will either accept or decline the challenge.
|
|
1248
|
+
* It's the same than `requestProofOfEventChallenge` but rather than executing operations on the blockchain to prove the identity,
|
|
1249
|
+
* The wallet will return a list of operations that you'll be able to run on your side to verify the identity of the abstracted account
|
|
1250
|
+
* It's **highly recommended** to run a proof of event challenge to check the identity of an abstracted account
|
|
1251
|
+
*
|
|
1252
|
+
* @param input The message details we need to prepare the SimulatedProofOfEventChallenge message.
|
|
1253
|
+
*/
|
|
1254
|
+
requestSimulatedProofOfEventChallenge(input) {
|
|
1255
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1256
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1257
|
+
if (!activeAccount)
|
|
1258
|
+
throw new Error('Please request permissions before doing a proof of event challenge');
|
|
1259
|
+
if (activeAccount.walletType !== 'abstracted_account' &&
|
|
1260
|
+
activeAccount.verificationType !== 'proof_of_event') {
|
|
1261
|
+
throw new Error('This wallet is not an abstracted account and thus cannot perform a simulated proof of event');
|
|
1262
|
+
}
|
|
1263
|
+
const request = Object.assign({ type: octez_connect_types_1.BeaconMessageType.SimulatedProofOfEventChallengeRequest, contractAddress: activeAccount.address }, input);
|
|
1264
|
+
const logId = `makeRequest ${Date.now()}`;
|
|
1265
|
+
logger.time(true, logId);
|
|
1266
|
+
const res = (yield this.checkMakeRequest())
|
|
1267
|
+
? this.makeRequest(request)
|
|
1268
|
+
: this.makeRequestBC(request);
|
|
1269
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1270
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1271
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1272
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1273
|
+
logger.time(false, logId);
|
|
1274
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1275
|
+
}));
|
|
1276
|
+
const { message, connectionInfo } = (yield res);
|
|
1277
|
+
logger.time(false, logId);
|
|
1278
|
+
this.analytics.track('event', 'DAppClient', `Simulated proof of event challenge ${!message.errorMessage ? 'accepted' : 'refused'}`, { address: activeAccount.address });
|
|
1279
|
+
yield this.notifySuccess(request, {
|
|
1280
|
+
account: activeAccount,
|
|
1281
|
+
output: message,
|
|
1282
|
+
blockExplorer: this.blockExplorer,
|
|
1283
|
+
connectionContext: connectionInfo,
|
|
1284
|
+
walletInfo: yield this.getWalletInfo()
|
|
1285
|
+
});
|
|
1286
|
+
return message;
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* This method will send a "SignPayloadRequest" to the wallet. This method is meant to be used to sign
|
|
1291
|
+
* arbitrary data (eg. a string). It will return the signature in the format of "edsig..."
|
|
1292
|
+
*
|
|
1293
|
+
* @param input The message details we need to prepare the SignPayloadRequest message.
|
|
1294
|
+
*/
|
|
1295
|
+
requestSignPayload(input) {
|
|
1296
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1297
|
+
if (!input.payload) {
|
|
1298
|
+
throw yield this.sendInternalError('Payload must be provided');
|
|
1299
|
+
}
|
|
1300
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1301
|
+
if (!activeAccount) {
|
|
1302
|
+
throw yield this.sendInternalError('No active account!');
|
|
1303
|
+
}
|
|
1304
|
+
const payload = input.payload;
|
|
1305
|
+
if (typeof payload !== 'string') {
|
|
1306
|
+
throw new Error('Payload must be a string');
|
|
1307
|
+
}
|
|
1308
|
+
const signingType = (() => {
|
|
1309
|
+
switch (input.signingType) {
|
|
1310
|
+
case octez_connect_types_1.SigningType.OPERATION:
|
|
1311
|
+
if (!payload.startsWith('03')) {
|
|
1312
|
+
throw new Error('When using signing type "OPERATION", the payload must start with prefix "03"');
|
|
1313
|
+
}
|
|
1314
|
+
return octez_connect_types_1.SigningType.OPERATION;
|
|
1315
|
+
case octez_connect_types_1.SigningType.MICHELINE:
|
|
1316
|
+
if (!payload.startsWith('05')) {
|
|
1317
|
+
throw new Error('When using signing type "MICHELINE", the payload must start with prefix "05"');
|
|
1318
|
+
}
|
|
1319
|
+
return octez_connect_types_1.SigningType.MICHELINE;
|
|
1320
|
+
case octez_connect_types_1.SigningType.RAW:
|
|
1321
|
+
default:
|
|
1322
|
+
return octez_connect_types_1.SigningType.RAW;
|
|
1323
|
+
}
|
|
1324
|
+
})();
|
|
1325
|
+
this.analytics.track('event', 'DAppClient', 'Signature requested');
|
|
1326
|
+
const request = {
|
|
1327
|
+
type: octez_connect_types_1.BeaconMessageType.SignPayloadRequest,
|
|
1328
|
+
signingType,
|
|
1329
|
+
payload,
|
|
1330
|
+
sourceAddress: input.sourceAddress || activeAccount.address
|
|
1331
|
+
};
|
|
1332
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'start'));
|
|
1333
|
+
const logId = `makeRequest ${Date.now()}`;
|
|
1334
|
+
logger.time(true, logId);
|
|
1335
|
+
const res = (yield this.checkMakeRequest())
|
|
1336
|
+
? this.makeRequest(request)
|
|
1337
|
+
: this.makeRequestBC(request);
|
|
1338
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1339
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1340
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1341
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1342
|
+
logger.time(false, logId);
|
|
1343
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1344
|
+
}));
|
|
1345
|
+
const { message, connectionInfo } = (yield res);
|
|
1346
|
+
logger.time(false, logId);
|
|
1347
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'success'));
|
|
1348
|
+
yield this.notifySuccess(request, {
|
|
1349
|
+
account: activeAccount,
|
|
1350
|
+
output: message,
|
|
1351
|
+
connectionContext: connectionInfo,
|
|
1352
|
+
walletInfo: yield this.getWalletInfo()
|
|
1353
|
+
});
|
|
1354
|
+
this.analytics.track('event', 'DAppClient', 'Signature response');
|
|
1355
|
+
return message;
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* This method will send an "EncryptPayloadRequest" to the wallet. This method is meant to be used to encrypt or decrypt
|
|
1360
|
+
* arbitrary data (eg. a string). It will return the encrypted or decrypted payload
|
|
1361
|
+
*
|
|
1362
|
+
* @param input The message details we need to prepare the EncryptPayloadRequest message.
|
|
1363
|
+
*/
|
|
1364
|
+
// TODO: ENCRYPTION
|
|
1365
|
+
// public async requestEncryptPayload(
|
|
1366
|
+
// input: RequestEncryptPayloadInput
|
|
1367
|
+
// ): Promise<EncryptPayloadResponseOutput> {
|
|
1368
|
+
// if (!input.payload) {
|
|
1369
|
+
// throw await this.sendInternalError('Payload must be provided')
|
|
1370
|
+
// }
|
|
1371
|
+
// const activeAccount: AccountInfo | undefined = await this.getActiveAccount()
|
|
1372
|
+
// if (!activeAccount) {
|
|
1373
|
+
// throw await this.sendInternalError('No active account!')
|
|
1374
|
+
// }
|
|
1375
|
+
// const payload = input.payload
|
|
1376
|
+
// if (typeof payload !== 'string') {
|
|
1377
|
+
// throw new Error('Payload must be a string')
|
|
1378
|
+
// }
|
|
1379
|
+
// if (typeof input.encryptionCryptoOperation === 'undefined') {
|
|
1380
|
+
// throw new Error('encryptionCryptoOperation must be defined')
|
|
1381
|
+
// }
|
|
1382
|
+
// if (typeof input.encryptionType === 'undefined') {
|
|
1383
|
+
// throw new Error('encryptionType must be defined')
|
|
1384
|
+
// }
|
|
1385
|
+
// const request: EncryptPayloadRequestInput = {
|
|
1386
|
+
// type: BeaconMessageType.EncryptPayloadRequest,
|
|
1387
|
+
// cryptoOperation: input.encryptionCryptoOperation,
|
|
1388
|
+
// encryptionType: input.encryptionType,
|
|
1389
|
+
// payload,
|
|
1390
|
+
// sourceAddress: input.sourceAddress || activeAccount.address
|
|
1391
|
+
// }
|
|
1392
|
+
// const { message, connectionInfo } = await this.makeRequest<
|
|
1393
|
+
// EncryptPayloadRequest,
|
|
1394
|
+
// EncryptPayloadResponse
|
|
1395
|
+
// >(request).catch(async (requestError: ErrorResponse) => {
|
|
1396
|
+
// throw await this.handleRequestError(request, requestError)
|
|
1397
|
+
// })
|
|
1398
|
+
// await this.notifySuccess(request, {
|
|
1399
|
+
// account: activeAccount,
|
|
1400
|
+
// output: message,
|
|
1401
|
+
// connectionContext: connectionInfo,
|
|
1402
|
+
// walletInfo: await this.getWalletInfo()
|
|
1403
|
+
// })
|
|
1404
|
+
// return message
|
|
1405
|
+
// }
|
|
1406
|
+
/**
|
|
1407
|
+
* This method sends an OperationRequest to the wallet. This method should be used for all kinds of operations,
|
|
1408
|
+
* eg. transaction or delegation. Not all properties have to be provided. Data like "counter" and fees will be
|
|
1409
|
+
* fetched and calculated by the wallet (but they can still be provided if required).
|
|
1410
|
+
*
|
|
1411
|
+
* @param input The message details we need to prepare the OperationRequest message.
|
|
1412
|
+
*/
|
|
1413
|
+
requestOperation(input) {
|
|
1414
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1415
|
+
if (!input.operationDetails) {
|
|
1416
|
+
throw yield this.sendInternalError('Operation details must be provided');
|
|
1417
|
+
}
|
|
1418
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1419
|
+
if (!activeAccount) {
|
|
1420
|
+
throw yield this.sendInternalError('No active account!');
|
|
1421
|
+
}
|
|
1422
|
+
const request = {
|
|
1423
|
+
type: octez_connect_types_1.BeaconMessageType.OperationRequest,
|
|
1424
|
+
network: activeAccount.network || this.network,
|
|
1425
|
+
operationDetails: input.operationDetails,
|
|
1426
|
+
sourceAddress: activeAccount.address || ''
|
|
1427
|
+
};
|
|
1428
|
+
this.analytics.track('event', 'DAppClient', 'Operation requested');
|
|
1429
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'start'));
|
|
1430
|
+
const logId = `makeRequest ${Date.now()}`;
|
|
1431
|
+
logger.time(true, logId);
|
|
1432
|
+
const res = (yield this.checkMakeRequest())
|
|
1433
|
+
? this.makeRequest(request)
|
|
1434
|
+
: this.makeRequestBC(request);
|
|
1435
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1436
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1437
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1438
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1439
|
+
logger.time(false, logId);
|
|
1440
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1441
|
+
}));
|
|
1442
|
+
const { message, connectionInfo } = (yield res);
|
|
1443
|
+
logger.time(false, logId);
|
|
1444
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'success'));
|
|
1445
|
+
yield this.notifySuccess(request, {
|
|
1446
|
+
account: activeAccount,
|
|
1447
|
+
output: message,
|
|
1448
|
+
blockExplorer: this.blockExplorer,
|
|
1449
|
+
connectionContext: connectionInfo,
|
|
1450
|
+
walletInfo: yield this.getWalletInfo()
|
|
1451
|
+
});
|
|
1452
|
+
this.analytics.track('event', 'DAppClient', 'Operation response');
|
|
1453
|
+
return message;
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
/**
|
|
1457
|
+
* Sends a "BroadcastRequest" to the wallet. This method can be used to inject an already signed transaction
|
|
1458
|
+
* to the network.
|
|
1459
|
+
*
|
|
1460
|
+
* @param input The message details we need to prepare the BroadcastRequest message.
|
|
1461
|
+
*/
|
|
1462
|
+
requestBroadcast(input) {
|
|
1463
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1464
|
+
var _a;
|
|
1465
|
+
if (!input.signedTransaction) {
|
|
1466
|
+
throw yield this.sendInternalError('Signed transaction must be provided');
|
|
1467
|
+
}
|
|
1468
|
+
// Add error message for deprecation of network
|
|
1469
|
+
// TODO: Remove when we remove deprecated preferredNetwork
|
|
1470
|
+
if (input.network !== undefined && this.network.type !== ((_a = input.network) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
1471
|
+
console.error('[BEACON] The network specified in the DAppClient constructor does not match the network set in the broadcast request. Please set the network in the constructor. Setting it during the Broadcast Request is deprecated.');
|
|
1472
|
+
}
|
|
1473
|
+
const request = {
|
|
1474
|
+
type: octez_connect_types_1.BeaconMessageType.BroadcastRequest,
|
|
1475
|
+
network: this.network,
|
|
1476
|
+
signedTransaction: input.signedTransaction
|
|
1477
|
+
};
|
|
1478
|
+
this.analytics.track('event', 'DAppClient', 'Broadcast requested');
|
|
1479
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'start'));
|
|
1480
|
+
const logId = `makeRequest ${Date.now()}`;
|
|
1481
|
+
logger.time(true, logId);
|
|
1482
|
+
const res = (yield this.checkMakeRequest())
|
|
1483
|
+
? this.makeRequest(request)
|
|
1484
|
+
: this.makeRequestBC(request);
|
|
1485
|
+
res.catch((requestError) => __awaiter(this, void 0, void 0, function* () {
|
|
1486
|
+
requestError.errorType === octez_connect_types_1.BeaconErrorType.ABORTED_ERROR
|
|
1487
|
+
? this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'abort'))
|
|
1488
|
+
: this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'error'));
|
|
1489
|
+
logger.time(false, logId);
|
|
1490
|
+
throw yield this.handleRequestError(request, requestError);
|
|
1491
|
+
}));
|
|
1492
|
+
const { message, connectionInfo } = (yield res);
|
|
1493
|
+
logger.time(false, logId);
|
|
1494
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('message', 'success'));
|
|
1495
|
+
yield this.notifySuccess(request, {
|
|
1496
|
+
network: this.network,
|
|
1497
|
+
output: message,
|
|
1498
|
+
blockExplorer: this.blockExplorer,
|
|
1499
|
+
connectionContext: connectionInfo,
|
|
1500
|
+
walletInfo: yield this.getWalletInfo()
|
|
1501
|
+
});
|
|
1502
|
+
this.analytics.track('event', 'DAppClient', 'Broadcast response');
|
|
1503
|
+
return message;
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
setActivePeer(peer) {
|
|
1507
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1508
|
+
if (this._activePeer.isSettled()) {
|
|
1509
|
+
// If the promise has already been resolved we need to create a new one.
|
|
1510
|
+
this._activePeer = octez_connect_utils_1.ExposedPromise.resolve(peer);
|
|
1511
|
+
}
|
|
1512
|
+
else {
|
|
1513
|
+
this._activePeer.resolve(peer);
|
|
1514
|
+
}
|
|
1515
|
+
if (!peer) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
yield this.initInternalTransports();
|
|
1519
|
+
if (peer.type === 'postmessage-pairing-response') {
|
|
1520
|
+
yield this.setTransport(this.postMessageTransport);
|
|
1521
|
+
}
|
|
1522
|
+
else if (peer.type === 'p2p-pairing-response') {
|
|
1523
|
+
yield this.setTransport(this.p2pTransport);
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* A "setter" for when the transport needs to be changed.
|
|
1529
|
+
*/
|
|
1530
|
+
setTransport(transport) {
|
|
1531
|
+
const _super = Object.create(null, {
|
|
1532
|
+
setTransport: { get: () => super.setTransport }
|
|
1533
|
+
});
|
|
1534
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1535
|
+
if (!transport) {
|
|
1536
|
+
this._initPromise = undefined;
|
|
1537
|
+
}
|
|
1538
|
+
const result = _super.setTransport.call(this, transport);
|
|
1539
|
+
const event = transport ? Object.assign({}, transport) : undefined;
|
|
1540
|
+
// remove keyPair, to prevent dApps from accidentaly leaking the privateKey
|
|
1541
|
+
if (event) {
|
|
1542
|
+
event.client = Object.assign(Object.assign({}, event.client), { keyPair: undefined });
|
|
1543
|
+
}
|
|
1544
|
+
yield this.events.emit(events_1.BeaconEvent.ACTIVE_TRANSPORT_SET, event);
|
|
1545
|
+
return result;
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
/**
|
|
1549
|
+
* This method will emit an internal error message.
|
|
1550
|
+
*
|
|
1551
|
+
* @param errorMessage The error message to send.
|
|
1552
|
+
*/
|
|
1553
|
+
sendInternalError(errorMessage) {
|
|
1554
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1555
|
+
yield this.events.emit(events_1.BeaconEvent.INTERNAL_ERROR, { text: errorMessage });
|
|
1556
|
+
throw new Error(errorMessage);
|
|
1557
|
+
});
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* This method will remove all accounts associated with a specific peer.
|
|
1561
|
+
*
|
|
1562
|
+
* @param peersToRemove An array of peers for which accounts should be removed
|
|
1563
|
+
*/
|
|
1564
|
+
removeAccountsForPeers(peersToRemove) {
|
|
1565
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1566
|
+
const peerIdsToRemove = peersToRemove.map((peer) => peer.senderId);
|
|
1567
|
+
return this.removeAccountsForPeerIds(peerIdsToRemove);
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
removeAccountsForPeerIds(peerIds) {
|
|
1571
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1572
|
+
const accounts = yield this.accountManager.getAccounts();
|
|
1573
|
+
// Remove all accounts with origin of the specified peer
|
|
1574
|
+
const accountsToRemove = accounts.filter((account) => peerIds.includes(account.senderId));
|
|
1575
|
+
const accountIdentifiersToRemove = accountsToRemove.map((accountInfo) => accountInfo.accountIdentifier);
|
|
1576
|
+
yield this.accountManager.removeAccounts(accountIdentifiersToRemove);
|
|
1577
|
+
// Check if one of the accounts that was removed was the active account and if yes, set it to undefined
|
|
1578
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1579
|
+
if (activeAccount) {
|
|
1580
|
+
if (accountIdentifiersToRemove.includes(activeAccount.accountIdentifier)) {
|
|
1581
|
+
yield this.setActiveAccount(undefined);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
/**
|
|
1587
|
+
* This message handles errors that we receive from the wallet.
|
|
1588
|
+
*
|
|
1589
|
+
* @param request The request we sent
|
|
1590
|
+
* @param beaconError The error we received
|
|
1591
|
+
*/
|
|
1592
|
+
handleRequestError(request, beaconError) {
|
|
1593
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1594
|
+
logger.error('handleRequestError', 'error response', beaconError);
|
|
1595
|
+
if (beaconError.errorType) {
|
|
1596
|
+
const buttons = [];
|
|
1597
|
+
if (beaconError.errorType === octez_connect_types_1.BeaconErrorType.NO_PRIVATE_KEY_FOUND_ERROR) {
|
|
1598
|
+
const actionCallback = () => __awaiter(this, void 0, void 0, function* () {
|
|
1599
|
+
const operationRequest = request;
|
|
1600
|
+
// if the account we requested is not available, we remove it locally
|
|
1601
|
+
let accountInfo;
|
|
1602
|
+
if (operationRequest.sourceAddress && operationRequest.network) {
|
|
1603
|
+
const accountIdentifier = yield (0, octez_connect_core_1.getAccountIdentifier)(operationRequest.sourceAddress, operationRequest.network);
|
|
1604
|
+
accountInfo = yield this.getAccount(accountIdentifier);
|
|
1605
|
+
if (accountInfo) {
|
|
1606
|
+
yield this.removeAccount(accountInfo.accountIdentifier);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
});
|
|
1610
|
+
buttons.push({ text: 'Remove account', actionCallback });
|
|
1611
|
+
}
|
|
1612
|
+
const peer = yield this.getPeer();
|
|
1613
|
+
const activeAccount = yield this.getActiveAccount();
|
|
1614
|
+
// If we sent a permission request, received an error and there is no active account, we need to reset the DAppClient.
|
|
1615
|
+
// This most likely means that the user rejected the first permission request after pairing a wallet, so we "forget" the paired wallet to allow the user to pair again.
|
|
1616
|
+
if (request.type === octez_connect_types_1.BeaconMessageType.PermissionRequest &&
|
|
1617
|
+
(yield this.getActiveAccount()) === undefined) {
|
|
1618
|
+
this._initPromise = undefined;
|
|
1619
|
+
this.postMessageTransport = undefined;
|
|
1620
|
+
this.p2pTransport = undefined;
|
|
1621
|
+
this.walletConnectTransport = undefined;
|
|
1622
|
+
yield this.setTransport();
|
|
1623
|
+
yield this.setActivePeer();
|
|
1624
|
+
}
|
|
1625
|
+
this.events
|
|
1626
|
+
.emit(beacon_message_events_1.messageEvents[request.type].error, {
|
|
1627
|
+
errorResponse: beaconError,
|
|
1628
|
+
walletInfo: yield this.getWalletInfo(peer, activeAccount),
|
|
1629
|
+
errorMessages: this.errorMessages
|
|
1630
|
+
}, buttons)
|
|
1631
|
+
.catch((emitError) => logger.error('handleRequestError', emitError));
|
|
1632
|
+
throw (0, octez_connect_core_1.getError)(beaconError.errorType, beaconError.errorData);
|
|
1633
|
+
}
|
|
1634
|
+
throw beaconError;
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* This message will send an event when we receive a successful response to one of the requests we sent.
|
|
1639
|
+
*
|
|
1640
|
+
* @param request The request we sent
|
|
1641
|
+
* @param response The response we received
|
|
1642
|
+
*/
|
|
1643
|
+
notifySuccess(request, response) {
|
|
1644
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1645
|
+
this.events
|
|
1646
|
+
.emit(beacon_message_events_1.messageEvents[request.type].success, response)
|
|
1647
|
+
.catch((emitError) => console.warn(emitError));
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1650
|
+
getWalletInfoFromStorage() {
|
|
1651
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1652
|
+
return yield this.storage.get(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET);
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
updateStorageWallet(walletInfo) {
|
|
1656
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1657
|
+
var _a;
|
|
1658
|
+
const wallet = yield this.storage.get(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET);
|
|
1659
|
+
if (!wallet) {
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
wallet.name = walletInfo.name;
|
|
1663
|
+
wallet.icon = (_a = walletInfo.icon) !== null && _a !== void 0 ? _a : wallet.icon;
|
|
1664
|
+
this.storage.set(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET, wallet);
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
getWalletInfo(peer_1, account_1) {
|
|
1668
|
+
return __awaiter(this, arguments, void 0, function* (peer, account, readFromStorage = true) {
|
|
1669
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1670
|
+
const selectedAccount = account ? account : yield this.getActiveAccount();
|
|
1671
|
+
const selectedPeer = peer ? peer : yield this.getPeer(selectedAccount);
|
|
1672
|
+
let walletInfo;
|
|
1673
|
+
if (selectedAccount) {
|
|
1674
|
+
walletInfo = yield this.appMetadataManager.getAppMetadata(selectedAccount.senderId);
|
|
1675
|
+
}
|
|
1676
|
+
let storageWallet;
|
|
1677
|
+
if (readFromStorage) {
|
|
1678
|
+
storageWallet = yield this.getWalletInfoFromStorage();
|
|
1679
|
+
}
|
|
1680
|
+
if (!walletInfo) {
|
|
1681
|
+
walletInfo = {
|
|
1682
|
+
name: (_b = (_a = selectedPeer === null || selectedPeer === void 0 ? void 0 : selectedPeer.name) !== null && _a !== void 0 ? _a : storageWallet === null || storageWallet === void 0 ? void 0 : storageWallet.key) !== null && _b !== void 0 ? _b : '',
|
|
1683
|
+
icon: (_c = selectedPeer === null || selectedPeer === void 0 ? void 0 : selectedPeer.icon) !== null && _c !== void 0 ? _c : storageWallet === null || storageWallet === void 0 ? void 0 : storageWallet.icon,
|
|
1684
|
+
type: storageWallet === null || storageWallet === void 0 ? void 0 : storageWallet.type
|
|
1685
|
+
};
|
|
1686
|
+
this.updateStorageWallet(walletInfo);
|
|
1687
|
+
}
|
|
1688
|
+
const lowerCaseCompare = (str1, str2) => {
|
|
1689
|
+
if (str1 && str2) {
|
|
1690
|
+
return str1.toLowerCase() === str2.toLowerCase();
|
|
1691
|
+
}
|
|
1692
|
+
return false;
|
|
1693
|
+
};
|
|
1694
|
+
const getOrgName = (name) => name.split(/[_\s]+/)[0];
|
|
1695
|
+
const apps = [
|
|
1696
|
+
...(0, octez_connect_ui_1.getiOSList)(),
|
|
1697
|
+
...(0, octez_connect_ui_1.getWebList)(),
|
|
1698
|
+
...(0, octez_connect_ui_1.getDesktopList)(),
|
|
1699
|
+
...(0, octez_connect_ui_1.getExtensionList)()
|
|
1700
|
+
].filter((app) => { var _a; return lowerCaseCompare(getOrgName(app.key), getOrgName((_a = walletInfo === null || walletInfo === void 0 ? void 0 : walletInfo.name) !== null && _a !== void 0 ? _a : 'wallet')); });
|
|
1701
|
+
// TODO: Remove once all wallets send the icon?
|
|
1702
|
+
const mobile = apps.find((app) => app.universalLink || app.key.includes('ios') || app.key.includes('mobile'));
|
|
1703
|
+
const browser = apps.find((app) => app.links);
|
|
1704
|
+
const desktop = apps.find((app) => app.downloadLink);
|
|
1705
|
+
const extension = apps.find((app) => app.id);
|
|
1706
|
+
const appTypeMap = {
|
|
1707
|
+
extension: { app: extension, type: 'extension' },
|
|
1708
|
+
desktop: { app: desktop, type: 'desktop' },
|
|
1709
|
+
mobile: { app: mobile, type: 'mobile' },
|
|
1710
|
+
web: { app: browser, type: 'web' }
|
|
1711
|
+
};
|
|
1712
|
+
const defaultType = () => {
|
|
1713
|
+
if ((0, octez_connect_ui_1.isBrowser)(window) && browser)
|
|
1714
|
+
return { app: browser, type: 'web' };
|
|
1715
|
+
if ((0, octez_connect_ui_1.isDesktop)(window) && desktop)
|
|
1716
|
+
return { app: desktop, type: 'desktop' };
|
|
1717
|
+
if ((0, octez_connect_ui_1.isBrowser)(window) && extension)
|
|
1718
|
+
return { app: extension, type: 'extension' };
|
|
1719
|
+
if (mobile)
|
|
1720
|
+
return { app: mobile, type: 'mobile' };
|
|
1721
|
+
return { app: undefined, type: undefined };
|
|
1722
|
+
};
|
|
1723
|
+
const { app, type } = storageWallet ? appTypeMap[storageWallet.type] : defaultType();
|
|
1724
|
+
if (app) {
|
|
1725
|
+
let deeplink;
|
|
1726
|
+
if (app.hasOwnProperty('links')) {
|
|
1727
|
+
deeplink = app.links[(_d = selectedAccount === null || selectedAccount === void 0 ? void 0 : selectedAccount.network.type) !== null && _d !== void 0 ? _d : this.network.type];
|
|
1728
|
+
}
|
|
1729
|
+
else if (app.hasOwnProperty('deepLink')) {
|
|
1730
|
+
deeplink = app.deepLink;
|
|
1731
|
+
}
|
|
1732
|
+
return {
|
|
1733
|
+
name: (_e = app === null || app === void 0 ? void 0 : app.name) !== null && _e !== void 0 ? _e : walletInfo.name,
|
|
1734
|
+
icon: (_f = app === null || app === void 0 ? void 0 : app.logo) !== null && _f !== void 0 ? _f : walletInfo.icon,
|
|
1735
|
+
deeplink,
|
|
1736
|
+
type: type
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
return walletInfo;
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
getPeer(account) {
|
|
1743
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1744
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1745
|
+
let peer;
|
|
1746
|
+
if (account) {
|
|
1747
|
+
logger.log('getPeer', 'We have an account', account);
|
|
1748
|
+
const postMessagePeers = (_b = (yield ((_a = this.postMessageTransport) === null || _a === void 0 ? void 0 : _a.getPeers()))) !== null && _b !== void 0 ? _b : [];
|
|
1749
|
+
const p2pPeers = (_d = (yield ((_c = this.p2pTransport) === null || _c === void 0 ? void 0 : _c.getPeers()))) !== null && _d !== void 0 ? _d : [];
|
|
1750
|
+
const walletConnectPeers = (_f = (yield ((_e = this.walletConnectTransport) === null || _e === void 0 ? void 0 : _e.getPeers()))) !== null && _f !== void 0 ? _f : [];
|
|
1751
|
+
const peers = [...postMessagePeers, ...p2pPeers, ...walletConnectPeers];
|
|
1752
|
+
logger.log('getPeer', 'Found peers', peers, account);
|
|
1753
|
+
peer = peers.find((peerEl) => peerEl.senderId === account.senderId);
|
|
1754
|
+
if (!peer) {
|
|
1755
|
+
// We could not find an exact match for a sender, so we most likely received it over a relay
|
|
1756
|
+
peer = peers.find((peerEl) => peerEl.id === account.origin.id);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
else {
|
|
1760
|
+
peer = yield this._activePeer.promise;
|
|
1761
|
+
logger.log('getPeer', 'Active peer', peer);
|
|
1762
|
+
}
|
|
1763
|
+
return peer;
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
makeRequest(requestInput, skipResponse, otherTabMessageId) {
|
|
1767
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1768
|
+
var _a, _b, _c;
|
|
1769
|
+
const messageId = otherTabMessageId !== null && otherTabMessageId !== void 0 ? otherTabMessageId : (yield (0, octez_connect_utils_1.generateGUID)());
|
|
1770
|
+
if (this._initPromise && this.isInitPending) {
|
|
1771
|
+
yield Promise.all([
|
|
1772
|
+
(_a = this.postMessageTransport) === null || _a === void 0 ? void 0 : _a.disconnect(),
|
|
1773
|
+
(_b = this.walletConnectTransport) === null || _b === void 0 ? void 0 : _b.disconnect()
|
|
1774
|
+
]);
|
|
1775
|
+
this._initPromise = undefined;
|
|
1776
|
+
this.hideUI(['toast']);
|
|
1777
|
+
}
|
|
1778
|
+
logger.log('makeRequest', 'starting');
|
|
1779
|
+
this.isInitPending = true;
|
|
1780
|
+
yield this.init();
|
|
1781
|
+
this.isInitPending = false;
|
|
1782
|
+
logger.log('makeRequest', 'after init');
|
|
1783
|
+
if (yield this.addRequestAndCheckIfRateLimited()) {
|
|
1784
|
+
this.events
|
|
1785
|
+
.emit(events_1.BeaconEvent.LOCAL_RATE_LIMIT_REACHED)
|
|
1786
|
+
.catch((emitError) => console.warn(emitError));
|
|
1787
|
+
throw new Error('rate limit reached');
|
|
1788
|
+
}
|
|
1789
|
+
if (!(yield this.checkPermissions(requestInput.type))) {
|
|
1790
|
+
this.events.emit(events_1.BeaconEvent.NO_PERMISSIONS).catch((emitError) => console.warn(emitError));
|
|
1791
|
+
throw new Error('No permissions to send this request to wallet!');
|
|
1792
|
+
}
|
|
1793
|
+
if (!this.beaconId) {
|
|
1794
|
+
throw yield this.sendInternalError('octez.connect ID not defined');
|
|
1795
|
+
}
|
|
1796
|
+
const request = Object.assign({ id: messageId, version: '2', senderId: yield (0, octez_connect_core_1.getSenderId)(yield this.beaconId) }, requestInput);
|
|
1797
|
+
let exposed;
|
|
1798
|
+
if (!skipResponse) {
|
|
1799
|
+
exposed = new octez_connect_utils_1.ExposedPromise();
|
|
1800
|
+
this.addOpenRequest(request.id, exposed);
|
|
1801
|
+
}
|
|
1802
|
+
const payload = yield new octez_connect_core_1.Serializer().serialize(request);
|
|
1803
|
+
const account = yield this.getActiveAccount();
|
|
1804
|
+
const peer = yield this.getPeer(account);
|
|
1805
|
+
const walletInfo = yield this.getWalletInfo(peer, account);
|
|
1806
|
+
logger.log('makeRequest', 'sending message', request);
|
|
1807
|
+
try {
|
|
1808
|
+
;
|
|
1809
|
+
(yield this.transport).send(payload, peer);
|
|
1810
|
+
if (request.type !== octez_connect_types_1.BeaconMessageType.PermissionRequest ||
|
|
1811
|
+
(this._activeAccount.isResolved() && (yield this._activeAccount.promise))) {
|
|
1812
|
+
this.tryToAppSwitch();
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
catch (sendError) {
|
|
1816
|
+
this.events.emit(events_1.BeaconEvent.INTERNAL_ERROR, {
|
|
1817
|
+
text: 'Unable to send message. If this problem persists, please reset the connection and pair your wallet again.',
|
|
1818
|
+
buttons: [
|
|
1819
|
+
{
|
|
1820
|
+
text: 'Reset Connection',
|
|
1821
|
+
actionCallback: () => __awaiter(this, void 0, void 0, function* () {
|
|
1822
|
+
(0, octez_connect_ui_1.closeToast)();
|
|
1823
|
+
this.disconnect();
|
|
1824
|
+
})
|
|
1825
|
+
}
|
|
1826
|
+
]
|
|
1827
|
+
});
|
|
1828
|
+
throw sendError;
|
|
1829
|
+
}
|
|
1830
|
+
if (!otherTabMessageId) {
|
|
1831
|
+
this.events
|
|
1832
|
+
.emit(beacon_message_events_1.messageEvents[requestInput.type].sent, {
|
|
1833
|
+
walletInfo: Object.assign(Object.assign({}, walletInfo), { name: (_c = walletInfo.name) !== null && _c !== void 0 ? _c : 'Wallet' }),
|
|
1834
|
+
extraInfo: {
|
|
1835
|
+
resetCallback: () => __awaiter(this, void 0, void 0, function* () {
|
|
1836
|
+
this.disconnect();
|
|
1837
|
+
})
|
|
1838
|
+
}
|
|
1839
|
+
})
|
|
1840
|
+
.catch((emitError) => console.warn(emitError));
|
|
1841
|
+
}
|
|
1842
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1843
|
+
return exposed === null || exposed === void 0 ? void 0 : exposed.promise; // TODO: fix type
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
/**
|
|
1847
|
+
* This method handles sending of requests to the DApp. It makes sure that the DAppClient is initialized and connected
|
|
1848
|
+
* to the transport. After that rate limits and permissions will be checked, an ID is attached and the request is sent
|
|
1849
|
+
* to the DApp over the transport.
|
|
1850
|
+
*
|
|
1851
|
+
* @param requestInput The BeaconMessage to be sent to the wallet
|
|
1852
|
+
* @param account The account that the message will be sent to
|
|
1853
|
+
*/
|
|
1854
|
+
makeRequestV3(requestInput, otherTabMessageId) {
|
|
1855
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1856
|
+
var _a, _b, _c;
|
|
1857
|
+
if (this._initPromise && this.isInitPending) {
|
|
1858
|
+
yield Promise.all([
|
|
1859
|
+
(_a = this.postMessageTransport) === null || _a === void 0 ? void 0 : _a.disconnect(),
|
|
1860
|
+
(_b = this.walletConnectTransport) === null || _b === void 0 ? void 0 : _b.disconnect()
|
|
1861
|
+
]);
|
|
1862
|
+
this._initPromise = undefined;
|
|
1863
|
+
this.hideUI(['toast']);
|
|
1864
|
+
}
|
|
1865
|
+
const messageId = otherTabMessageId !== null && otherTabMessageId !== void 0 ? otherTabMessageId : (yield (0, octez_connect_utils_1.generateGUID)());
|
|
1866
|
+
logger.log('makeRequest', 'starting');
|
|
1867
|
+
this.isInitPending = true;
|
|
1868
|
+
yield this.init(undefined, true);
|
|
1869
|
+
this.isInitPending = false;
|
|
1870
|
+
logger.log('makeRequest', 'after init');
|
|
1871
|
+
if (yield this.addRequestAndCheckIfRateLimited()) {
|
|
1872
|
+
this.events
|
|
1873
|
+
.emit(events_1.BeaconEvent.LOCAL_RATE_LIMIT_REACHED)
|
|
1874
|
+
.catch((emitError) => console.warn(emitError));
|
|
1875
|
+
throw new Error('rate limit reached');
|
|
1876
|
+
}
|
|
1877
|
+
if (!this.beaconId) {
|
|
1878
|
+
throw yield this.sendInternalError('octez.connect ID not defined');
|
|
1879
|
+
}
|
|
1880
|
+
const request = {
|
|
1881
|
+
id: messageId,
|
|
1882
|
+
version: '3',
|
|
1883
|
+
senderId: yield (0, octez_connect_core_1.getSenderId)(yield this.beaconId),
|
|
1884
|
+
message: requestInput
|
|
1885
|
+
};
|
|
1886
|
+
const exposed = new octez_connect_utils_1.ExposedPromise();
|
|
1887
|
+
this.addOpenRequest(request.id, exposed);
|
|
1888
|
+
const payload = yield new octez_connect_core_1.Serializer().serialize(request);
|
|
1889
|
+
const account = yield this.getActiveAccount();
|
|
1890
|
+
const peer = yield this.getPeer(account);
|
|
1891
|
+
const walletInfo = yield this.getWalletInfo(peer, account);
|
|
1892
|
+
logger.log('makeRequest', 'sending message', request);
|
|
1893
|
+
try {
|
|
1894
|
+
;
|
|
1895
|
+
(yield this.transport).send(payload, peer);
|
|
1896
|
+
if (request.message.type !== octez_connect_types_1.BeaconMessageType.PermissionRequest ||
|
|
1897
|
+
(this._activeAccount.isResolved() && (yield this._activeAccount.promise))) {
|
|
1898
|
+
this.tryToAppSwitch();
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
catch (sendError) {
|
|
1902
|
+
this.events.emit(events_1.BeaconEvent.INTERNAL_ERROR, {
|
|
1903
|
+
text: 'Unable to send message. If this problem persists, please reset the connection and pair your wallet again.',
|
|
1904
|
+
buttons: [
|
|
1905
|
+
{
|
|
1906
|
+
text: 'Reset Connection',
|
|
1907
|
+
actionCallback: () => __awaiter(this, void 0, void 0, function* () {
|
|
1908
|
+
(0, octez_connect_ui_1.closeToast)();
|
|
1909
|
+
this.disconnect();
|
|
1910
|
+
})
|
|
1911
|
+
}
|
|
1912
|
+
]
|
|
1913
|
+
});
|
|
1914
|
+
throw sendError;
|
|
1915
|
+
}
|
|
1916
|
+
const index = requestInput.type;
|
|
1917
|
+
this.events
|
|
1918
|
+
.emit(beacon_message_events_1.messageEvents[index].sent, {
|
|
1919
|
+
walletInfo: Object.assign(Object.assign({}, walletInfo), { name: (_c = walletInfo.name) !== null && _c !== void 0 ? _c : 'Wallet' }),
|
|
1920
|
+
extraInfo: {
|
|
1921
|
+
resetCallback: () => __awaiter(this, void 0, void 0, function* () {
|
|
1922
|
+
this.disconnect();
|
|
1923
|
+
})
|
|
1924
|
+
}
|
|
1925
|
+
})
|
|
1926
|
+
.catch((emitError) => console.warn(emitError));
|
|
1927
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1928
|
+
return exposed.promise; // TODO: fix type
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
makeRequestBC(request) {
|
|
1932
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1933
|
+
if (!this._transport.isResolved()) {
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
const transport = yield this.transport;
|
|
1937
|
+
if (transport.type !== octez_connect_types_1.TransportType.WALLETCONNECT) {
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
if (yield this.addRequestAndCheckIfRateLimited()) {
|
|
1941
|
+
this.events
|
|
1942
|
+
.emit(events_1.BeaconEvent.LOCAL_RATE_LIMIT_REACHED)
|
|
1943
|
+
.catch((emitError) => console.warn(emitError));
|
|
1944
|
+
throw new Error('rate limit reached');
|
|
1945
|
+
}
|
|
1946
|
+
const id = yield (0, octez_connect_utils_1.generateGUID)();
|
|
1947
|
+
this.multiTabChannel.postMessage({
|
|
1948
|
+
type: request.type,
|
|
1949
|
+
data: request,
|
|
1950
|
+
id
|
|
1951
|
+
});
|
|
1952
|
+
if (request.type !== octez_connect_types_1.BeaconMessageType.PermissionRequest ||
|
|
1953
|
+
(this._activeAccount.isResolved() && (yield this._activeAccount.promise))) {
|
|
1954
|
+
this.tryToAppSwitch();
|
|
1955
|
+
}
|
|
1956
|
+
this.events
|
|
1957
|
+
.emit(beacon_message_events_1.messageEvents[octez_connect_types_1.BeaconMessageType.PermissionRequest].sent, {
|
|
1958
|
+
walletInfo: yield this.getWalletInfo(),
|
|
1959
|
+
extraInfo: {
|
|
1960
|
+
resetCallback: () => this.disconnect()
|
|
1961
|
+
}
|
|
1962
|
+
})
|
|
1963
|
+
.catch((emitError) => console.warn(emitError));
|
|
1964
|
+
const exposed = new octez_connect_utils_1.ExposedPromise();
|
|
1965
|
+
this.addOpenRequest(id, exposed);
|
|
1966
|
+
return exposed.promise;
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1969
|
+
disconnect() {
|
|
1970
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1971
|
+
if (!this._transport.isResolved()) {
|
|
1972
|
+
throw new Error('No transport available.');
|
|
1973
|
+
}
|
|
1974
|
+
const transport = yield this.transport;
|
|
1975
|
+
if (transport.connectionStatus === octez_connect_types_1.TransportStatus.NOT_CONNECTED) {
|
|
1976
|
+
throw new Error('Not connected.');
|
|
1977
|
+
}
|
|
1978
|
+
yield this.createStateSnapshot();
|
|
1979
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('disconnect', 'start'));
|
|
1980
|
+
yield this.clearActiveAccount();
|
|
1981
|
+
if (!(transport instanceof octez_connect_transport_walletconnect_1.WalletConnectTransport)) {
|
|
1982
|
+
yield transport.disconnect();
|
|
1983
|
+
}
|
|
1984
|
+
this.postMessageTransport = undefined;
|
|
1985
|
+
this.p2pTransport = undefined;
|
|
1986
|
+
this.walletConnectTransport = undefined;
|
|
1987
|
+
this.sendMetrics('performance-metrics/save', yield this.buildPayload('disconnect', 'success'));
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Adds a requests to the "openRequests" set so we know what messages have already been answered/handled.
|
|
1992
|
+
*
|
|
1993
|
+
* @param id The ID of the message
|
|
1994
|
+
* @param promise A promise that resolves once the response for that specific message is received
|
|
1995
|
+
*/
|
|
1996
|
+
addOpenRequest(id, promise) {
|
|
1997
|
+
logger.log('addOpenRequest', this.name, `adding request ${id} and waiting for answer`);
|
|
1998
|
+
this.openRequests.set(id, promise);
|
|
1999
|
+
}
|
|
2000
|
+
sendNotificationWithAccessToken(notification) {
|
|
2001
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2002
|
+
const { url, recipient, title, body, payload, protocolIdentifier, accessToken } = notification;
|
|
2003
|
+
const timestamp = new Date().toISOString();
|
|
2004
|
+
const keypair = yield this.keyPair;
|
|
2005
|
+
const rawPublicKey = keypair.publicKey;
|
|
2006
|
+
const prefix = Buffer.from(new Uint8Array([13, 15, 37, 217]));
|
|
2007
|
+
const publicKey = bs58check_1.default.encode(Buffer.concat([prefix, Buffer.from(rawPublicKey)]));
|
|
2008
|
+
const constructedString = [
|
|
2009
|
+
'Tezos Signed Message: ',
|
|
2010
|
+
recipient,
|
|
2011
|
+
title,
|
|
2012
|
+
body,
|
|
2013
|
+
timestamp,
|
|
2014
|
+
payload
|
|
2015
|
+
].join(' ');
|
|
2016
|
+
const bytes = (0, octez_connect_utils_1.toHex)(constructedString);
|
|
2017
|
+
const payloadBytes = '05' + '01' + bytes.length.toString(16).padStart(8, '0') + bytes;
|
|
2018
|
+
const signature = yield (0, octez_connect_utils_1.signMessage)(payloadBytes, {
|
|
2019
|
+
secretKey: Buffer.from(keypair.secretKey)
|
|
2020
|
+
});
|
|
2021
|
+
const notificationResponse = yield axios_1.default.post(`${url}/send`, {
|
|
2022
|
+
recipient,
|
|
2023
|
+
title,
|
|
2024
|
+
body,
|
|
2025
|
+
timestamp,
|
|
2026
|
+
payload,
|
|
2027
|
+
accessToken,
|
|
2028
|
+
protocolIdentifier,
|
|
2029
|
+
sender: {
|
|
2030
|
+
name: this.name,
|
|
2031
|
+
publicKey,
|
|
2032
|
+
signature
|
|
2033
|
+
}
|
|
2034
|
+
});
|
|
2035
|
+
return notificationResponse.data;
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
onNewAccount(message, connectionInfo) {
|
|
2039
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2040
|
+
var _a, _b, _c;
|
|
2041
|
+
// TODO: Migration code. Remove sometime after 1.0.0 release.
|
|
2042
|
+
const tempPK = message.publicKey || message.pubkey || message.pubKey;
|
|
2043
|
+
const publicKey = !!tempPK ? (0, octez_connect_utils_1.prefixPublicKey)(tempPK) : undefined;
|
|
2044
|
+
if (!publicKey && !message.address) {
|
|
2045
|
+
throw new Error('PublicKey or Address must be defined');
|
|
2046
|
+
}
|
|
2047
|
+
const address = (_a = message.address) !== null && _a !== void 0 ? _a : (yield (0, octez_connect_utils_1.getAddressFromPublicKey)(publicKey));
|
|
2048
|
+
if (!(0, octez_connect_utils_1.isValidAddress)(address)) {
|
|
2049
|
+
throw new Error(`Invalid address: "${address}"`);
|
|
2050
|
+
}
|
|
2051
|
+
if (message.walletType === 'abstracted_account' &&
|
|
2052
|
+
address.substring(0, 3) !== octez_connect_utils_1.CONTRACT_PREFIX) {
|
|
2053
|
+
throw new Error(`Invalid abstracted account address "${address}", it should be a ${octez_connect_utils_1.CONTRACT_PREFIX} address`);
|
|
2054
|
+
}
|
|
2055
|
+
logger.log('######## MESSAGE #######');
|
|
2056
|
+
logger.log('onNewAccount', message);
|
|
2057
|
+
const walletKey = (_b = (yield this.storage.get(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET))) === null || _b === void 0 ? void 0 : _b.key;
|
|
2058
|
+
const accountInfo = Object.assign({ accountIdentifier: yield (0, octez_connect_core_1.getAccountIdentifier)(address, message.network), senderId: message.senderId, origin: {
|
|
2059
|
+
type: connectionInfo.origin,
|
|
2060
|
+
id: connectionInfo.id
|
|
2061
|
+
}, walletKey,
|
|
2062
|
+
address,
|
|
2063
|
+
publicKey, network: message.network, scopes: message.scopes, threshold: message.threshold, notification: message.notification, connectedAt: new Date().getTime(), walletType: (_c = message.walletType) !== null && _c !== void 0 ? _c : 'implicit', verificationType: message.verificationType }, (message.verificationType === 'proof_of_event' ? { hasVerifiedChallenge: false } : {}));
|
|
2064
|
+
logger.log('accountInfo', '######## ACCOUNT INFO #######');
|
|
2065
|
+
logger.log('accountInfo', accountInfo);
|
|
2066
|
+
yield this.accountManager.addAccount(accountInfo);
|
|
2067
|
+
yield this.setActiveAccount(accountInfo);
|
|
2068
|
+
return accountInfo;
|
|
2069
|
+
});
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
exports.DAppClient = DAppClient;
|
|
2073
|
+
//# sourceMappingURL=DAppClient.js.map
|