@tezos-x/octez.connect-dapp 5.0.0-beta.6 → 5.0.1
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/dist/cjs/dapp-client/DAppClient.d.ts +27 -5
- package/dist/cjs/dapp-client/DAppClient.js +525 -78
- package/dist/cjs/dapp-client/DAppClient.js.map +1 -1
- package/dist/cjs/dapp-client/DAppClientOptions.d.ts +25 -0
- package/dist/cjs/dapp-client/DAppClientOptions.js.map +1 -1
- package/dist/esm/dapp-client/DAppClient.d.ts +27 -5
- package/dist/esm/dapp-client/DAppClient.js +548 -77
- package/dist/esm/dapp-client/DAppClient.js.map +1 -1
- package/dist/esm/dapp-client/DAppClientOptions.d.ts +25 -0
- package/dist/esm/dapp-client/DAppClientOptions.js.map +1 -1
- package/dist/octez.connect.dapp.min.js +1 -1
- package/package.json +9 -8
|
@@ -16,17 +16,20 @@ exports.DAppClient = void 0;
|
|
|
16
16
|
const bs58check_1 = __importDefault(require("bs58check"));
|
|
17
17
|
const octez_connect_types_1 = require("@tezos-x/octez.connect-types");
|
|
18
18
|
const octez_connect_core_1 = require("@tezos-x/octez.connect-core");
|
|
19
|
+
const octez_connect_blockchain_tezos_1 = require("@tezos-x/octez.connect-blockchain-tezos");
|
|
19
20
|
const octez_connect_utils_1 = require("@tezos-x/octez.connect-utils");
|
|
21
|
+
const octez_connect_transport_postmessage_1 = require("@tezos-x/octez.connect-transport-postmessage");
|
|
22
|
+
const octez_connect_ui_1 = require("@tezos-x/octez.connect-ui");
|
|
23
|
+
const octez_connect_transport_walletconnect_1 = require("@tezos-x/octez.connect-transport-walletconnect");
|
|
20
24
|
const beacon_message_events_1 = require("../beacon-message-events");
|
|
21
25
|
const events_1 = require("../events");
|
|
22
26
|
const tzkt_blockexplorer_1 = require("../utils/tzkt-blockexplorer");
|
|
23
27
|
const DappPostMessageTransport_1 = require("../transports/DappPostMessageTransport");
|
|
24
28
|
const DappP2PTransport_1 = require("../transports/DappP2PTransport");
|
|
25
29
|
const DappWalletConnectTransport_1 = require("../transports/DappWalletConnectTransport");
|
|
26
|
-
const octez_connect_transport_postmessage_1 = require("@tezos-x/octez.connect-transport-postmessage");
|
|
27
|
-
const octez_connect_ui_1 = require("@tezos-x/octez.connect-ui");
|
|
28
|
-
const octez_connect_transport_walletconnect_1 = require("@tezos-x/octez.connect-transport-walletconnect");
|
|
29
30
|
const logger = new octez_connect_core_1.Logger('DAppClient');
|
|
31
|
+
// Surfaced when a permission response yields zero account records.
|
|
32
|
+
const EMPTY_PERMISSION_ACCOUNTS_MESSAGE = 'Wallet permission response did not include any accounts. Please re-pair the wallet and try again.';
|
|
30
33
|
/**
|
|
31
34
|
* @publicapi
|
|
32
35
|
*
|
|
@@ -40,6 +43,12 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
40
43
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
41
44
|
super(Object.assign({ storage: config && config.storage ? config.storage : new octez_connect_core_1.LocalStorage() }, config));
|
|
42
45
|
this.events = new events_1.BeaconEventHandler();
|
|
46
|
+
/**
|
|
47
|
+
* WalletConnect is opt-in: only enabled when `walletConnectOptions` is provided
|
|
48
|
+
* and `disableWalletConnect` is not set. When false, no WC transport is built,
|
|
49
|
+
* listened to, or offered for pairing, and no default projectId is applied.
|
|
50
|
+
*/
|
|
51
|
+
this.isWalletConnectEnabled = false;
|
|
43
52
|
this.isGetActiveAccountHandled = false;
|
|
44
53
|
this.openRequestsOtherTabs = new Set();
|
|
45
54
|
/**
|
|
@@ -60,8 +69,14 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
60
69
|
this.debounceSetActiveAccount = false;
|
|
61
70
|
this.multiTabChannel = new octez_connect_core_1.MultiTabChannel('octez.connect-sdk-channel', this.onBCMessageHandler.bind(this), this.onElectedLeaderhandler.bind(this));
|
|
62
71
|
this.description = config.description;
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
// WalletConnect is opt-in: only when walletConnectOptions is provided and not
|
|
73
|
+
// explicitly disabled. Don't apply the default projectId otherwise (#32).
|
|
74
|
+
this.isWalletConnectEnabled =
|
|
75
|
+
Boolean(config.walletConnectOptions) && !config.disableWalletConnect;
|
|
76
|
+
this.wcProjectId = this.isWalletConnectEnabled
|
|
77
|
+
? ((_a = config.walletConnectOptions) === null || _a === void 0 ? void 0 : _a.projectId) || '24469fd0a06df227b6e5f7dc7de0ff4f'
|
|
78
|
+
: undefined;
|
|
79
|
+
this.wcRelayUrl = this.isWalletConnectEnabled ? (_b = config.walletConnectOptions) === null || _b === void 0 ? void 0 : _b.relayUrl : undefined;
|
|
65
80
|
this.featuredWallets = config.featuredWallets;
|
|
66
81
|
this.events = new events_1.BeaconEventHandler(config.eventHandlers, (_c = config.disableDefaultEvents) !== null && _c !== void 0 ? _c : false);
|
|
67
82
|
this.blockExplorer = (_d = config.blockExplorer) !== null && _d !== void 0 ? _d : new tzkt_blockexplorer_1.TzktBlockExplorer();
|
|
@@ -73,8 +88,14 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
73
88
|
this.appMetadataManager = new octez_connect_core_1.AppMetadataManager(this.storage);
|
|
74
89
|
this.storageValidator = new octez_connect_core_1.StorageValidator(this.storage);
|
|
75
90
|
this.enableAppSwitching =
|
|
76
|
-
config.enableAppSwitching === undefined ? true :
|
|
91
|
+
config.enableAppSwitching === undefined ? true : Boolean(config.enableAppSwitching);
|
|
77
92
|
this.enableMetrics = config.enableMetrics ? true : false;
|
|
93
|
+
this.requiredMinimumVersion = (0, octez_connect_core_1.resolveRequiredMinimumVersion)(config.requiredMinimumVersion);
|
|
94
|
+
// Tezos is the default chain: the wrapped-only pipeline routes every
|
|
95
|
+
// request/response through the registry handler, so registration is no
|
|
96
|
+
// longer a consumer obligation. addBlockchain stays public — a later
|
|
97
|
+
// registration under 'tezos' overrides this default.
|
|
98
|
+
this.addBlockchain(new octez_connect_blockchain_tezos_1.TezosBlockchain());
|
|
78
99
|
// Subscribe to storage changes and update the active account if it changes on other tabs
|
|
79
100
|
this.storage.subscribeToStorageChanged((event) => __awaiter(this, void 0, void 0, function* () {
|
|
80
101
|
if (event.eventType === 'storageCleared') {
|
|
@@ -94,7 +115,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
94
115
|
return;
|
|
95
116
|
}
|
|
96
117
|
if (event.key === this.storage.getPrefixedKey(octez_connect_types_1.StorageKey.ENABLE_METRICS)) {
|
|
97
|
-
this.enableMetrics =
|
|
118
|
+
this.enableMetrics = Boolean(yield this.storage.get(octez_connect_types_1.StorageKey.ENABLE_METRICS));
|
|
98
119
|
return;
|
|
99
120
|
}
|
|
100
121
|
if (event.key === this.storage.getPrefixedKey(octez_connect_types_1.StorageKey.BEACON_SDK_SECRET_SEED)) {
|
|
@@ -124,15 +145,31 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
124
145
|
this.events.emit(events_1.BeaconEvent.INVALID_ACCOUNT_DEACTIVATED);
|
|
125
146
|
return undefined;
|
|
126
147
|
}));
|
|
127
|
-
this.handleResponse = (
|
|
148
|
+
this.handleResponse = (wireMessage, connectionInfo) => __awaiter(this, void 0, void 0, function* () {
|
|
128
149
|
var _a;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
// Negotiated wire: a flat arrival is the legacy v2 dialect (from a
|
|
151
|
+
// v4.8.x wallet answering a flat request) and is already the shape the
|
|
152
|
+
// pipeline consumes. Wrapped arrivals carry Tezos payloads that are
|
|
153
|
+
// normalized back to those same flat shapes — the wire dialect stays
|
|
154
|
+
// invisible to integrators. Non-Tezos wrapped payloads keep the
|
|
155
|
+
// pass-through of the generic permissionRequest/request API.
|
|
156
|
+
const isWrapped = (0, octez_connect_core_1.usesWrappedMessages)(wireMessage.version);
|
|
157
|
+
// Issue #33: a V3-versioned message can arrive without its wrapped payload.
|
|
158
|
+
// Drop it safely instead of dereferencing an undefined payload, which would
|
|
159
|
+
// throw an unhandled rejection inside the transport subscription callback.
|
|
160
|
+
if (isWrapped && !wireMessage.message) {
|
|
161
|
+
logger.log('handleResponse', 'Received wrapped message with undefined payload; dropping', wireMessage);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const normalized = isWrapped
|
|
165
|
+
? this.normalizeWrappedTezosMessage(wireMessage)
|
|
166
|
+
: wireMessage;
|
|
167
|
+
const message = normalized !== null && normalized !== void 0 ? normalized : wireMessage;
|
|
168
|
+
const typedMessage = normalized !== null && normalized !== void 0 ? normalized : wireMessage.message;
|
|
169
|
+
let appMetadata = normalized
|
|
170
|
+
? typedMessage.appMetadata
|
|
171
|
+
: (_a = typedMessage.blockchainData) === null || _a === void 0 ? void 0 : _a.appMetadata;
|
|
172
|
+
if (!appMetadata && !normalized) {
|
|
136
173
|
const storedMetadata = yield Promise.all([
|
|
137
174
|
this.storage.get(octez_connect_types_1.StorageKey.TRANSPORT_P2P_PEERS_DAPP),
|
|
138
175
|
this.storage.get(octez_connect_types_1.StorageKey.TRANSPORT_WALLETCONNECT_PEERS_DAPP),
|
|
@@ -153,10 +190,15 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
153
190
|
}
|
|
154
191
|
}
|
|
155
192
|
if (this.openRequestsOtherTabs.has(message.id)) {
|
|
193
|
+
// Relay the ORIGINAL wrapped envelope, not the normalized flat
|
|
194
|
+
// message: the receiving tab funnels this straight back into its own
|
|
195
|
+
// handleResponse, whose wrapped-only contract would drop a flat
|
|
196
|
+
// arrival (version '4' with no `.message` payload) and leave the
|
|
197
|
+
// other tab's request pending forever.
|
|
156
198
|
this.multiTabChannel.postMessage({
|
|
157
199
|
type: 'RESPONSE',
|
|
158
200
|
data: {
|
|
159
|
-
message,
|
|
201
|
+
message: wireMessage,
|
|
160
202
|
connectionInfo
|
|
161
203
|
},
|
|
162
204
|
id: message.id
|
|
@@ -278,7 +320,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
278
320
|
}
|
|
279
321
|
}))
|
|
280
322
|
.catch((err) => logger.error(err.message));
|
|
281
|
-
this.sendMetrics(
|
|
323
|
+
this.sendMetrics(`enable-metrics?${this.addQueryParam('version', octez_connect_core_1.SDK_VERSION)}`, undefined, (res) => {
|
|
282
324
|
if (!res.ok) {
|
|
283
325
|
res.status === 426
|
|
284
326
|
? console.error('Metrics are no longer supported for this version, please upgrade.')
|
|
@@ -402,22 +444,32 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
402
444
|
yield this.addListener(this.postMessageTransport);
|
|
403
445
|
this.p2pTransport = new DappP2PTransport_1.DappP2PTransport(this.name, keyPair, this.storage, this.matrixNodes, this.iconUrl, this.appUrl);
|
|
404
446
|
yield this.addListener(this.p2pTransport);
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
447
|
+
// WalletConnect is opt-in (#32): skip building/listening the transport when
|
|
448
|
+
// no walletConnectOptions were provided or it was explicitly disabled.
|
|
449
|
+
if (this.isWalletConnectEnabled) {
|
|
450
|
+
const wcOptions = {
|
|
451
|
+
projectId: this.wcProjectId,
|
|
452
|
+
relayUrl: this.wcRelayUrl,
|
|
453
|
+
metadata: {
|
|
454
|
+
name: this.name,
|
|
455
|
+
description: (_a = this.description) !== null && _a !== void 0 ? _a : '',
|
|
456
|
+
url: (_b = this.appUrl) !== null && _b !== void 0 ? _b : '',
|
|
457
|
+
icons: this.iconUrl ? [this.iconUrl] : []
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
this.walletConnectTransport = new DappWalletConnectTransport_1.DappWalletConnectTransport(this.name, keyPair, this.storage, {
|
|
461
|
+
network: this.network.type,
|
|
462
|
+
opts: wcOptions
|
|
463
|
+
}, this.checkIfBCLeaderExists.bind(this));
|
|
464
|
+
// Apply proposal networks requested before the transport existed
|
|
465
|
+
// (requestPermissions runs before init creates the transport).
|
|
466
|
+
if (this.pendingWcProposalNetworks) {
|
|
467
|
+
this.walletConnectTransport.setProposalNetworks(this.pendingWcProposalNetworks);
|
|
468
|
+
this.pendingWcProposalNetworks = undefined;
|
|
413
469
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
opts: wcOptions
|
|
418
|
-
}, this.checkIfBCLeaderExists.bind(this));
|
|
419
|
-
this.initEvents();
|
|
420
|
-
yield this.addListener(this.walletConnectTransport);
|
|
470
|
+
this.initEvents();
|
|
471
|
+
yield this.addListener(this.walletConnectTransport);
|
|
472
|
+
}
|
|
421
473
|
});
|
|
422
474
|
}
|
|
423
475
|
initEvents() {
|
|
@@ -531,7 +583,9 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
531
583
|
}
|
|
532
584
|
};
|
|
533
585
|
yield this.initInternalTransports();
|
|
534
|
-
if (!this.postMessageTransport ||
|
|
586
|
+
if (!this.postMessageTransport ||
|
|
587
|
+
!this.p2pTransport ||
|
|
588
|
+
(this.isWalletConnectEnabled && !this.walletConnectTransport)) {
|
|
535
589
|
return;
|
|
536
590
|
}
|
|
537
591
|
this.postMessageTransport.connect().then().catch(console.error);
|
|
@@ -544,9 +598,20 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
544
598
|
else if (origin === octez_connect_types_1.Origin.P2P) {
|
|
545
599
|
resolve(yield _super.init.call(this, this.p2pTransport));
|
|
546
600
|
}
|
|
547
|
-
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT) {
|
|
601
|
+
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT && this.walletConnectTransport) {
|
|
548
602
|
resolve(yield _super.init.call(this, this.walletConnectTransport));
|
|
549
603
|
}
|
|
604
|
+
else {
|
|
605
|
+
// The persisted active account was paired over WalletConnect but WC
|
|
606
|
+
// is now opt-out/disabled (#32), so there is no matching transport to
|
|
607
|
+
// restore. Without this branch none of the conditions above call
|
|
608
|
+
// resolve() and the init promise created above never settles, so
|
|
609
|
+
// init() (and every later call awaiting it) hangs forever. Resolve on
|
|
610
|
+
// the always-available P2P transport so the SDK stays usable and the
|
|
611
|
+
// stale WC account can be re-paired.
|
|
612
|
+
logger.warn('init', 'Active account was paired over WalletConnect but WC is disabled; falling back to the P2P transport');
|
|
613
|
+
resolve(yield _super.init.call(this, this.p2pTransport));
|
|
614
|
+
}
|
|
550
615
|
}
|
|
551
616
|
else {
|
|
552
617
|
const p2pTransport = this.p2pTransport;
|
|
@@ -582,8 +647,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
582
647
|
resolve(octez_connect_types_1.TransportType.P2P);
|
|
583
648
|
})
|
|
584
649
|
.catch(console.error);
|
|
585
|
-
walletConnectTransport
|
|
586
|
-
.listenForNewPeer((peer) => {
|
|
650
|
+
walletConnectTransport === null || walletConnectTransport === void 0 ? void 0 : walletConnectTransport.listenForNewPeer((peer) => {
|
|
587
651
|
logger.log('init', 'walletconnect transport peer connected', peer);
|
|
588
652
|
this.analytics.track('event', 'DAppClient', 'WalletConnect Wallet connected', {
|
|
589
653
|
peerName: peer.name
|
|
@@ -595,8 +659,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
595
659
|
this.setTransport(this.walletConnectTransport).catch(console.error);
|
|
596
660
|
stopListening();
|
|
597
661
|
resolve(octez_connect_types_1.TransportType.WALLETCONNECT);
|
|
598
|
-
})
|
|
599
|
-
.catch(console.error);
|
|
662
|
+
}).catch(console.error);
|
|
600
663
|
octez_connect_transport_postmessage_1.PostMessageTransport.getAvailableExtensions()
|
|
601
664
|
.then((extensions) => __awaiter(this, void 0, void 0, function* () {
|
|
602
665
|
this.analytics.track('event', 'DAppClient', 'Extensions detected', { extensions });
|
|
@@ -612,7 +675,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
612
675
|
yield Promise.all([
|
|
613
676
|
postMessageTransport.disconnect(),
|
|
614
677
|
// p2pTransport.disconnect(), do not abort connection manually
|
|
615
|
-
walletConnectTransport.disconnect()
|
|
678
|
+
walletConnectTransport === null || walletConnectTransport === void 0 ? void 0 : walletConnectTransport.disconnect()
|
|
616
679
|
]);
|
|
617
680
|
this.postMessageTransport = this.walletConnectTransport = this.p2pTransport = undefined;
|
|
618
681
|
this._activeAccount.isResolved() && this.clearActiveAccount();
|
|
@@ -647,7 +710,10 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
647
710
|
resolve(yield serializer.serialize(yield p2pTransport.getPairingRequestInfo()));
|
|
648
711
|
}));
|
|
649
712
|
const walletConnectPeerInfo = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
650
|
-
|
|
713
|
+
// When WC is disabled there is no transport to pair through (#32).
|
|
714
|
+
resolve(walletConnectTransport
|
|
715
|
+
? (yield walletConnectTransport.getPairingRequestInfo()).uri
|
|
716
|
+
: '');
|
|
651
717
|
}));
|
|
652
718
|
const postmessagePeerInfo = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
653
719
|
resolve(yield serializer.serialize(yield postMessageTransport.getPairingRequestInfo()));
|
|
@@ -713,7 +779,6 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
713
779
|
*/
|
|
714
780
|
setActiveAccount(account) {
|
|
715
781
|
return __awaiter(this, void 0, void 0, function* () {
|
|
716
|
-
var _a;
|
|
717
782
|
if (!this.isGetActiveAccountHandled) {
|
|
718
783
|
console.warn(`An active account has been received, but no active subscription was found for BeaconEvent.ACTIVE_ACCOUNT_SET.
|
|
719
784
|
For more information, visit: https://octez-connect.tezos.com/guides/migration-guide`);
|
|
@@ -753,7 +818,9 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
753
818
|
errorType: octez_connect_types_1.BeaconErrorType.ABORTED_ERROR,
|
|
754
819
|
id,
|
|
755
820
|
senderId: '',
|
|
756
|
-
|
|
821
|
+
// SDK-synthesized rejection consumed in-process (never hits the
|
|
822
|
+
// wire); stamped with the wrapped baseline for consistency.
|
|
823
|
+
version: (0, octez_connect_core_1.negotiateEnvelopeVersion)(undefined)
|
|
757
824
|
});
|
|
758
825
|
});
|
|
759
826
|
this.openRequests.clear();
|
|
@@ -784,9 +851,18 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
784
851
|
else if (origin === octez_connect_types_1.Origin.P2P) {
|
|
785
852
|
yield this.setTransport(this.p2pTransport);
|
|
786
853
|
}
|
|
787
|
-
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT) {
|
|
854
|
+
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT && this.walletConnectTransport) {
|
|
788
855
|
yield this.setTransport(this.walletConnectTransport);
|
|
789
|
-
|
|
856
|
+
this.walletConnectTransport.forceUpdate('INIT');
|
|
857
|
+
}
|
|
858
|
+
else if (origin === octez_connect_types_1.Origin.WALLETCONNECT) {
|
|
859
|
+
// WalletConnect is opt-out/disabled (#32) but this persisted account was
|
|
860
|
+
// paired over WC. There is no WC transport to bind; setting the transport
|
|
861
|
+
// to `undefined` would leave the client unable to send any request. Fall
|
|
862
|
+
// back to the always-available P2P transport so the SDK stays usable
|
|
863
|
+
// (the stale WC account can be re-paired).
|
|
864
|
+
logger.warn('setActiveAccount', 'Active account was paired over WalletConnect but WC is disabled; falling back to the P2P transport');
|
|
865
|
+
yield this.setTransport(this.p2pTransport);
|
|
790
866
|
}
|
|
791
867
|
if (this._transport.isResolved()) {
|
|
792
868
|
const transport = yield this.transport;
|
|
@@ -867,7 +943,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
867
943
|
});
|
|
868
944
|
}
|
|
869
945
|
addQueryParam(paramName, paramValue) {
|
|
870
|
-
return paramName
|
|
946
|
+
return `${paramName}=${paramValue}`;
|
|
871
947
|
}
|
|
872
948
|
buildPayload(action, status) {
|
|
873
949
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1080,6 +1156,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1080
1156
|
}
|
|
1081
1157
|
permissionRequest(input) {
|
|
1082
1158
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1159
|
+
var _a;
|
|
1083
1160
|
logger.log('permissionRequest', input);
|
|
1084
1161
|
const blockchain = this.blockchains.get(input.blockchainIdentifier);
|
|
1085
1162
|
if (!blockchain) {
|
|
@@ -1094,21 +1171,32 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1094
1171
|
logger.time(false, logId);
|
|
1095
1172
|
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'start'));
|
|
1096
1173
|
logger.log('RESPONSE V3', response, connectionInfo);
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1174
|
+
// The version stamp lives on the wrapper envelope, not the inner payload;
|
|
1175
|
+
// reading response.message.version would always miss and collapse to '0',
|
|
1176
|
+
// misrouting v4 responses when no peer is persisted yet.
|
|
1177
|
+
const walletPeerV3 = yield this.getPeer();
|
|
1178
|
+
const walletPeerVersionV3 = (_a = walletPeerV3 === null || walletPeerV3 === void 0 ? void 0 : walletPeerV3.version) !== null && _a !== void 0 ? _a : response.version;
|
|
1179
|
+
const partialAccountInfos = yield blockchain.getAccountInfosFromPermissionResponse(response.message, walletPeerVersionV3);
|
|
1180
|
+
const blockchainDataScopes = response.message.blockchainData.scopes;
|
|
1181
|
+
const accountInfos = partialAccountInfos.map((p) => ({
|
|
1182
|
+
accountIdentifier: p.accountId,
|
|
1100
1183
|
senderId: response.senderId,
|
|
1101
1184
|
origin: {
|
|
1102
1185
|
type: connectionInfo.origin,
|
|
1103
1186
|
id: connectionInfo.id
|
|
1104
1187
|
},
|
|
1105
|
-
address:
|
|
1106
|
-
publicKey:
|
|
1107
|
-
|
|
1188
|
+
address: p.address,
|
|
1189
|
+
publicKey: p.publicKey,
|
|
1190
|
+
network: p.network,
|
|
1191
|
+
scopes: blockchainDataScopes !== null && blockchainDataScopes !== void 0 ? blockchainDataScopes : p.scopes,
|
|
1108
1192
|
connectedAt: new Date().getTime(),
|
|
1109
1193
|
chainData: response.message.blockchainData
|
|
1110
|
-
};
|
|
1111
|
-
yield this.accountManager.
|
|
1194
|
+
}));
|
|
1195
|
+
yield this.accountManager.addAccounts(accountInfos);
|
|
1196
|
+
const accountInfo = accountInfos[0];
|
|
1197
|
+
if (!accountInfo) {
|
|
1198
|
+
throw new Error(EMPTY_PERMISSION_ACCOUNTS_MESSAGE);
|
|
1199
|
+
}
|
|
1112
1200
|
yield this.setActiveAccount(accountInfo);
|
|
1113
1201
|
yield blockchain.handleResponse({
|
|
1114
1202
|
request,
|
|
@@ -1121,7 +1209,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1121
1209
|
yield this.notifySuccess(request, {
|
|
1122
1210
|
account: accountInfo,
|
|
1123
1211
|
output: {
|
|
1124
|
-
address:
|
|
1212
|
+
address: accountInfo.address,
|
|
1125
1213
|
network: { type: 'substrate' },
|
|
1126
1214
|
scopes: []
|
|
1127
1215
|
},
|
|
@@ -1178,6 +1266,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1178
1266
|
*/
|
|
1179
1267
|
requestPermissions(input) {
|
|
1180
1268
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1269
|
+
var _a, _b;
|
|
1181
1270
|
if (input === null || input === void 0 ? void 0 : input.network) {
|
|
1182
1271
|
throw new Error('[BEACON] the "network" property is no longer accepted in input. Please provide it when instantiating DAppClient.');
|
|
1183
1272
|
}
|
|
@@ -1189,6 +1278,39 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1189
1278
|
? input.scopes
|
|
1190
1279
|
: [octez_connect_types_1.PermissionScope.OPERATION_REQUEST, octez_connect_types_1.PermissionScope.SIGN]
|
|
1191
1280
|
};
|
|
1281
|
+
// Dedupe by the normalized CAIP-2 chainId so equivalent input entries
|
|
1282
|
+
// ('NetX…' and 'tezos:NetX…') collapse to one canonical wire entry.
|
|
1283
|
+
if ((input === null || input === void 0 ? void 0 : input.networks) && input.networks.length > 0) {
|
|
1284
|
+
const dedupedNetworks = Array.from(new Map(input.networks.map((n) => {
|
|
1285
|
+
const chainId = (0, octez_connect_core_1.normalizeTezosCaip2)(n.chainId);
|
|
1286
|
+
return [chainId, Object.assign(Object.assign({}, n), { chainId })];
|
|
1287
|
+
})).values());
|
|
1288
|
+
request.networks = dedupedNetworks;
|
|
1289
|
+
// Multi-network over WalletConnect travels via the session proposal,
|
|
1290
|
+
// not the wire payload (WC peers have no beacon version handshake).
|
|
1291
|
+
// Map each requested chain id to its named network for the proposal;
|
|
1292
|
+
// ids without a static genesis mapping are skipped here (the
|
|
1293
|
+
// NetworksUnsupportedBeaconError guard above reports them when the
|
|
1294
|
+
// dApp opted into requiredMinimumVersion '4').
|
|
1295
|
+
const proposalNetworkTypes = [];
|
|
1296
|
+
for (const { chainId } of dedupedNetworks) {
|
|
1297
|
+
const networkType = (0, octez_connect_core_1.networkTypeFromTezosCaip2)(chainId);
|
|
1298
|
+
if (networkType === undefined) {
|
|
1299
|
+
logger.debug('requestPermissions', `No static network mapping for "${chainId}"; excluded from the WalletConnect proposal`);
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
proposalNetworkTypes.push(networkType);
|
|
1303
|
+
}
|
|
1304
|
+
if (this.walletConnectTransport) {
|
|
1305
|
+
this.walletConnectTransport.setProposalNetworks(proposalNetworkTypes);
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
// The WalletConnect transport is created lazily inside init() (run
|
|
1309
|
+
// by makeRequest below, before the pairing proposal is built); stash
|
|
1310
|
+
// the networks and apply them right after creation.
|
|
1311
|
+
this.pendingWcProposalNetworks = proposalNetworkTypes;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1192
1314
|
this.analytics.track('event', 'DAppClient', 'Permission requested');
|
|
1193
1315
|
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'start'));
|
|
1194
1316
|
const logId = `makeRequest ${Date.now()}`;
|
|
@@ -1201,10 +1323,60 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1201
1323
|
this.sendMetrics('performance-metrics/save', yield this.buildPayload('connect', 'success'));
|
|
1202
1324
|
logger.log('requestPermissions', '######## MESSAGE #######');
|
|
1203
1325
|
logger.log('requestPermissions', message);
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1326
|
+
// walletPeer.version is the negotiated pairing version; fall back to the
|
|
1327
|
+
// response envelope version when no peer is persisted yet.
|
|
1328
|
+
const walletPeer = yield this.getPeer();
|
|
1329
|
+
const walletPeerVersion = (_a = walletPeer === null || walletPeer === void 0 ? void 0 : walletPeer.version) !== null && _a !== void 0 ? _a : message.version;
|
|
1330
|
+
// Gate the freshly-paired wallet against the dApp's required minimum (a
|
|
1331
|
+
// no-op under the default, permissive minimum). Throws
|
|
1332
|
+
// VersionUnsupportedBeaconError when the wallet is too old.
|
|
1333
|
+
this.assertWalletVersionMeetsMinimum(walletPeerVersion);
|
|
1334
|
+
const isV4Session = (0, octez_connect_core_1.isMultiNetworkVersion)(walletPeerVersion);
|
|
1335
|
+
const messageAccounts = message.accounts;
|
|
1336
|
+
const multiNetworkAccounts = isV4Session &&
|
|
1337
|
+
messageAccounts &&
|
|
1338
|
+
typeof messageAccounts === 'object' &&
|
|
1339
|
+
!Array.isArray(messageAccounts)
|
|
1340
|
+
? messageAccounts
|
|
1341
|
+
: null;
|
|
1342
|
+
let accountInfo;
|
|
1343
|
+
if (isV4Session) {
|
|
1344
|
+
const requestedNetworks = ((_b = request.networks) !== null && _b !== void 0 ? _b : []).map((n) => (0, octez_connect_core_1.normalizeTezosCaip2)(n.chainId));
|
|
1345
|
+
const servedChainIds = multiNetworkAccounts
|
|
1346
|
+
? Object.keys(multiNetworkAccounts).map(octez_connect_core_1.normalizeTezosCaip2)
|
|
1347
|
+
: [];
|
|
1348
|
+
const isMinimumVersionV4OrHigher = (0, octez_connect_core_1.isMultiNetworkVersion)(this.requiredMinimumVersion);
|
|
1349
|
+
// Reject silently-degraded responses: a v4 session with >=2 networks
|
|
1350
|
+
// requested but no accounts fanout returned.
|
|
1351
|
+
if (requestedNetworks.length >= 2 && isMinimumVersionV4OrHigher) {
|
|
1352
|
+
const missing = requestedNetworks.filter((c) => !servedChainIds.includes(c));
|
|
1353
|
+
if (missing.length > 0) {
|
|
1354
|
+
throw new octez_connect_core_1.NetworksUnsupportedBeaconError({
|
|
1355
|
+
requestedNetworks,
|
|
1356
|
+
unsupportedNetworks: missing
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (isV4Session && multiNetworkAccounts) {
|
|
1362
|
+
const builtAccounts = yield this.buildAccountInfosFromV4Fanout(message, multiNetworkAccounts, walletPeerVersion !== null && walletPeerVersion !== void 0 ? walletPeerVersion : '0', connectionInfo);
|
|
1363
|
+
yield this.accountManager.addAccounts(builtAccounts);
|
|
1364
|
+
accountInfo = builtAccounts[0];
|
|
1365
|
+
if (!accountInfo) {
|
|
1366
|
+
throw new Error(EMPTY_PERMISSION_ACCOUNTS_MESSAGE);
|
|
1367
|
+
}
|
|
1368
|
+
yield this.setActiveAccount(accountInfo);
|
|
1369
|
+
logger.log('requestPermissions', '######## MULTI-NETWORK ACCOUNTS #######', builtAccounts.length);
|
|
1370
|
+
}
|
|
1371
|
+
else {
|
|
1372
|
+
accountInfo = yield this.onNewAccount(message, connectionInfo);
|
|
1373
|
+
logger.log('requestPermissions', '######## ACCOUNT INFO #######');
|
|
1374
|
+
logger.log('requestPermissions', JSON.stringify(accountInfo));
|
|
1375
|
+
yield this.accountManager.addAccount(accountInfo);
|
|
1376
|
+
}
|
|
1377
|
+
if (!accountInfo) {
|
|
1378
|
+
throw new Error(EMPTY_PERMISSION_ACCOUNTS_MESSAGE);
|
|
1379
|
+
}
|
|
1208
1380
|
const output = Object.assign(Object.assign({}, message), { walletKey: accountInfo.walletKey, address: accountInfo.address, accountInfo });
|
|
1209
1381
|
yield this.notifySuccess(request, {
|
|
1210
1382
|
account: accountInfo,
|
|
@@ -1230,11 +1402,13 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1230
1402
|
requestProofOfEventChallenge(input) {
|
|
1231
1403
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1232
1404
|
const activeAccount = yield this.getActiveAccount();
|
|
1233
|
-
if (!activeAccount)
|
|
1405
|
+
if (!activeAccount) {
|
|
1234
1406
|
throw new Error('Please request permissions before doing a proof of event challenge');
|
|
1407
|
+
}
|
|
1235
1408
|
if (activeAccount.walletType !== 'abstracted_account' &&
|
|
1236
|
-
activeAccount.verificationType !== 'proof_of_event')
|
|
1409
|
+
activeAccount.verificationType !== 'proof_of_event') {
|
|
1237
1410
|
throw new Error('This wallet is not an abstracted account and thus cannot perform proof of event');
|
|
1411
|
+
}
|
|
1238
1412
|
const request = {
|
|
1239
1413
|
type: octez_connect_types_1.BeaconMessageType.ProofOfEventChallengeRequest,
|
|
1240
1414
|
contractAddress: activeAccount.address,
|
|
@@ -1271,8 +1445,9 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1271
1445
|
requestSimulatedProofOfEventChallenge(input) {
|
|
1272
1446
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1273
1447
|
const activeAccount = yield this.getActiveAccount();
|
|
1274
|
-
if (!activeAccount)
|
|
1448
|
+
if (!activeAccount) {
|
|
1275
1449
|
throw new Error('Please request permissions before doing a proof of event challenge');
|
|
1450
|
+
}
|
|
1276
1451
|
if (activeAccount.walletType !== 'abstracted_account' &&
|
|
1277
1452
|
activeAccount.verificationType !== 'proof_of_event') {
|
|
1278
1453
|
throw new Error('This wallet is not an abstracted account and thus cannot perform a simulated proof of event');
|
|
@@ -1422,9 +1597,10 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1422
1597
|
if (!activeAccount) {
|
|
1423
1598
|
throw yield this.sendInternalError('No active account!');
|
|
1424
1599
|
}
|
|
1600
|
+
const resolvedNetwork = yield this.resolveOperationNetwork(input.network, activeAccount);
|
|
1425
1601
|
const request = {
|
|
1426
1602
|
type: octez_connect_types_1.BeaconMessageType.OperationRequest,
|
|
1427
|
-
network:
|
|
1603
|
+
network: resolvedNetwork,
|
|
1428
1604
|
operationDetails: input.operationDetails,
|
|
1429
1605
|
sourceAddress: activeAccount.address || ''
|
|
1430
1606
|
};
|
|
@@ -1624,7 +1800,10 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1624
1800
|
// if the account we requested is not available, we remove it locally
|
|
1625
1801
|
let accountInfo;
|
|
1626
1802
|
if (operationRequest.sourceAddress && operationRequest.network) {
|
|
1627
|
-
const
|
|
1803
|
+
const networkForId = typeof operationRequest.network === 'string'
|
|
1804
|
+
? (0, octez_connect_core_1.networkFromTezosCaip2)((0, octez_connect_core_1.normalizeTezosCaip2)(operationRequest.network))
|
|
1805
|
+
: operationRequest.network;
|
|
1806
|
+
const accountIdentifier = yield (0, octez_connect_core_1.getAccountIdentifier)(operationRequest.sourceAddress, networkForId);
|
|
1628
1807
|
accountInfo = yield this.getAccount(accountIdentifier);
|
|
1629
1808
|
if (accountInfo) {
|
|
1630
1809
|
yield this.removeAccount(accountInfo.accountIdentifier);
|
|
@@ -1736,14 +1915,18 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1736
1915
|
web: { app: browser, type: 'web' }
|
|
1737
1916
|
};
|
|
1738
1917
|
const defaultType = () => {
|
|
1739
|
-
if ((0, octez_connect_ui_1.isBrowser)(window) && browser)
|
|
1918
|
+
if ((0, octez_connect_ui_1.isBrowser)(window) && browser) {
|
|
1740
1919
|
return { app: browser, type: 'web' };
|
|
1741
|
-
|
|
1920
|
+
}
|
|
1921
|
+
if ((0, octez_connect_ui_1.isDesktop)(window) && desktop) {
|
|
1742
1922
|
return { app: desktop, type: 'desktop' };
|
|
1743
|
-
|
|
1923
|
+
}
|
|
1924
|
+
if ((0, octez_connect_ui_1.isBrowser)(window) && extension) {
|
|
1744
1925
|
return { app: extension, type: 'extension' };
|
|
1745
|
-
|
|
1926
|
+
}
|
|
1927
|
+
if (mobile) {
|
|
1746
1928
|
return { app: mobile, type: 'mobile' };
|
|
1929
|
+
}
|
|
1747
1930
|
return { app: undefined, type: undefined };
|
|
1748
1931
|
};
|
|
1749
1932
|
const { app, type } = storageWallet ? appTypeMap[storageWallet.type] : defaultType();
|
|
@@ -1765,6 +1948,85 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1765
1948
|
return walletInfo;
|
|
1766
1949
|
});
|
|
1767
1950
|
}
|
|
1951
|
+
// Throws VersionUnsupportedBeaconError when a wallet that reported a version
|
|
1952
|
+
// is below requiredMinimumVersion (or reports a malformed one). A peer that
|
|
1953
|
+
// never reported a version (legacy pairing predating versioning) is treated
|
|
1954
|
+
// as unknown and allowed through, so raising the minimum never retroactively
|
|
1955
|
+
// breaks an already-paired session on a pure read.
|
|
1956
|
+
assertWalletVersionMeetsMinimum(walletVersion) {
|
|
1957
|
+
if (walletVersion === undefined) {
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
const min = this.requiredMinimumVersion;
|
|
1961
|
+
let cmp;
|
|
1962
|
+
try {
|
|
1963
|
+
cmp = (0, octez_connect_core_1.compareBeaconVersion)(walletVersion, min);
|
|
1964
|
+
}
|
|
1965
|
+
catch (_a) {
|
|
1966
|
+
// A present-but-malformed version cannot be shown to meet the minimum.
|
|
1967
|
+
throw new octez_connect_core_1.VersionUnsupportedBeaconError(min, walletVersion);
|
|
1968
|
+
}
|
|
1969
|
+
if (cmp < 0) {
|
|
1970
|
+
throw new octez_connect_core_1.VersionUnsupportedBeaconError(min, walletVersion);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
// Distinct CAIP-2 chain ids across all session accounts. Reads the account
|
|
1974
|
+
// store, so callers should avoid it on paths that can decide without it.
|
|
1975
|
+
getSessionChainIds() {
|
|
1976
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1977
|
+
const allAccounts = yield this.accountManager.getAccounts();
|
|
1978
|
+
return Array.from(new Set(allAccounts
|
|
1979
|
+
.map((a) => { var _a; return (_a = a.network) === null || _a === void 0 ? void 0 : _a.chainId; })
|
|
1980
|
+
.filter((c) => typeof c === 'string' && c.length > 0)));
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
// Resolves the network for an outgoing operation. Returns the supplied
|
|
1984
|
+
// CAIP-2 string (validated and confirmed in-session), or the active
|
|
1985
|
+
// account's Network when there is no ambiguity. Throws on a multi-network
|
|
1986
|
+
// session when no network is supplied.
|
|
1987
|
+
resolveOperationNetwork(inputNetwork, activeAccount) {
|
|
1988
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1989
|
+
var _a;
|
|
1990
|
+
if (inputNetwork) {
|
|
1991
|
+
if (!(0, octez_connect_core_1.isValidTezosCaip2)(inputNetwork)) {
|
|
1992
|
+
throw new octez_connect_core_1.NetworksUnsupportedBeaconError({
|
|
1993
|
+
requestedNetworks: [inputNetwork],
|
|
1994
|
+
unsupportedNetworks: [inputNetwork],
|
|
1995
|
+
customMessage: `Malformed CAIP-2 string: "${inputNetwork}". Expected format: tezos:<NetID>.`
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
// Fast path: the active account is already on the requested network, so
|
|
1999
|
+
// it is trivially in-session — skip the account-store read.
|
|
2000
|
+
if (inputNetwork === ((_a = activeAccount.network) === null || _a === void 0 ? void 0 : _a.chainId)) {
|
|
2001
|
+
return inputNetwork;
|
|
2002
|
+
}
|
|
2003
|
+
const knownChainIds = yield this.getSessionChainIds();
|
|
2004
|
+
// Tolerate pre-multi-network sessions with no recorded chain ids: such a
|
|
2005
|
+
// wallet (v2/v3) expects a Network object, not a bare CAIP-2 string it
|
|
2006
|
+
// cannot interpret, so return the active account's Network rather than the
|
|
2007
|
+
// string. (There is exactly one network in a session with no chain ids.)
|
|
2008
|
+
if (knownChainIds.length === 0) {
|
|
2009
|
+
return activeAccount.network || this.network;
|
|
2010
|
+
}
|
|
2011
|
+
if (!knownChainIds.includes(inputNetwork)) {
|
|
2012
|
+
throw new octez_connect_core_1.NetworksUnsupportedBeaconError({
|
|
2013
|
+
requestedNetworks: [inputNetwork],
|
|
2014
|
+
unsupportedNetworks: [inputNetwork]
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
return inputNetwork;
|
|
2018
|
+
}
|
|
2019
|
+
// No explicit network: a session spanning more than one chain is ambiguous.
|
|
2020
|
+
const sessionChainIds = yield this.getSessionChainIds();
|
|
2021
|
+
if (sessionChainIds.length > 1) {
|
|
2022
|
+
throw new octez_connect_core_1.NetworksUnsupportedBeaconError({
|
|
2023
|
+
requestedNetworks: [],
|
|
2024
|
+
unsupportedNetworks: []
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
return activeAccount.network || this.network;
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
1768
2030
|
getPeer(account) {
|
|
1769
2031
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1770
2032
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -1786,12 +2048,84 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1786
2048
|
peer = yield this._activePeer.promise;
|
|
1787
2049
|
logger.log('getPeer', 'Active peer', peer);
|
|
1788
2050
|
}
|
|
2051
|
+
// NB: getPeer() is a pure read used during session resumption, error
|
|
2052
|
+
// handling and wallet-info lookups, so it must not throw on an
|
|
2053
|
+
// under-minimum peer (that would wipe a resumed session or mask the real
|
|
2054
|
+
// wallet error). The version gate is enforced at the pairing response and
|
|
2055
|
+
// at request-send time instead — see assertWalletVersionMeetsMinimum.
|
|
1789
2056
|
return peer;
|
|
1790
2057
|
});
|
|
1791
2058
|
}
|
|
2059
|
+
// Build the wrapped Tezos wire message for a flat request input. The v4
|
|
2060
|
+
// multi-network `networks` field is stripped for peers negotiated below
|
|
2061
|
+
// v4 — a v3 peer must never see v4 payload fields.
|
|
2062
|
+
wrapTezosRequest(flat, envelope, account) {
|
|
2063
|
+
var _a;
|
|
2064
|
+
if (flat.type === octez_connect_types_1.BeaconMessageType.PermissionRequest) {
|
|
2065
|
+
const blockchainData = Object.assign({}, flat);
|
|
2066
|
+
delete blockchainData.type;
|
|
2067
|
+
if (!(0, octez_connect_core_1.isMultiNetworkVersion)(envelope.version)) {
|
|
2068
|
+
delete blockchainData.networks;
|
|
2069
|
+
}
|
|
2070
|
+
return (0, octez_connect_core_1.wrapBeaconMessage)(envelope, {
|
|
2071
|
+
blockchainIdentifier: 'tezos',
|
|
2072
|
+
type: octez_connect_types_1.BeaconMessageType.PermissionRequest,
|
|
2073
|
+
blockchainData
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
const payloadMeta = DAppClient.FLAT_REQUEST_PAYLOAD_TYPES[flat.type];
|
|
2077
|
+
if (!payloadMeta) {
|
|
2078
|
+
throw new Error(`Cannot send a "${flat.type}" message: not a Tezos request type`);
|
|
2079
|
+
}
|
|
2080
|
+
const payload = Object.assign({}, flat);
|
|
2081
|
+
delete payload.type;
|
|
2082
|
+
return (0, octez_connect_core_1.wrapBeaconMessage)(envelope, {
|
|
2083
|
+
blockchainIdentifier: 'tezos',
|
|
2084
|
+
type: octez_connect_types_1.BeaconMessageType.BlockchainRequest,
|
|
2085
|
+
accountId: (_a = account === null || account === void 0 ? void 0 : account.accountIdentifier) !== null && _a !== void 0 ? _a : '',
|
|
2086
|
+
blockchainData: Object.assign({ type: payloadMeta.type, scope: payloadMeta.scope }, payload)
|
|
2087
|
+
});
|
|
2088
|
+
}
|
|
2089
|
+
// Normalize a wrapped Tezos wire message back to the flat shape the
|
|
2090
|
+
// pre-fork pipeline (request* methods, onNewAccount, integrator events)
|
|
2091
|
+
// consumes. Returns undefined for non-Tezos payloads, which keep the
|
|
2092
|
+
// wrapped pass-through of the generic permissionRequest/request API.
|
|
2093
|
+
normalizeWrappedTezosMessage(wrapper) {
|
|
2094
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2095
|
+
const inner = wrapper.message;
|
|
2096
|
+
const envelope = { id: wrapper.id, version: wrapper.version, senderId: wrapper.senderId };
|
|
2097
|
+
// Chain-agnostic control messages.
|
|
2098
|
+
if (inner.type === octez_connect_types_1.BeaconMessageType.Acknowledge || inner.type === octez_connect_types_1.BeaconMessageType.Disconnect) {
|
|
2099
|
+
return Object.assign(Object.assign({}, envelope), { type: inner.type });
|
|
2100
|
+
}
|
|
2101
|
+
if (inner.type === octez_connect_types_1.BeaconMessageType.Error) {
|
|
2102
|
+
return Object.assign(Object.assign({}, envelope), { type: octez_connect_types_1.BeaconMessageType.Error, errorType: (_b = (_a = inner.error) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : octez_connect_types_1.BeaconErrorType.UNKNOWN_ERROR, errorData: (_c = inner.error) === null || _c === void 0 ? void 0 : _c.data, description: inner.description });
|
|
2103
|
+
}
|
|
2104
|
+
if (inner.blockchainIdentifier === undefined ||
|
|
2105
|
+
!DAppClient.TEZOS_IDENTIFIERS.includes(inner.blockchainIdentifier)) {
|
|
2106
|
+
return undefined;
|
|
2107
|
+
}
|
|
2108
|
+
if (inner.type === octez_connect_types_1.BeaconMessageType.PermissionResponse ||
|
|
2109
|
+
inner.type === octez_connect_types_1.BeaconMessageType.ChangeAccountRequest) {
|
|
2110
|
+
return Object.assign(Object.assign(Object.assign({}, envelope), { type: inner.type }), ((_d = inner.blockchainData) !== null && _d !== void 0 ? _d : {}));
|
|
2111
|
+
}
|
|
2112
|
+
if (inner.type === octez_connect_types_1.BeaconMessageType.BlockchainResponse) {
|
|
2113
|
+
const payloadType = (_e = inner.blockchainData) === null || _e === void 0 ? void 0 : _e.type;
|
|
2114
|
+
const flatType = typeof payloadType === 'string'
|
|
2115
|
+
? DAppClient.TEZOS_PAYLOAD_TO_FLAT_TYPE[payloadType]
|
|
2116
|
+
: undefined;
|
|
2117
|
+
if (!flatType) {
|
|
2118
|
+
return undefined;
|
|
2119
|
+
}
|
|
2120
|
+
const payload = Object.assign({}, ((_f = inner.blockchainData) !== null && _f !== void 0 ? _f : {}));
|
|
2121
|
+
delete payload.type;
|
|
2122
|
+
return Object.assign(Object.assign(Object.assign({}, envelope), { type: flatType }), payload);
|
|
2123
|
+
}
|
|
2124
|
+
return undefined;
|
|
2125
|
+
}
|
|
1792
2126
|
makeRequest(requestInput, skipResponse, otherTabMessageId) {
|
|
1793
2127
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1794
|
-
var _a, _b, _c, _d;
|
|
2128
|
+
var _a, _b, _c, _d, _e;
|
|
1795
2129
|
const messageId = otherTabMessageId !== null && otherTabMessageId !== void 0 ? otherTabMessageId : (yield (0, octez_connect_utils_1.generateGUID)());
|
|
1796
2130
|
if (this._initPromise && this.isInitPending) {
|
|
1797
2131
|
if (this._initPromiseReject) {
|
|
@@ -1823,25 +2157,44 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1823
2157
|
if (!this.beaconId) {
|
|
1824
2158
|
throw yield this.sendInternalError('octez.connect ID not defined');
|
|
1825
2159
|
}
|
|
1826
|
-
const
|
|
2160
|
+
const account = yield this.getActiveAccount();
|
|
2161
|
+
const peer = yield this.getPeer(account);
|
|
2162
|
+
// Enforce the dApp's required minimum before a request leaves the SDK.
|
|
2163
|
+
// No-op under the default (permissive) minimum; otherwise rejects an
|
|
2164
|
+
// under-minimum wallet with VersionUnsupportedBeaconError.
|
|
2165
|
+
this.assertWalletVersionMeetsMinimum(peer === null || peer === void 0 ? void 0 : peer.version);
|
|
2166
|
+
// The wire dialect is negotiated per peer — min(peer.version,
|
|
2167
|
+
// BEACON_VERSION), floor '2'. A wrapped-capable peer (>= 3) receives the
|
|
2168
|
+
// flat requestInput (the unchanged public shape) mapped onto the wrapped
|
|
2169
|
+
// Tezos payload; a legacy peer receives the flat v2 message it has
|
|
2170
|
+
// always spoken. Integrators never see either dialect.
|
|
2171
|
+
const negotiatedVersion = (0, octez_connect_core_1.negotiateEnvelopeVersion)(peer === null || peer === void 0 ? void 0 : peer.version);
|
|
2172
|
+
const requestSenderId = yield (0, octez_connect_core_1.getSenderId)(yield this.beaconId);
|
|
2173
|
+
let request;
|
|
2174
|
+
if ((0, octez_connect_core_1.usesWrappedMessages)(negotiatedVersion)) {
|
|
2175
|
+
const wrapped = this.wrapTezosRequest(requestInput, { id: messageId, version: negotiatedVersion, senderId: requestSenderId }, account);
|
|
2176
|
+
yield ((_c = this.blockchains.get('tezos')) === null || _c === void 0 ? void 0 : _c.validateRequest(wrapped.message));
|
|
2177
|
+
request = wrapped;
|
|
2178
|
+
}
|
|
2179
|
+
else {
|
|
2180
|
+
request = Object.assign({ id: messageId, version: negotiatedVersion, senderId: requestSenderId }, requestInput);
|
|
2181
|
+
}
|
|
1827
2182
|
let exposed;
|
|
1828
2183
|
if (!skipResponse) {
|
|
1829
2184
|
exposed = new octez_connect_utils_1.ExposedPromise();
|
|
1830
2185
|
this.addOpenRequest(request.id, exposed);
|
|
1831
2186
|
}
|
|
1832
|
-
const account = yield this.getActiveAccount();
|
|
1833
|
-
const peer = yield this.getPeer(account);
|
|
1834
2187
|
const payload = yield new octez_connect_core_1.Serializer(this.getPeerProtocolVersion(peer)).serialize(request);
|
|
1835
2188
|
const walletInfo = yield this.getWalletInfo(peer, account);
|
|
1836
2189
|
logger.log('makeRequest', 'sending message', request);
|
|
1837
2190
|
try {
|
|
1838
2191
|
// Hook for performance measurement
|
|
1839
|
-
if ((
|
|
2192
|
+
if ((_d = window.__beaconPerf) === null || _d === void 0 ? void 0 : _d.onBeforeSend) {
|
|
1840
2193
|
window.__beaconPerf.onBeforeSend();
|
|
1841
2194
|
}
|
|
1842
2195
|
;
|
|
1843
2196
|
(yield this.transport).send(payload, peer);
|
|
1844
|
-
if (
|
|
2197
|
+
if (requestInput.type !== octez_connect_types_1.BeaconMessageType.PermissionRequest ||
|
|
1845
2198
|
(this._activeAccount.isResolved() && (yield this._activeAccount.promise))) {
|
|
1846
2199
|
this.tryToAppSwitch();
|
|
1847
2200
|
}
|
|
@@ -1868,7 +2221,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1868
2221
|
if (!otherTabMessageId) {
|
|
1869
2222
|
this.events
|
|
1870
2223
|
.emit(beacon_message_events_1.messageEvents[requestInput.type].sent, {
|
|
1871
|
-
walletInfo: Object.assign(Object.assign({}, walletInfo), { name: (
|
|
2224
|
+
walletInfo: Object.assign(Object.assign({}, walletInfo), { name: (_e = walletInfo.name) !== null && _e !== void 0 ? _e : 'Wallet' }),
|
|
1872
2225
|
extraInfo: {
|
|
1873
2226
|
resetCallback: () => __awaiter(this, void 0, void 0, function* () {
|
|
1874
2227
|
this.disconnect();
|
|
@@ -1919,16 +2272,22 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
1919
2272
|
if (!this.beaconId) {
|
|
1920
2273
|
throw yield this.sendInternalError('octez.connect ID not defined');
|
|
1921
2274
|
}
|
|
2275
|
+
const account = yield this.getActiveAccount();
|
|
2276
|
+
const peer = yield this.getPeer(account);
|
|
2277
|
+
// Enforce the dApp's required minimum before a request leaves the SDK.
|
|
2278
|
+
this.assertWalletVersionMeetsMinimum(peer === null || peer === void 0 ? void 0 : peer.version);
|
|
1922
2279
|
const request = {
|
|
1923
2280
|
id: messageId,
|
|
1924
|
-
version:
|
|
2281
|
+
// The envelope carries the version negotiated against the peer:
|
|
2282
|
+
// min(peer.version, BEACON_VERSION), floor '3'. A v3 wallet treats any
|
|
2283
|
+
// version >= 3 as a wrapped message; a v4 wallet reaches its
|
|
2284
|
+
// multi-network branch only when it declared v4 at pairing.
|
|
2285
|
+
version: (0, octez_connect_core_1.negotiateEnvelopeVersion)(peer === null || peer === void 0 ? void 0 : peer.version),
|
|
1925
2286
|
senderId: yield (0, octez_connect_core_1.getSenderId)(yield this.beaconId),
|
|
1926
2287
|
message: requestInput
|
|
1927
2288
|
};
|
|
1928
2289
|
const exposed = new octez_connect_utils_1.ExposedPromise();
|
|
1929
2290
|
this.addOpenRequest(request.id, exposed);
|
|
1930
|
-
const account = yield this.getActiveAccount();
|
|
1931
|
-
const peer = yield this.getPeer(account);
|
|
1932
2291
|
const payload = yield new octez_connect_core_1.Serializer(this.getPeerProtocolVersion(peer)).serialize(request);
|
|
1933
2292
|
const walletInfo = yield this.getWalletInfo(peer, account);
|
|
1934
2293
|
logger.log('makeRequest', 'sending message', request);
|
|
@@ -2084,7 +2443,7 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
2084
2443
|
payload
|
|
2085
2444
|
].join(' ');
|
|
2086
2445
|
const bytes = (0, octez_connect_utils_1.toHex)(constructedString);
|
|
2087
|
-
const payloadBytes =
|
|
2446
|
+
const payloadBytes = `05` + `01${bytes.length.toString(16).padStart(8, '0')}${bytes}`;
|
|
2088
2447
|
const signature = yield (0, octez_connect_utils_1.signMessage)(payloadBytes, {
|
|
2089
2448
|
secretKey: Buffer.from(keypair.secretKey)
|
|
2090
2449
|
});
|
|
@@ -2112,6 +2471,59 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
2112
2471
|
return notificationResponse.json();
|
|
2113
2472
|
});
|
|
2114
2473
|
}
|
|
2474
|
+
// Delegate the per-network unpacking to the Tezos blockchain plug-in (the
|
|
2475
|
+
// single owner of the v4 fanout shape) and enrich each returned record with
|
|
2476
|
+
// the envelope-level AccountInfo metadata that the parser doesn't see.
|
|
2477
|
+
buildAccountInfosFromV4Fanout(message, fanout, peerVersion, connectionInfo) {
|
|
2478
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2479
|
+
var _a, _b;
|
|
2480
|
+
// Keyed by the CAIP-2 namespace `'tezos'`, which is also the wire-format
|
|
2481
|
+
// `blockchainIdentifier` carried by PermissionRequestV3/Response. The
|
|
2482
|
+
// dApp must have registered `new TezosBlockchain()` via `addBlockchain`
|
|
2483
|
+
// before requesting permissions on the v4 path.
|
|
2484
|
+
const tezosBlockchain = this.blockchains.get('tezos');
|
|
2485
|
+
if (!tezosBlockchain) {
|
|
2486
|
+
throw new Error('Tezos blockchain handler is required to parse v4 permission responses');
|
|
2487
|
+
}
|
|
2488
|
+
// Normalize the legacy `pubkey`/`pubKey` aliases and prefix any raw key
|
|
2489
|
+
// before handing the fanout to the parser. The parser keeps publicKey
|
|
2490
|
+
// strings verbatim, so prefixing here keeps stored records canonical.
|
|
2491
|
+
const envelopePublicKey = (_a = message.publicKey) !== null && _a !== void 0 ? _a : message.pubkey;
|
|
2492
|
+
const prefixedEnvelopePk = envelopePublicKey ? (0, octez_connect_utils_1.prefixPublicKey)(envelopePublicKey) : undefined;
|
|
2493
|
+
const prefixedFanout = Object.fromEntries(Object.entries(fanout).map(([cid, raw]) => [
|
|
2494
|
+
cid,
|
|
2495
|
+
Object.assign(Object.assign({}, raw), { publicKey: (raw === null || raw === void 0 ? void 0 : raw.publicKey) ? (0, octez_connect_utils_1.prefixPublicKey)(raw.publicKey) : undefined })
|
|
2496
|
+
]));
|
|
2497
|
+
const synthesizedResponse = {
|
|
2498
|
+
blockchainIdentifier: 'tezos',
|
|
2499
|
+
type: octez_connect_types_1.BeaconMessageType.PermissionResponse,
|
|
2500
|
+
blockchainData: Object.assign(Object.assign({}, message), { publicKey: prefixedEnvelopePk, accounts: prefixedFanout })
|
|
2501
|
+
};
|
|
2502
|
+
const partials = yield tezosBlockchain.getAccountInfosFromPermissionResponse(synthesizedResponse, peerVersion);
|
|
2503
|
+
const walletKey = (_b = (yield this.storage.get(octez_connect_types_1.StorageKey.LAST_SELECTED_WALLET))) === null || _b === void 0 ? void 0 : _b.key;
|
|
2504
|
+
return Promise.all(partials.map((p) => __awaiter(this, void 0, void 0, function* () {
|
|
2505
|
+
var _a, _b;
|
|
2506
|
+
if (!p.publicKey && !p.address) {
|
|
2507
|
+
throw new Error('PublicKey or Address must be defined for multi-network account');
|
|
2508
|
+
}
|
|
2509
|
+
const address = p.address || (yield (0, octez_connect_utils_1.getAddressFromPublicKey)(p.publicKey));
|
|
2510
|
+
// The parser keys by the address it saw; re-derive accountId if we
|
|
2511
|
+
// synthesized the address from a publicKey above.
|
|
2512
|
+
const accountIdentifier = p.address || !p.network ? p.accountId : yield (0, octez_connect_core_1.getAccountIdentifier)(address, p.network);
|
|
2513
|
+
return Object.assign({ accountIdentifier, senderId: message.senderId, origin: {
|
|
2514
|
+
type: connectionInfo.origin,
|
|
2515
|
+
id: connectionInfo.id
|
|
2516
|
+
}, walletKey,
|
|
2517
|
+
address, publicKey: p.publicKey || undefined,
|
|
2518
|
+
// The v4 fanout parser always sets a Network (networkFromTezosCaip2);
|
|
2519
|
+
// the `?? this.network` fallback keeps the type `Network` (required by
|
|
2520
|
+
// AccountInfo) without an `as AccountInfo` assertion.
|
|
2521
|
+
network: (_a = p.network) !== null && _a !== void 0 ? _a : this.network, scopes: message.scopes, threshold: message.threshold, notification: message.notification, connectedAt: new Date().getTime(), walletType: (_b = message.walletType) !== null && _b !== void 0 ? _b : 'implicit', verificationType: message.verificationType }, (message.verificationType === 'proof_of_event'
|
|
2522
|
+
? { hasVerifiedChallenge: false }
|
|
2523
|
+
: {}));
|
|
2524
|
+
})));
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2115
2527
|
onNewAccount(message, connectionInfo) {
|
|
2116
2528
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2117
2529
|
var _a, _b, _c;
|
|
@@ -2147,4 +2559,39 @@ class DAppClient extends octez_connect_core_1.Client {
|
|
|
2147
2559
|
}
|
|
2148
2560
|
}
|
|
2149
2561
|
exports.DAppClient = DAppClient;
|
|
2562
|
+
/**
|
|
2563
|
+
* This method handles sending of requests to the DApp. It makes sure that the DAppClient is initialized and connected
|
|
2564
|
+
* to the transport. After that rate limits and permissions will be checked, an ID is attached and the request is sent
|
|
2565
|
+
* to the DApp over the transport.
|
|
2566
|
+
*
|
|
2567
|
+
* @param requestInput The BeaconMessage to be sent to the wallet
|
|
2568
|
+
* @param account The account that the message will be sent to
|
|
2569
|
+
* @param skipResponse If true, the function return as soon as the message is sent
|
|
2570
|
+
*/
|
|
2571
|
+
// Maps each flat Tezos request type to its wrapped blockchainData
|
|
2572
|
+
// discriminator + scope (the pre-fork flat wire strings, kept verbatim;
|
|
2573
|
+
// mirrored by the wallet-side flat-output normalization).
|
|
2574
|
+
DAppClient.FLAT_REQUEST_PAYLOAD_TYPES = {
|
|
2575
|
+
[octez_connect_types_1.BeaconMessageType.OperationRequest]: { type: 'operation_request', scope: 'operation_request' },
|
|
2576
|
+
[octez_connect_types_1.BeaconMessageType.SignPayloadRequest]: { type: 'sign_payload_request', scope: 'sign' },
|
|
2577
|
+
[octez_connect_types_1.BeaconMessageType.BroadcastRequest]: { type: 'broadcast_request', scope: 'broadcast' },
|
|
2578
|
+
[octez_connect_types_1.BeaconMessageType.ProofOfEventChallengeRequest]: {
|
|
2579
|
+
type: 'proof_of_event_challenge_request',
|
|
2580
|
+
scope: 'proof_of_event'
|
|
2581
|
+
},
|
|
2582
|
+
[octez_connect_types_1.BeaconMessageType.SimulatedProofOfEventChallengeRequest]: {
|
|
2583
|
+
type: 'simulated_proof_of_event_challenge_request',
|
|
2584
|
+
scope: 'proof_of_event'
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
// Wrapped Tezos response blockchainData discriminators → the flat
|
|
2588
|
+
// BeaconMessageType the request* methods (and integrators) consume.
|
|
2589
|
+
DAppClient.TEZOS_PAYLOAD_TO_FLAT_TYPE = {
|
|
2590
|
+
operation_response: octez_connect_types_1.BeaconMessageType.OperationResponse,
|
|
2591
|
+
sign_payload_response: octez_connect_types_1.BeaconMessageType.SignPayloadResponse,
|
|
2592
|
+
broadcast_response: octez_connect_types_1.BeaconMessageType.BroadcastResponse,
|
|
2593
|
+
proof_of_event_challenge_response: octez_connect_types_1.BeaconMessageType.ProofOfEventChallengeResponse,
|
|
2594
|
+
simulated_proof_of_event_challenge_response: octez_connect_types_1.BeaconMessageType.SimulatedProofOfEventChallengeResponse
|
|
2595
|
+
};
|
|
2596
|
+
DAppClient.TEZOS_IDENTIFIERS = ['tezos', 'xtz'];
|
|
2150
2597
|
//# sourceMappingURL=DAppClient.js.map
|