@pooflabs/web 0.0.84 → 0.0.85-rc1
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/auth/providers/solana-mobile-wallet-provider.d.ts +42 -20
- package/dist/{index-ep10Sw82.esm.js → index-4TKz3Mn_.esm.js} +3 -3
- package/dist/{index-ep10Sw82.esm.js.map → index-4TKz3Mn_.esm.js.map} +1 -1
- package/dist/{index-BM6hgCdH.js → index-BoWQVxMI.js} +2 -2
- package/dist/{index-BM6hgCdH.js.map → index-BoWQVxMI.js.map} +1 -1
- package/dist/{index-CH2G5Y9i.esm.js → index-Buu8v-Oe.esm.js} +2 -2
- package/dist/{index-CH2G5Y9i.esm.js.map → index-Buu8v-Oe.esm.js.map} +1 -1
- package/dist/{index-CSeN3jbG.js → index-C2p1Cldz.js} +3 -3
- package/dist/{index-CSeN3jbG.js.map → index-C2p1Cldz.js.map} +1 -1
- package/dist/index-COF6zNCs.esm.js +6 -0
- package/dist/index-COF6zNCs.esm.js.map +1 -0
- package/dist/{index-Bp4b5LXs.js → index-DlyeWzMk.js} +2 -2
- package/dist/index-DlyeWzMk.js.map +1 -0
- package/dist/{index-BPlF6-PQ.js → index-R7cvXys2.js} +394 -286
- package/dist/{index-BPlF6-PQ.js.map → index-R7cvXys2.js.map} +1 -1
- package/dist/{index-XHbmzFFO.esm.js → index-ZKzq5QT_.esm.js} +395 -287
- package/dist/{index-XHbmzFFO.esm.js.map → index-ZKzq5QT_.esm.js.map} +1 -1
- package/dist/{index.browser-C1QL04xM.js → index.browser-BQSN-6X2.js} +846 -815
- package/dist/index.browser-BQSN-6X2.js.map +1 -0
- package/dist/index.browser-DZCNegue.js +6070 -0
- package/dist/index.browser-DZCNegue.js.map +1 -0
- package/dist/{index.browser-Cgj7Hs6n.esm.js → index.browser-tPepE5fo.esm.js} +836 -802
- package/dist/index.browser-tPepE5fo.esm.js.map +1 -0
- package/dist/index.browser-zfGYm0ST.esm.js +6060 -0
- package/dist/index.browser-zfGYm0ST.esm.js.map +1 -0
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{index.native-BmtuyGXs.js → index.native-BGaUOX9f.js} +4 -4
- package/dist/{index.native-BmtuyGXs.js.map → index.native-BGaUOX9f.js.map} +1 -1
- package/dist/{index.native-X01vlukI.esm.js → index.native-BPQqeP6_.esm.js} +4 -4
- package/dist/{index.native-X01vlukI.esm.js.map → index.native-BPQqeP6_.esm.js.map} +1 -1
- package/dist/index.native.esm.js +1 -1
- package/dist/index.native.js +1 -1
- package/dist/{phantom-wallet-provider-DRvhBbbR.esm.js → phantom-wallet-provider-DheGhOp4.esm.js} +4 -4
- package/dist/{phantom-wallet-provider-DRvhBbbR.esm.js.map → phantom-wallet-provider-DheGhOp4.esm.js.map} +1 -1
- package/dist/{phantom-wallet-provider-C_LPU6Ns.js → phantom-wallet-provider-MFcwrRpJ.js} +4 -4
- package/dist/{phantom-wallet-provider-C_LPU6Ns.js.map → phantom-wallet-provider-MFcwrRpJ.js.map} +1 -1
- package/dist/{privy-wallet-provider-DQM8xO38.js → privy-wallet-provider-CFw6o7O5.js} +3 -3
- package/dist/{privy-wallet-provider-DQM8xO38.js.map → privy-wallet-provider-CFw6o7O5.js.map} +1 -1
- package/dist/{privy-wallet-provider-ZGu8q5T5.esm.js → privy-wallet-provider-D15Au3j8.esm.js} +3 -3
- package/dist/{privy-wallet-provider-ZGu8q5T5.esm.js.map → privy-wallet-provider-D15Au3j8.esm.js.map} +1 -1
- package/dist/solana-mobile-wallet-provider-BM9wdF0m.js +719 -0
- package/dist/solana-mobile-wallet-provider-BM9wdF0m.js.map +1 -0
- package/dist/solana-mobile-wallet-provider-ChHh-U_p.esm.js +698 -0
- package/dist/solana-mobile-wallet-provider-ChHh-U_p.esm.js.map +1 -0
- package/package.json +2 -1
- package/dist/index-Bp4b5LXs.js.map +0 -1
- package/dist/index-C80kRxWk.esm.js +0 -6
- package/dist/index-C80kRxWk.esm.js.map +0 -1
- package/dist/index.browser-BvNsUWjt.js +0 -105
- package/dist/index.browser-BvNsUWjt.js.map +0 -1
- package/dist/index.browser-BwIqqM4U.js +0 -1099
- package/dist/index.browser-BwIqqM4U.js.map +0 -1
- package/dist/index.browser-C1QL04xM.js.map +0 -1
- package/dist/index.browser-Cgj7Hs6n.esm.js.map +0 -1
- package/dist/index.browser-CifFI7Ju.esm.js +0 -1096
- package/dist/index.browser-CifFI7Ju.esm.js.map +0 -1
- package/dist/index.browser-D8VWPXTZ.esm.js +0 -102
- package/dist/index.browser-D8VWPXTZ.esm.js.map +0 -1
- package/dist/index.browser-OvGNsMPu.esm.js +0 -1002
- package/dist/index.browser-OvGNsMPu.esm.js.map +0 -1
- package/dist/index.browser-vuTr40so.js +0 -1008
- package/dist/index.browser-vuTr40so.js.map +0 -1
- package/dist/solana-mobile-wallet-provider-6gNw2_bX.js +0 -608
- package/dist/solana-mobile-wallet-provider-6gNw2_bX.js.map +0 -1
- package/dist/solana-mobile-wallet-provider-B65A7abd.esm.js +0 -587
- package/dist/solana-mobile-wallet-provider-B65A7abd.esm.js.map +0 -1
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var index = require('./index-BPlF6-PQ.js');
|
|
3
|
+
var index_native = require('./index.native-BGaUOX9f.js');
|
|
5
4
|
require('axios');
|
|
6
5
|
require('@solana/web3.js');
|
|
7
6
|
require('@coral-xyz/anchor');
|
|
8
7
|
require('react');
|
|
9
8
|
|
|
10
|
-
/** Solana Mainnet (beta) cluster, e.g. https://api.mainnet-beta.solana.com */
|
|
11
|
-
const SOLANA_MAINNET_CHAIN = 'solana:mainnet';
|
|
12
|
-
|
|
13
9
|
/** Name of the feature. */
|
|
14
10
|
const SolanaSignAndSendTransaction = 'solana:signAndSendTransaction';
|
|
15
11
|
|
|
@@ -22,6 +18,779 @@ const SolanaSignMessage = 'solana:signMessage';
|
|
|
22
18
|
/** Name of the feature. */
|
|
23
19
|
const SolanaSignTransaction = 'solana:signTransaction';
|
|
24
20
|
|
|
21
|
+
function createDecoder(decoder) {
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
...decoder,
|
|
24
|
+
decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var getBaseXDecoder = (alphabet4) => {
|
|
29
|
+
return createDecoder({
|
|
30
|
+
read(rawBytes, offset) {
|
|
31
|
+
const bytes = offset === 0 || offset <= -rawBytes.byteLength ? rawBytes : rawBytes.slice(offset);
|
|
32
|
+
if (bytes.length === 0) return ["", 0];
|
|
33
|
+
let trailIndex = bytes.findIndex((n) => n !== 0);
|
|
34
|
+
trailIndex = trailIndex === -1 ? bytes.length : trailIndex;
|
|
35
|
+
const leadingZeroes = alphabet4[0].repeat(trailIndex);
|
|
36
|
+
if (trailIndex === bytes.length) return [leadingZeroes, rawBytes.length];
|
|
37
|
+
const base10Number = bytes.slice(trailIndex).reduce((sum, byte) => sum * 256n + BigInt(byte), 0n);
|
|
38
|
+
const tailChars = getBaseXFromBigInt(base10Number, alphabet4);
|
|
39
|
+
return [leadingZeroes + tailChars, rawBytes.length];
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
function getBaseXFromBigInt(value, alphabet4) {
|
|
44
|
+
const base = BigInt(alphabet4.length);
|
|
45
|
+
const tailChars = [];
|
|
46
|
+
while (value > 0n) {
|
|
47
|
+
tailChars.unshift(alphabet4[Number(value % base)]);
|
|
48
|
+
value /= base;
|
|
49
|
+
}
|
|
50
|
+
return tailChars.join("");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/base58.ts
|
|
54
|
+
var alphabet2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
55
|
+
var getBase58Decoder = () => getBaseXDecoder(alphabet2);
|
|
56
|
+
|
|
57
|
+
/** Solana Mainnet (beta) cluster, e.g. https://api.mainnet-beta.solana.com */
|
|
58
|
+
const SOLANA_MAINNET_CHAIN = 'solana:mainnet';
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* TODO: docs
|
|
62
|
+
*/
|
|
63
|
+
function createSignInMessageText(input) {
|
|
64
|
+
// ${domain} wants you to sign in with your Solana account:
|
|
65
|
+
// ${address}
|
|
66
|
+
//
|
|
67
|
+
// ${statement}
|
|
68
|
+
//
|
|
69
|
+
// URI: ${uri}
|
|
70
|
+
// Version: ${version}
|
|
71
|
+
// Chain ID: ${chain}
|
|
72
|
+
// Nonce: ${nonce}
|
|
73
|
+
// Issued At: ${issued-at}
|
|
74
|
+
// Expiration Time: ${expiration-time}
|
|
75
|
+
// Not Before: ${not-before}
|
|
76
|
+
// Request ID: ${request-id}
|
|
77
|
+
// Resources:
|
|
78
|
+
// - ${resources[0]}
|
|
79
|
+
// - ${resources[1]}
|
|
80
|
+
// ...
|
|
81
|
+
// - ${resources[n]}
|
|
82
|
+
let message = `${input.domain} wants you to sign in with your Solana account:\n`;
|
|
83
|
+
message += `${input.address}`;
|
|
84
|
+
if (input.statement) {
|
|
85
|
+
message += `\n\n${input.statement}`;
|
|
86
|
+
}
|
|
87
|
+
const fields = [];
|
|
88
|
+
if (input.uri) {
|
|
89
|
+
fields.push(`URI: ${input.uri}`);
|
|
90
|
+
}
|
|
91
|
+
if (input.version) {
|
|
92
|
+
fields.push(`Version: ${input.version}`);
|
|
93
|
+
}
|
|
94
|
+
if (input.chainId) {
|
|
95
|
+
fields.push(`Chain ID: ${input.chainId}`);
|
|
96
|
+
}
|
|
97
|
+
if (input.nonce) {
|
|
98
|
+
fields.push(`Nonce: ${input.nonce}`);
|
|
99
|
+
}
|
|
100
|
+
if (input.issuedAt) {
|
|
101
|
+
fields.push(`Issued At: ${input.issuedAt}`);
|
|
102
|
+
}
|
|
103
|
+
if (input.expirationTime) {
|
|
104
|
+
fields.push(`Expiration Time: ${input.expirationTime}`);
|
|
105
|
+
}
|
|
106
|
+
if (input.notBefore) {
|
|
107
|
+
fields.push(`Not Before: ${input.notBefore}`);
|
|
108
|
+
}
|
|
109
|
+
if (input.requestId) {
|
|
110
|
+
fields.push(`Request ID: ${input.requestId}`);
|
|
111
|
+
}
|
|
112
|
+
if (input.resources) {
|
|
113
|
+
fields.push(`Resources:`);
|
|
114
|
+
for (const resource of input.resources) {
|
|
115
|
+
fields.push(`- ${resource}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (fields.length) {
|
|
119
|
+
message += `\n\n${fields.join('\n')}`;
|
|
120
|
+
}
|
|
121
|
+
return message;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
//#region src/errors.ts
|
|
125
|
+
const SolanaMobileWalletAdapterErrorCode = {
|
|
126
|
+
ERROR_ASSOCIATION_PORT_OUT_OF_RANGE: "ERROR_ASSOCIATION_PORT_OUT_OF_RANGE",
|
|
127
|
+
ERROR_REFLECTOR_ID_OUT_OF_RANGE: "ERROR_REFLECTOR_ID_OUT_OF_RANGE",
|
|
128
|
+
ERROR_FORBIDDEN_WALLET_BASE_URL: "ERROR_FORBIDDEN_WALLET_BASE_URL",
|
|
129
|
+
ERROR_SECURE_CONTEXT_REQUIRED: "ERROR_SECURE_CONTEXT_REQUIRED",
|
|
130
|
+
ERROR_SESSION_CLOSED: "ERROR_SESSION_CLOSED",
|
|
131
|
+
ERROR_SESSION_TIMEOUT: "ERROR_SESSION_TIMEOUT",
|
|
132
|
+
ERROR_WALLET_NOT_FOUND: "ERROR_WALLET_NOT_FOUND",
|
|
133
|
+
ERROR_INVALID_PROTOCOL_VERSION: "ERROR_INVALID_PROTOCOL_VERSION",
|
|
134
|
+
ERROR_BROWSER_NOT_SUPPORTED: "ERROR_BROWSER_NOT_SUPPORTED",
|
|
135
|
+
ERROR_LOOPBACK_ACCESS_BLOCKED: "ERROR_LOOPBACK_ACCESS_BLOCKED",
|
|
136
|
+
ERROR_ASSOCIATION_CANCELLED: "ERROR_ASSOCIATION_CANCELLED"
|
|
137
|
+
};
|
|
138
|
+
var SolanaMobileWalletAdapterError = class extends Error {
|
|
139
|
+
data;
|
|
140
|
+
code;
|
|
141
|
+
constructor(...args) {
|
|
142
|
+
const [code, message, data] = args;
|
|
143
|
+
super(message);
|
|
144
|
+
this.code = code;
|
|
145
|
+
this.data = data;
|
|
146
|
+
this.name = "SolanaMobileWalletAdapterError";
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
var SolanaMobileWalletAdapterProtocolError = class extends Error {
|
|
150
|
+
data;
|
|
151
|
+
code;
|
|
152
|
+
jsonRpcMessageId;
|
|
153
|
+
constructor(...args) {
|
|
154
|
+
const [jsonRpcMessageId, code, message, data] = args;
|
|
155
|
+
super(message);
|
|
156
|
+
this.code = code;
|
|
157
|
+
this.data = data;
|
|
158
|
+
this.jsonRpcMessageId = jsonRpcMessageId;
|
|
159
|
+
this.name = "SolanaMobileWalletAdapterProtocolError";
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/base64Utils.ts
|
|
164
|
+
function encode(input) {
|
|
165
|
+
return window.btoa(input);
|
|
166
|
+
}
|
|
167
|
+
function fromUint8Array$1(byteArray, urlsafe) {
|
|
168
|
+
const base64 = window.btoa(String.fromCharCode.call(null, ...byteArray));
|
|
169
|
+
return base64;
|
|
170
|
+
}
|
|
171
|
+
function toUint8Array$1(base64EncodedByteArray) {
|
|
172
|
+
return new Uint8Array(window.atob(base64EncodedByteArray).split("").map((c) => c.charCodeAt(0)));
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/createHelloReq.ts
|
|
176
|
+
async function createHelloReq(ecdhPublicKey, associationKeypairPrivateKey) {
|
|
177
|
+
const publicKeyBuffer = await crypto.subtle.exportKey("raw", ecdhPublicKey);
|
|
178
|
+
const signatureBuffer = await crypto.subtle.sign({
|
|
179
|
+
hash: "SHA-256",
|
|
180
|
+
name: "ECDSA"
|
|
181
|
+
}, associationKeypairPrivateKey, publicKeyBuffer);
|
|
182
|
+
const response = new Uint8Array(publicKeyBuffer.byteLength + signatureBuffer.byteLength);
|
|
183
|
+
response.set(new Uint8Array(publicKeyBuffer), 0);
|
|
184
|
+
response.set(new Uint8Array(signatureBuffer), publicKeyBuffer.byteLength);
|
|
185
|
+
return response;
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/base58Utils.ts
|
|
189
|
+
function fromUint8Array$2(byteArray) {
|
|
190
|
+
return getBase58Decoder().decode(byteArray);
|
|
191
|
+
}
|
|
192
|
+
function base64ToBase58(base64EncodedString) {
|
|
193
|
+
return fromUint8Array$2(toUint8Array$1(base64EncodedString));
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/createSIWSMessage.ts
|
|
197
|
+
function createSIWSMessage(payload) {
|
|
198
|
+
return createSignInMessageText(payload);
|
|
199
|
+
}
|
|
200
|
+
function createSIWSMessageBase64Url(payload) {
|
|
201
|
+
return encode(createSIWSMessage(payload)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/types.ts
|
|
205
|
+
const SolanaSignTransactions = "solana:signTransactions";
|
|
206
|
+
const SolanaCloneAuthorization = "solana:cloneAuthorization";
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/createMobileWalletProxy.ts
|
|
209
|
+
/**
|
|
210
|
+
* Creates a {@link MobileWallet} proxy that handles backwards compatibility and API to RPC conversion.
|
|
211
|
+
*
|
|
212
|
+
* @param protocolVersion the protocol version in use for this session/request
|
|
213
|
+
* @param protocolRequestHandler callback function that handles sending the RPC request to the wallet endpoint.
|
|
214
|
+
* @returns a {@link MobileWallet} proxy
|
|
215
|
+
*/
|
|
216
|
+
function createMobileWalletProxy(protocolVersion, protocolRequestHandler) {
|
|
217
|
+
return new Proxy({}, {
|
|
218
|
+
get(target, p) {
|
|
219
|
+
if (p === "then") return null;
|
|
220
|
+
if (target[p] == null) target[p] = async function(inputParams) {
|
|
221
|
+
const { method, params } = handleMobileWalletRequest(p, inputParams, protocolVersion);
|
|
222
|
+
const result = await protocolRequestHandler(method, params);
|
|
223
|
+
if (method === "authorize" && params.sign_in_payload && !result.sign_in_result) result.sign_in_result = await signInFallback(params.sign_in_payload, result, protocolRequestHandler);
|
|
224
|
+
return handleMobileWalletResponse(p, result, protocolVersion);
|
|
225
|
+
};
|
|
226
|
+
return target[p];
|
|
227
|
+
},
|
|
228
|
+
defineProperty() {
|
|
229
|
+
return false;
|
|
230
|
+
},
|
|
231
|
+
deleteProperty() {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Handles all {@link MobileWallet} API requests and determines the correct MWA RPC method and params to call.
|
|
238
|
+
* This handles backwards compatibility, based on the provided @protocolVersion.
|
|
239
|
+
*
|
|
240
|
+
* @param methodName the name of {@link MobileWallet} method that was called
|
|
241
|
+
* @param methodParams the parameters that were passed to the method
|
|
242
|
+
* @param protocolVersion the protocol version in use for this session/request
|
|
243
|
+
* @returns the RPC request method and params that should be sent to the wallet endpoint
|
|
244
|
+
*/
|
|
245
|
+
function handleMobileWalletRequest(methodName, methodParams, protocolVersion) {
|
|
246
|
+
let params = methodParams;
|
|
247
|
+
let method = methodName.toString().replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`).toLowerCase();
|
|
248
|
+
switch (methodName) {
|
|
249
|
+
case "authorize": {
|
|
250
|
+
const authorizeParams = params;
|
|
251
|
+
let { chain } = authorizeParams;
|
|
252
|
+
if (protocolVersion === "legacy") {
|
|
253
|
+
switch (chain) {
|
|
254
|
+
case "solana:testnet":
|
|
255
|
+
chain = "testnet";
|
|
256
|
+
break;
|
|
257
|
+
case "solana:devnet":
|
|
258
|
+
chain = "devnet";
|
|
259
|
+
break;
|
|
260
|
+
case "solana:mainnet":
|
|
261
|
+
chain = "mainnet-beta";
|
|
262
|
+
break;
|
|
263
|
+
default: chain = authorizeParams.cluster;
|
|
264
|
+
}
|
|
265
|
+
authorizeParams.cluster = chain;
|
|
266
|
+
params = authorizeParams;
|
|
267
|
+
} else {
|
|
268
|
+
switch (chain) {
|
|
269
|
+
case "testnet":
|
|
270
|
+
case "devnet":
|
|
271
|
+
chain = `solana:${chain}`;
|
|
272
|
+
break;
|
|
273
|
+
case "mainnet-beta":
|
|
274
|
+
chain = "solana:mainnet";
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
authorizeParams.chain = chain;
|
|
278
|
+
params = authorizeParams;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
case "reauthorize": {
|
|
282
|
+
const { auth_token, identity } = params;
|
|
283
|
+
if (auth_token) switch (protocolVersion) {
|
|
284
|
+
case "legacy":
|
|
285
|
+
method = "reauthorize";
|
|
286
|
+
params = {
|
|
287
|
+
auth_token,
|
|
288
|
+
identity
|
|
289
|
+
};
|
|
290
|
+
break;
|
|
291
|
+
default:
|
|
292
|
+
method = "authorize";
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
method,
|
|
300
|
+
params
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Handles all {@link MobileWallet} API responses and modifies the response for backwards compatibility, if needed
|
|
305
|
+
*
|
|
306
|
+
* @param method the {@link MobileWallet} method that was called
|
|
307
|
+
* @param response the original response that was returned by the method call
|
|
308
|
+
* @param protocolVersion the protocol version in use for this session/request
|
|
309
|
+
* @returns the possibly modified response
|
|
310
|
+
*/
|
|
311
|
+
function handleMobileWalletResponse(method, response, protocolVersion) {
|
|
312
|
+
switch (method) {
|
|
313
|
+
case "getCapabilities": {
|
|
314
|
+
const capabilities = response;
|
|
315
|
+
switch (protocolVersion) {
|
|
316
|
+
case "legacy": {
|
|
317
|
+
const features = [SolanaSignTransactions];
|
|
318
|
+
if (capabilities.supports_clone_authorization === true) features.push(SolanaCloneAuthorization);
|
|
319
|
+
return {
|
|
320
|
+
...capabilities,
|
|
321
|
+
features
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
case "v1": return {
|
|
325
|
+
...capabilities,
|
|
326
|
+
supports_sign_and_send_transactions: true,
|
|
327
|
+
supports_clone_authorization: capabilities.features.includes(SolanaCloneAuthorization)
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return response;
|
|
333
|
+
}
|
|
334
|
+
async function signInFallback(signInPayload, authorizationResult, protocolRequestHandler) {
|
|
335
|
+
const domain = signInPayload.domain ?? window.location.host;
|
|
336
|
+
const address = authorizationResult.accounts[0].address;
|
|
337
|
+
const siwsMessage = createSIWSMessageBase64Url({
|
|
338
|
+
...signInPayload,
|
|
339
|
+
domain,
|
|
340
|
+
address: base64ToBase58(address)
|
|
341
|
+
});
|
|
342
|
+
const signedPayload = toUint8Array$1((await protocolRequestHandler("sign_messages", {
|
|
343
|
+
addresses: [address],
|
|
344
|
+
payloads: [siwsMessage]
|
|
345
|
+
})).signed_payloads[0]);
|
|
346
|
+
const signedMessage = fromUint8Array$1(signedPayload.slice(0, signedPayload.length - 64));
|
|
347
|
+
const signature = fromUint8Array$1(signedPayload.slice(signedPayload.length - 64));
|
|
348
|
+
return {
|
|
349
|
+
address,
|
|
350
|
+
signed_message: signedMessage.length == 0 ? siwsMessage : signedMessage,
|
|
351
|
+
signature
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function createSequenceNumberVector(sequenceNumber) {
|
|
355
|
+
if (sequenceNumber >= 4294967296) throw new Error("Outbound sequence number overflow. The maximum sequence number is 32-bytes.");
|
|
356
|
+
const byteArray = /* @__PURE__ */ new ArrayBuffer(4);
|
|
357
|
+
new DataView(byteArray).setUint32(0, sequenceNumber, false);
|
|
358
|
+
return new Uint8Array(byteArray);
|
|
359
|
+
}
|
|
360
|
+
//#endregion
|
|
361
|
+
//#region src/encryptedMessage.ts
|
|
362
|
+
const INITIALIZATION_VECTOR_BYTES = 12;
|
|
363
|
+
async function encryptMessage(plaintext, sequenceNumber, sharedSecret) {
|
|
364
|
+
const sequenceNumberVector = createSequenceNumberVector(sequenceNumber);
|
|
365
|
+
const initializationVector = new Uint8Array(INITIALIZATION_VECTOR_BYTES);
|
|
366
|
+
crypto.getRandomValues(initializationVector);
|
|
367
|
+
const ciphertext = await crypto.subtle.encrypt(getAlgorithmParams(sequenceNumberVector, initializationVector), sharedSecret, new TextEncoder().encode(plaintext));
|
|
368
|
+
const response = new Uint8Array(sequenceNumberVector.byteLength + initializationVector.byteLength + ciphertext.byteLength);
|
|
369
|
+
response.set(new Uint8Array(sequenceNumberVector), 0);
|
|
370
|
+
response.set(new Uint8Array(initializationVector), sequenceNumberVector.byteLength);
|
|
371
|
+
response.set(new Uint8Array(ciphertext), sequenceNumberVector.byteLength + initializationVector.byteLength);
|
|
372
|
+
return response;
|
|
373
|
+
}
|
|
374
|
+
async function decryptMessage(message, sharedSecret) {
|
|
375
|
+
const sequenceNumberVector = message.slice(0, 4);
|
|
376
|
+
const initializationVector = message.slice(4, 4 + INITIALIZATION_VECTOR_BYTES);
|
|
377
|
+
const ciphertext = message.slice(4 + INITIALIZATION_VECTOR_BYTES);
|
|
378
|
+
const plaintextBuffer = await crypto.subtle.decrypt(getAlgorithmParams(sequenceNumberVector, initializationVector), sharedSecret, ciphertext);
|
|
379
|
+
return getUtf8Decoder().decode(plaintextBuffer);
|
|
380
|
+
}
|
|
381
|
+
function getAlgorithmParams(sequenceNumber, initializationVector) {
|
|
382
|
+
return {
|
|
383
|
+
additionalData: sequenceNumber,
|
|
384
|
+
iv: initializationVector,
|
|
385
|
+
name: "AES-GCM",
|
|
386
|
+
tagLength: 128
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
let _utf8Decoder;
|
|
390
|
+
function getUtf8Decoder() {
|
|
391
|
+
if (_utf8Decoder === void 0) _utf8Decoder = new TextDecoder("utf-8");
|
|
392
|
+
return _utf8Decoder;
|
|
393
|
+
}
|
|
394
|
+
//#endregion
|
|
395
|
+
//#region src/generateAssociationKeypair.ts
|
|
396
|
+
async function generateAssociationKeypair() {
|
|
397
|
+
return await crypto.subtle.generateKey({
|
|
398
|
+
name: "ECDSA",
|
|
399
|
+
namedCurve: "P-256"
|
|
400
|
+
}, false, ["sign"]);
|
|
401
|
+
}
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/generateECDHKeypair.ts
|
|
404
|
+
async function generateECDHKeypair() {
|
|
405
|
+
return await crypto.subtle.generateKey({
|
|
406
|
+
name: "ECDH",
|
|
407
|
+
namedCurve: "P-256"
|
|
408
|
+
}, false, ["deriveKey", "deriveBits"]);
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/arrayBufferToBase64String.ts
|
|
412
|
+
function arrayBufferToBase64String(buffer) {
|
|
413
|
+
let binary = "";
|
|
414
|
+
const bytes = new Uint8Array(buffer);
|
|
415
|
+
const len = bytes.byteLength;
|
|
416
|
+
for (let ii = 0; ii < len; ii++) binary += String.fromCharCode(bytes[ii]);
|
|
417
|
+
return window.btoa(binary);
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region src/associationPort.ts
|
|
421
|
+
function getRandomAssociationPort() {
|
|
422
|
+
return assertAssociationPort(49152 + Math.floor(Math.random() * 16384));
|
|
423
|
+
}
|
|
424
|
+
function assertAssociationPort(port) {
|
|
425
|
+
if (port < 49152 || port > 65535) throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_PORT_OUT_OF_RANGE, `Association port number must be between 49152 and 65535. ${port} given.`, { port });
|
|
426
|
+
return port;
|
|
427
|
+
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/getStringWithURLUnsafeBase64CharactersReplaced.ts
|
|
430
|
+
function getStringWithURLUnsafeCharactersReplaced(unsafeBase64EncodedString) {
|
|
431
|
+
return unsafeBase64EncodedString.replace(/[/+=]/g, (m) => ({
|
|
432
|
+
"/": "_",
|
|
433
|
+
"+": "-",
|
|
434
|
+
"=": "."
|
|
435
|
+
})[m]);
|
|
436
|
+
}
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/getAssociateAndroidIntentURL.ts
|
|
439
|
+
const INTENT_NAME = "solana-wallet";
|
|
440
|
+
function getPathParts(pathString) {
|
|
441
|
+
return pathString.replace(/(^\/+|\/+$)/g, "").split("/");
|
|
442
|
+
}
|
|
443
|
+
function getIntentURL(methodPathname, intentUrlBase) {
|
|
444
|
+
let baseUrl = null;
|
|
445
|
+
if (intentUrlBase) {
|
|
446
|
+
try {
|
|
447
|
+
baseUrl = new URL(intentUrlBase);
|
|
448
|
+
} catch {}
|
|
449
|
+
if (baseUrl?.protocol !== "https:") throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_FORBIDDEN_WALLET_BASE_URL, "Base URLs supplied by wallets must be valid `https` URLs");
|
|
450
|
+
}
|
|
451
|
+
baseUrl ||= new URL(`${INTENT_NAME}:/`);
|
|
452
|
+
const pathname = methodPathname.startsWith("/") ? methodPathname : [...getPathParts(baseUrl.pathname), ...getPathParts(methodPathname)].join("/");
|
|
453
|
+
return new URL(pathname, baseUrl);
|
|
454
|
+
}
|
|
455
|
+
async function getAssociateAndroidIntentURL(associationPublicKey, putativePort, associationURLBase, protocolVersions = ["v1"]) {
|
|
456
|
+
const associationPort = assertAssociationPort(putativePort);
|
|
457
|
+
const encodedKey = arrayBufferToBase64String(await crypto.subtle.exportKey("raw", associationPublicKey));
|
|
458
|
+
const url = getIntentURL("v1/associate/local", associationURLBase);
|
|
459
|
+
url.searchParams.set("association", getStringWithURLUnsafeCharactersReplaced(encodedKey));
|
|
460
|
+
url.searchParams.set("port", `${associationPort}`);
|
|
461
|
+
protocolVersions.forEach((version) => {
|
|
462
|
+
url.searchParams.set("v", version);
|
|
463
|
+
});
|
|
464
|
+
return url;
|
|
465
|
+
}
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/jsonRpcMessage.ts
|
|
468
|
+
async function encryptJsonRpcMessage(jsonRpcMessage, sharedSecret) {
|
|
469
|
+
const plaintext = JSON.stringify(jsonRpcMessage);
|
|
470
|
+
const sequenceNumber = jsonRpcMessage.id;
|
|
471
|
+
return encryptMessage(plaintext, sequenceNumber, sharedSecret);
|
|
472
|
+
}
|
|
473
|
+
async function decryptJsonRpcMessage(message, sharedSecret) {
|
|
474
|
+
const plaintext = await decryptMessage(message, sharedSecret);
|
|
475
|
+
const jsonRpcMessage = JSON.parse(plaintext);
|
|
476
|
+
if (Object.hasOwnProperty.call(jsonRpcMessage, "error")) throw new SolanaMobileWalletAdapterProtocolError(jsonRpcMessage.id, jsonRpcMessage.error.code, jsonRpcMessage.error.message);
|
|
477
|
+
return jsonRpcMessage;
|
|
478
|
+
}
|
|
479
|
+
//#endregion
|
|
480
|
+
//#region src/parseHelloRsp.ts
|
|
481
|
+
async function parseHelloRsp(payloadBuffer, associationPublicKey, ecdhPrivateKey) {
|
|
482
|
+
const [associationPublicKeyBuffer, walletPublicKey] = await Promise.all([crypto.subtle.exportKey("raw", associationPublicKey), crypto.subtle.importKey("raw", payloadBuffer.slice(0, 65), {
|
|
483
|
+
name: "ECDH",
|
|
484
|
+
namedCurve: "P-256"
|
|
485
|
+
}, false, [])]);
|
|
486
|
+
const sharedSecret = await crypto.subtle.deriveBits({
|
|
487
|
+
name: "ECDH",
|
|
488
|
+
public: walletPublicKey
|
|
489
|
+
}, ecdhPrivateKey, 256);
|
|
490
|
+
const ecdhSecretKey = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, ["deriveKey"]);
|
|
491
|
+
return await crypto.subtle.deriveKey({
|
|
492
|
+
name: "HKDF",
|
|
493
|
+
hash: "SHA-256",
|
|
494
|
+
salt: new Uint8Array(associationPublicKeyBuffer),
|
|
495
|
+
info: new Uint8Array()
|
|
496
|
+
}, ecdhSecretKey, {
|
|
497
|
+
name: "AES-GCM",
|
|
498
|
+
length: 128
|
|
499
|
+
}, false, ["encrypt", "decrypt"]);
|
|
500
|
+
}
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region src/parseSessionProps.ts
|
|
503
|
+
async function parseSessionProps(message, sharedSecret) {
|
|
504
|
+
const plaintext = await decryptMessage(message, sharedSecret);
|
|
505
|
+
const jsonProperties = JSON.parse(plaintext);
|
|
506
|
+
let protocolVersion = "legacy";
|
|
507
|
+
if (Object.hasOwnProperty.call(jsonProperties, "v")) switch (jsonProperties.v) {
|
|
508
|
+
case 1:
|
|
509
|
+
case "1":
|
|
510
|
+
case "v1":
|
|
511
|
+
protocolVersion = "v1";
|
|
512
|
+
break;
|
|
513
|
+
case "legacy":
|
|
514
|
+
protocolVersion = "legacy";
|
|
515
|
+
break;
|
|
516
|
+
default: throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_INVALID_PROTOCOL_VERSION, `Unknown/unsupported protocol version: ${jsonProperties.v}`);
|
|
517
|
+
}
|
|
518
|
+
return { protocol_version: protocolVersion };
|
|
519
|
+
}
|
|
520
|
+
//#endregion
|
|
521
|
+
//#region src/startSession.ts
|
|
522
|
+
const Browser = {
|
|
523
|
+
Firefox: 0,
|
|
524
|
+
Other: 1
|
|
525
|
+
};
|
|
526
|
+
function assertUnreachable(x) {
|
|
527
|
+
return x;
|
|
528
|
+
}
|
|
529
|
+
function getBrowser() {
|
|
530
|
+
return navigator.userAgent.indexOf("Firefox/") !== -1 ? Browser.Firefox : Browser.Other;
|
|
531
|
+
}
|
|
532
|
+
function getDetectionPromise() {
|
|
533
|
+
return new Promise((resolve, reject) => {
|
|
534
|
+
function cleanup() {
|
|
535
|
+
clearTimeout(timeoutId);
|
|
536
|
+
window.removeEventListener("blur", handleBlur);
|
|
537
|
+
}
|
|
538
|
+
function handleBlur() {
|
|
539
|
+
cleanup();
|
|
540
|
+
resolve();
|
|
541
|
+
}
|
|
542
|
+
window.addEventListener("blur", handleBlur);
|
|
543
|
+
const timeoutId = setTimeout(() => {
|
|
544
|
+
cleanup();
|
|
545
|
+
reject();
|
|
546
|
+
}, 3e3);
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
let _frame = null;
|
|
550
|
+
function launchUrlThroughHiddenFrame(url) {
|
|
551
|
+
if (_frame == null) {
|
|
552
|
+
_frame = document.createElement("iframe");
|
|
553
|
+
_frame.style.display = "none";
|
|
554
|
+
document.body.appendChild(_frame);
|
|
555
|
+
}
|
|
556
|
+
_frame.contentWindow.location.href = url.toString();
|
|
557
|
+
}
|
|
558
|
+
async function launchAssociation(associationUrl) {
|
|
559
|
+
if (associationUrl.protocol === "https:") window.location.assign(associationUrl);
|
|
560
|
+
else try {
|
|
561
|
+
const browser = getBrowser();
|
|
562
|
+
switch (browser) {
|
|
563
|
+
case Browser.Firefox:
|
|
564
|
+
launchUrlThroughHiddenFrame(associationUrl);
|
|
565
|
+
break;
|
|
566
|
+
case Browser.Other: {
|
|
567
|
+
const detectionPromise = getDetectionPromise();
|
|
568
|
+
window.location.assign(associationUrl);
|
|
569
|
+
await detectionPromise;
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
default: assertUnreachable(browser);
|
|
573
|
+
}
|
|
574
|
+
} catch {
|
|
575
|
+
throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_WALLET_NOT_FOUND, "Found no installed wallet that supports the mobile wallet protocol.");
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
async function startSession(associationPublicKey, associationURLBase) {
|
|
579
|
+
const randomAssociationPort = getRandomAssociationPort();
|
|
580
|
+
await launchAssociation(await getAssociateAndroidIntentURL(associationPublicKey, randomAssociationPort, associationURLBase));
|
|
581
|
+
return randomAssociationPort;
|
|
582
|
+
}
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region src/transact.ts
|
|
585
|
+
const WEBSOCKET_CONNECTION_CONFIG = {
|
|
586
|
+
retryDelayScheduleMs: [
|
|
587
|
+
150,
|
|
588
|
+
150,
|
|
589
|
+
200,
|
|
590
|
+
500,
|
|
591
|
+
500,
|
|
592
|
+
750,
|
|
593
|
+
750,
|
|
594
|
+
1e3
|
|
595
|
+
],
|
|
596
|
+
timeoutMs: 3e4
|
|
597
|
+
};
|
|
598
|
+
const WEBSOCKET_PROTOCOL_BINARY = "com.solana.mobilewalletadapter.v1";
|
|
599
|
+
function assertSecureContext() {
|
|
600
|
+
if (typeof window === "undefined" || window.isSecureContext !== true) throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_SECURE_CONTEXT_REQUIRED, "The mobile wallet adapter protocol must be used in a secure context (`https`).");
|
|
601
|
+
}
|
|
602
|
+
function assertSecureEndpointSpecificURI(walletUriBase) {
|
|
603
|
+
let url;
|
|
604
|
+
try {
|
|
605
|
+
url = new URL(walletUriBase);
|
|
606
|
+
} catch {
|
|
607
|
+
throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_FORBIDDEN_WALLET_BASE_URL, "Invalid base URL supplied by wallet");
|
|
608
|
+
}
|
|
609
|
+
if (url.protocol !== "https:") throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_FORBIDDEN_WALLET_BASE_URL, "Base URLs supplied by wallets must be valid `https` URLs");
|
|
610
|
+
}
|
|
611
|
+
function getSequenceNumberFromByteArray(byteArray) {
|
|
612
|
+
return new DataView(byteArray).getUint32(0, false);
|
|
613
|
+
}
|
|
614
|
+
async function startScenario(config) {
|
|
615
|
+
assertSecureContext();
|
|
616
|
+
const associationKeypair = await generateAssociationKeypair();
|
|
617
|
+
const websocketURL = `ws://localhost:${await startSession(associationKeypair.publicKey, config?.baseUri)}/solana-wallet`;
|
|
618
|
+
let connectionStartTime;
|
|
619
|
+
const getNextRetryDelayMs = (() => {
|
|
620
|
+
const schedule = [...WEBSOCKET_CONNECTION_CONFIG.retryDelayScheduleMs];
|
|
621
|
+
return () => schedule.length > 1 ? schedule.shift() : schedule[0];
|
|
622
|
+
})();
|
|
623
|
+
let nextJsonRpcMessageId = 1;
|
|
624
|
+
let lastKnownInboundSequenceNumber = 0;
|
|
625
|
+
let state = { __type: "disconnected" };
|
|
626
|
+
let socket;
|
|
627
|
+
let sessionEstablished = false;
|
|
628
|
+
let handleForceClose;
|
|
629
|
+
return {
|
|
630
|
+
close: () => {
|
|
631
|
+
socket.close();
|
|
632
|
+
handleForceClose();
|
|
633
|
+
},
|
|
634
|
+
wallet: new Promise((resolve, reject) => {
|
|
635
|
+
const jsonRpcResponsePromises = {};
|
|
636
|
+
const handleOpen = async () => {
|
|
637
|
+
if (state.__type !== "connecting") {
|
|
638
|
+
console.warn(`Expected adapter state to be \`connecting\` at the moment the websocket opens. Got \`${state.__type}\`.`);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
socket.removeEventListener("open", handleOpen);
|
|
642
|
+
const { associationKeypair } = state;
|
|
643
|
+
const ecdhKeypair = await generateECDHKeypair();
|
|
644
|
+
socket.send(await createHelloReq(ecdhKeypair.publicKey, associationKeypair.privateKey));
|
|
645
|
+
state = {
|
|
646
|
+
__type: "hello_req_sent",
|
|
647
|
+
associationPublicKey: associationKeypair.publicKey,
|
|
648
|
+
ecdhPrivateKey: ecdhKeypair.privateKey
|
|
649
|
+
};
|
|
650
|
+
};
|
|
651
|
+
const handleClose = (evt) => {
|
|
652
|
+
if (evt.wasClean) state = { __type: "disconnected" };
|
|
653
|
+
else reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_SESSION_CLOSED, `The wallet session dropped unexpectedly (${evt.code}: ${evt.reason}).`, { closeEvent: evt }));
|
|
654
|
+
disposeSocket();
|
|
655
|
+
};
|
|
656
|
+
const handleError = async (_evt) => {
|
|
657
|
+
disposeSocket();
|
|
658
|
+
if (Date.now() - connectionStartTime >= WEBSOCKET_CONNECTION_CONFIG.timeoutMs) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_SESSION_TIMEOUT, `Failed to connect to the wallet websocket at ${websocketURL}.`));
|
|
659
|
+
else {
|
|
660
|
+
await new Promise((resolve) => {
|
|
661
|
+
const retryDelayMs = getNextRetryDelayMs();
|
|
662
|
+
retryWaitTimeoutId = window.setTimeout(resolve, retryDelayMs);
|
|
663
|
+
});
|
|
664
|
+
attemptSocketConnection();
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
const handleMessage = async (evt) => {
|
|
668
|
+
const responseBuffer = await evt.data.arrayBuffer();
|
|
669
|
+
switch (state.__type) {
|
|
670
|
+
case "connecting": {
|
|
671
|
+
if (responseBuffer.byteLength !== 0) throw new Error("Encountered unexpected message while connecting");
|
|
672
|
+
const ecdhKeypair = await generateECDHKeypair();
|
|
673
|
+
socket.send(await createHelloReq(ecdhKeypair.publicKey, associationKeypair.privateKey));
|
|
674
|
+
state = {
|
|
675
|
+
__type: "hello_req_sent",
|
|
676
|
+
associationPublicKey: associationKeypair.publicKey,
|
|
677
|
+
ecdhPrivateKey: ecdhKeypair.privateKey
|
|
678
|
+
};
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
case "connected":
|
|
682
|
+
try {
|
|
683
|
+
const sequenceNumber = getSequenceNumberFromByteArray(responseBuffer.slice(0, 4));
|
|
684
|
+
if (sequenceNumber !== lastKnownInboundSequenceNumber + 1) throw new Error("Encrypted message has invalid sequence number");
|
|
685
|
+
lastKnownInboundSequenceNumber = sequenceNumber;
|
|
686
|
+
const jsonRpcMessage = await decryptJsonRpcMessage(responseBuffer, state.sharedSecret);
|
|
687
|
+
const responsePromise = jsonRpcResponsePromises[jsonRpcMessage.id];
|
|
688
|
+
delete jsonRpcResponsePromises[jsonRpcMessage.id];
|
|
689
|
+
responsePromise.resolve(jsonRpcMessage.result);
|
|
690
|
+
} catch (e) {
|
|
691
|
+
if (e instanceof SolanaMobileWalletAdapterProtocolError) {
|
|
692
|
+
const responsePromise = jsonRpcResponsePromises[e.jsonRpcMessageId];
|
|
693
|
+
delete jsonRpcResponsePromises[e.jsonRpcMessageId];
|
|
694
|
+
responsePromise.reject(e);
|
|
695
|
+
} else throw e;
|
|
696
|
+
}
|
|
697
|
+
break;
|
|
698
|
+
case "hello_req_sent": {
|
|
699
|
+
if (responseBuffer.byteLength === 0) {
|
|
700
|
+
const ecdhKeypair = await generateECDHKeypair();
|
|
701
|
+
socket.send(await createHelloReq(ecdhKeypair.publicKey, associationKeypair.privateKey));
|
|
702
|
+
state = {
|
|
703
|
+
__type: "hello_req_sent",
|
|
704
|
+
associationPublicKey: associationKeypair.publicKey,
|
|
705
|
+
ecdhPrivateKey: ecdhKeypair.privateKey
|
|
706
|
+
};
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
const sharedSecret = await parseHelloRsp(responseBuffer, state.associationPublicKey, state.ecdhPrivateKey);
|
|
710
|
+
const sessionPropertiesBuffer = responseBuffer.slice(65);
|
|
711
|
+
const sessionProperties = sessionPropertiesBuffer.byteLength !== 0 ? await (async () => {
|
|
712
|
+
const sequenceNumber = getSequenceNumberFromByteArray(sessionPropertiesBuffer.slice(0, 4));
|
|
713
|
+
if (sequenceNumber !== lastKnownInboundSequenceNumber + 1) throw new Error("Encrypted message has invalid sequence number");
|
|
714
|
+
lastKnownInboundSequenceNumber = sequenceNumber;
|
|
715
|
+
return parseSessionProps(sessionPropertiesBuffer, sharedSecret);
|
|
716
|
+
})() : { protocol_version: "legacy" };
|
|
717
|
+
state = {
|
|
718
|
+
__type: "connected",
|
|
719
|
+
sharedSecret,
|
|
720
|
+
sessionProperties
|
|
721
|
+
};
|
|
722
|
+
const wallet = createMobileWalletProxy(sessionProperties.protocol_version, async (method, params) => {
|
|
723
|
+
const id = nextJsonRpcMessageId++;
|
|
724
|
+
socket.send(await encryptJsonRpcMessage({
|
|
725
|
+
id,
|
|
726
|
+
jsonrpc: "2.0",
|
|
727
|
+
method,
|
|
728
|
+
params: params ?? {}
|
|
729
|
+
}, sharedSecret));
|
|
730
|
+
return new Promise((resolve, reject) => {
|
|
731
|
+
jsonRpcResponsePromises[id] = {
|
|
732
|
+
resolve(result) {
|
|
733
|
+
switch (method) {
|
|
734
|
+
case "authorize":
|
|
735
|
+
case "reauthorize": {
|
|
736
|
+
const { wallet_uri_base } = result;
|
|
737
|
+
if (wallet_uri_base != null) try {
|
|
738
|
+
assertSecureEndpointSpecificURI(wallet_uri_base);
|
|
739
|
+
} catch (e) {
|
|
740
|
+
reject(e);
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
resolve(result);
|
|
747
|
+
},
|
|
748
|
+
reject
|
|
749
|
+
};
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
sessionEstablished = true;
|
|
753
|
+
try {
|
|
754
|
+
resolve(wallet);
|
|
755
|
+
} catch (e) {
|
|
756
|
+
reject(e);
|
|
757
|
+
}
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
handleForceClose = () => {
|
|
763
|
+
socket.removeEventListener("message", handleMessage);
|
|
764
|
+
disposeSocket();
|
|
765
|
+
if (!sessionEstablished) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_SESSION_CLOSED, `The wallet session was closed before connection.`, { closeEvent: new CloseEvent("socket was closed before connection") }));
|
|
766
|
+
};
|
|
767
|
+
let disposeSocket;
|
|
768
|
+
let retryWaitTimeoutId;
|
|
769
|
+
const attemptSocketConnection = () => {
|
|
770
|
+
if (disposeSocket) disposeSocket();
|
|
771
|
+
state = {
|
|
772
|
+
__type: "connecting",
|
|
773
|
+
associationKeypair
|
|
774
|
+
};
|
|
775
|
+
if (connectionStartTime === void 0) connectionStartTime = Date.now();
|
|
776
|
+
socket = new WebSocket(websocketURL, [WEBSOCKET_PROTOCOL_BINARY]);
|
|
777
|
+
socket.addEventListener("open", handleOpen);
|
|
778
|
+
socket.addEventListener("close", handleClose);
|
|
779
|
+
socket.addEventListener("error", handleError);
|
|
780
|
+
socket.addEventListener("message", handleMessage);
|
|
781
|
+
disposeSocket = () => {
|
|
782
|
+
window.clearTimeout(retryWaitTimeoutId);
|
|
783
|
+
socket.removeEventListener("open", handleOpen);
|
|
784
|
+
socket.removeEventListener("close", handleClose);
|
|
785
|
+
socket.removeEventListener("error", handleError);
|
|
786
|
+
socket.removeEventListener("message", handleMessage);
|
|
787
|
+
};
|
|
788
|
+
};
|
|
789
|
+
attemptSocketConnection();
|
|
790
|
+
})
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
25
794
|
/** Name of the feature. */
|
|
26
795
|
const StandardConnect = 'standard:connect';
|
|
27
796
|
|
|
@@ -3100,82 +3869,7 @@ function requireBrowser () {
|
|
|
3100
3869
|
return browser;
|
|
3101
3870
|
}
|
|
3102
3871
|
|
|
3103
|
-
|
|
3104
|
-
var QRCode = /*@__PURE__*/index.getDefaultExportFromCjs(browserExports);
|
|
3105
|
-
|
|
3106
|
-
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3107
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3108
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
3109
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
3110
|
-
};
|
|
3111
|
-
var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3112
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3113
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
3114
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
3115
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
3116
|
-
};
|
|
3117
|
-
var _RegisterWalletEvent_detail;
|
|
3118
|
-
/**
|
|
3119
|
-
* Register a {@link "@wallet-standard/base".Wallet} as a Standard Wallet with the app.
|
|
3120
|
-
*
|
|
3121
|
-
* This dispatches a {@link "@wallet-standard/base".WindowRegisterWalletEvent} to notify the app that the Wallet is
|
|
3122
|
-
* ready to be registered.
|
|
3123
|
-
*
|
|
3124
|
-
* This also adds a listener for {@link "@wallet-standard/base".WindowAppReadyEvent} to listen for a notification from
|
|
3125
|
-
* the app that the app is ready to register the Wallet.
|
|
3126
|
-
*
|
|
3127
|
-
* This combination of event dispatch and listener guarantees that the Wallet will be registered synchronously as soon
|
|
3128
|
-
* as the app is ready whether the Wallet loads before or after the app.
|
|
3129
|
-
*
|
|
3130
|
-
* @param wallet Wallet to register.
|
|
3131
|
-
*
|
|
3132
|
-
* @group Wallet
|
|
3133
|
-
*/
|
|
3134
|
-
function registerWallet(wallet) {
|
|
3135
|
-
const callback = ({ register }) => register(wallet);
|
|
3136
|
-
try {
|
|
3137
|
-
window.dispatchEvent(new RegisterWalletEvent(callback));
|
|
3138
|
-
}
|
|
3139
|
-
catch (error) {
|
|
3140
|
-
console.error('wallet-standard:register-wallet event could not be dispatched\n', error);
|
|
3141
|
-
}
|
|
3142
|
-
try {
|
|
3143
|
-
window.addEventListener('wallet-standard:app-ready', ({ detail: api }) => callback(api));
|
|
3144
|
-
}
|
|
3145
|
-
catch (error) {
|
|
3146
|
-
console.error('wallet-standard:app-ready event listener could not be added\n', error);
|
|
3147
|
-
}
|
|
3148
|
-
}
|
|
3149
|
-
class RegisterWalletEvent extends Event {
|
|
3150
|
-
get detail() {
|
|
3151
|
-
return __classPrivateFieldGet(this, _RegisterWalletEvent_detail, "f");
|
|
3152
|
-
}
|
|
3153
|
-
get type() {
|
|
3154
|
-
return 'wallet-standard:register-wallet';
|
|
3155
|
-
}
|
|
3156
|
-
constructor(callback) {
|
|
3157
|
-
super('wallet-standard:register-wallet', {
|
|
3158
|
-
bubbles: false,
|
|
3159
|
-
cancelable: false,
|
|
3160
|
-
composed: false,
|
|
3161
|
-
});
|
|
3162
|
-
_RegisterWalletEvent_detail.set(this, void 0);
|
|
3163
|
-
__classPrivateFieldSet(this, _RegisterWalletEvent_detail, callback, "f");
|
|
3164
|
-
}
|
|
3165
|
-
/** @deprecated */
|
|
3166
|
-
preventDefault() {
|
|
3167
|
-
throw new Error('preventDefault cannot be called');
|
|
3168
|
-
}
|
|
3169
|
-
/** @deprecated */
|
|
3170
|
-
stopImmediatePropagation() {
|
|
3171
|
-
throw new Error('stopImmediatePropagation cannot be called');
|
|
3172
|
-
}
|
|
3173
|
-
/** @deprecated */
|
|
3174
|
-
stopPropagation() {
|
|
3175
|
-
throw new Error('stopPropagation cannot be called');
|
|
3176
|
-
}
|
|
3177
|
-
}
|
|
3178
|
-
_RegisterWalletEvent_detail = new WeakMap();
|
|
3872
|
+
requireBrowser();
|
|
3179
3873
|
|
|
3180
3874
|
//#region src/base64Utils.ts
|
|
3181
3875
|
function fromUint8Array(byteArray) {
|
|
@@ -3485,361 +4179,79 @@ var EmbeddedModal = class {
|
|
|
3485
4179
|
};
|
|
3486
4180
|
};
|
|
3487
4181
|
//#endregion
|
|
3488
|
-
//#region src/embedded-modal/
|
|
3489
|
-
var
|
|
3490
|
-
contentStyles = css$
|
|
3491
|
-
contentHtml =
|
|
3492
|
-
|
|
4182
|
+
//#region src/embedded-modal/localConnectionModal.ts
|
|
4183
|
+
var LocalConnectionModal = class extends EmbeddedModal {
|
|
4184
|
+
contentStyles = css$3;
|
|
4185
|
+
contentHtml = ErrorDialogHtml$3;
|
|
4186
|
+
initWithCallback(callback) {
|
|
3493
4187
|
super.init();
|
|
3494
|
-
this
|
|
4188
|
+
this.#prepareLaunchAction(callback);
|
|
3495
4189
|
}
|
|
3496
|
-
|
|
3497
|
-
const
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
else qrcodeContainer.appendChild(qrCodeElement);
|
|
3505
|
-
const qrPlaceholder = this.dom?.getElementById("mobile-wallet-adapter-embedded-modal-qr-placeholder");
|
|
3506
|
-
if (qrPlaceholder) qrPlaceholder.style.display = "none";
|
|
3507
|
-
} else console.error("QRCode Container not found");
|
|
4190
|
+
#prepareLaunchAction(callback) {
|
|
4191
|
+
const launchButton = this.dom?.getElementById("mobile-wallet-adapter-launch-action");
|
|
4192
|
+
const listener = async () => {
|
|
4193
|
+
launchButton?.removeEventListener("click", listener);
|
|
4194
|
+
this.close();
|
|
4195
|
+
callback();
|
|
4196
|
+
};
|
|
4197
|
+
launchButton?.addEventListener("click", listener);
|
|
3508
4198
|
}
|
|
3509
4199
|
};
|
|
3510
|
-
const
|
|
3511
|
-
<
|
|
3512
|
-
<
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
<
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
<
|
|
3521
|
-
<
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
</
|
|
3530
|
-
<div class="mobile-wallet-adapter-embedded-modal-divider"><hr></div>
|
|
3531
|
-
<div class="mobile-wallet-adapter-embedded-modal-footer">
|
|
3532
|
-
<div class="mobile-wallet-adapter-embedded-modal-subtitle">
|
|
3533
|
-
Follow the instructions on your device. When you're finished, this screen will update.
|
|
3534
|
-
</div>
|
|
3535
|
-
<div class="mobile-wallet-adapter-embedded-modal-progress-badge">
|
|
3536
|
-
<div>
|
|
3537
|
-
<div class="spinner">
|
|
3538
|
-
<div class="leftWrapper">
|
|
3539
|
-
<div class="left">
|
|
3540
|
-
<div class="circle"></div>
|
|
3541
|
-
</div>
|
|
3542
|
-
</div>
|
|
3543
|
-
<div class="rightWrapper">
|
|
3544
|
-
<div class="right">
|
|
3545
|
-
<div class="circle"></div>
|
|
3546
|
-
</div>
|
|
3547
|
-
</div>
|
|
3548
|
-
</div>
|
|
3549
|
-
</div>
|
|
3550
|
-
<div>Waiting for scan</div>
|
|
3551
|
-
</div>
|
|
4200
|
+
const ErrorDialogHtml$3 = `
|
|
4201
|
+
<svg class="mobile-wallet-adapter-embedded-modal-launch-icon" width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
4202
|
+
<path d="M21.6 48C7.2 48 0 40.8 0 26.4V21.6C0 7.2 7.2 0 21.6 0H26.4C40.8 0 48 7.2 48 21.6V26.4C48 40.8 40.8 48 26.4 48H21.6Z" fill="#15994E"/>
|
|
4203
|
+
<mask id="mask0_189_522" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="8" width="32" height="32">
|
|
4204
|
+
<rect x="8" y="8" width="32" height="32" fill="#D9D9D9"/>
|
|
4205
|
+
</mask>
|
|
4206
|
+
<g mask="url(#mask0_189_522)">
|
|
4207
|
+
<mask id="mask1_189_522" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="8" width="32" height="32">
|
|
4208
|
+
<rect x="8" y="8" width="32" height="32" fill="#D9D9D9"/>
|
|
4209
|
+
</mask>
|
|
4210
|
+
<g mask="url(#mask1_189_522)">
|
|
4211
|
+
<path d="M22.1092 26.1208L19.4498 23.4615C19.1736 23.1851 18.8253 23.0468 18.4048 23.0468C17.9846 23.0468 17.6363 23.1851 17.3598 23.4615C17.0836 23.7377 16.9468 24.0861 16.9495 24.5065C16.9522 24.9267 17.0916 25.275 17.3678 25.5512L21.0405 29.2238C21.3463 29.5276 21.7031 29.6795 22.1108 29.6795C22.5184 29.6795 22.8742 29.5276 23.1782 29.2238L30.5918 21.8098C30.8683 21.5336 31.0065 21.1867 31.0065 20.7692C31.0065 20.3514 30.8683 20.0044 30.5918 19.7282C30.3156 19.4517 29.9673 19.3135 29.5468 19.3135C29.1266 19.3135 28.7784 19.4517 28.5022 19.7282L22.1092 26.1208ZM23.9998 37.6042C22.113 37.6042 20.3425 37.2473 18.6885 36.5335C17.0343 35.8197 15.5954 34.8512 14.3718 33.6278C13.1485 32.4043 12.18 30.9654 11.4662 29.3112C10.7524 27.6572 10.3955 25.8867 10.3955 23.9998C10.3955 22.113 10.7524 20.3425 11.4662 18.6885C12.18 17.0343 13.1485 15.5954 14.3718 14.3718C15.5954 13.1485 17.0343 12.18 18.6885 11.4662C20.3425 10.7524 22.113 10.3955 23.9998 10.3955C25.8867 10.3955 27.6572 10.7524 29.3112 11.4662C30.9654 12.18 32.4043 13.1485 33.6278 14.3718C34.8512 15.5954 35.8197 17.0343 36.5335 18.6885C37.2473 20.3425 37.6042 22.113 37.6042 23.9998C37.6042 25.8867 37.2473 27.6572 36.5335 29.3112C35.8197 30.9654 34.8512 32.4043 33.6278 33.6278C32.4043 34.8512 30.9654 35.8197 29.3112 36.5335C27.6572 37.2473 25.8867 37.6042 23.9998 37.6042Z" fill="white"/>
|
|
4212
|
+
</g>
|
|
4213
|
+
</g>
|
|
4214
|
+
</svg>
|
|
4215
|
+
<div class="mobile-wallet-adapter-embedded-modal-title">Ready to connect!</div>
|
|
4216
|
+
<div>
|
|
4217
|
+
<button data-modal-action id="mobile-wallet-adapter-launch-action" class="mobile-wallet-adapter-embedded-modal-launch-action">
|
|
4218
|
+
Connect Wallet
|
|
4219
|
+
</button>
|
|
3552
4220
|
</div>
|
|
3553
4221
|
`;
|
|
3554
|
-
const css$
|
|
3555
|
-
.mobile-wallet-adapter-embedded-modal-
|
|
3556
|
-
display:
|
|
3557
|
-
margin-top: 10px;
|
|
3558
|
-
padding: 10px;
|
|
3559
|
-
}
|
|
3560
|
-
|
|
3561
|
-
.mobile-wallet-adapter-embedded-modal-qr-content > div:first-child {
|
|
3562
|
-
display: flex;
|
|
3563
|
-
flex-direction: column;
|
|
3564
|
-
flex: 2;
|
|
3565
|
-
margin-top: auto;
|
|
3566
|
-
margin-right: 30px;
|
|
4222
|
+
const css$3 = `
|
|
4223
|
+
.mobile-wallet-adapter-embedded-modal-close {
|
|
4224
|
+
display: none;
|
|
3567
4225
|
}
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
flex-direction: column;
|
|
3572
|
-
flex: 1;
|
|
3573
|
-
margin-left: auto;
|
|
4226
|
+
.mobile-wallet-adapter-embedded-modal-content {
|
|
4227
|
+
text-align: center;
|
|
4228
|
+
min-width: 300px;
|
|
3574
4229
|
}
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
display: flex;
|
|
3578
|
-
padding: 10px;
|
|
4230
|
+
.mobile-wallet-adapter-embedded-modal-launch-icon {
|
|
4231
|
+
margin-top: 24px;
|
|
3579
4232
|
}
|
|
3580
|
-
|
|
3581
|
-
.mobile-wallet-adapter-embedded-modal-icon {}
|
|
3582
|
-
|
|
3583
4233
|
.mobile-wallet-adapter-embedded-modal-title {
|
|
4234
|
+
margin: 18px 100px 30px 100px;
|
|
3584
4235
|
color: #000000;
|
|
3585
|
-
font-size: 2.
|
|
4236
|
+
font-size: 2.75em;
|
|
3586
4237
|
font-weight: 600;
|
|
3587
4238
|
}
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
4239
|
+
.mobile-wallet-adapter-embedded-modal-launch-action {
|
|
4240
|
+
display: block;
|
|
4241
|
+
width: 100%;
|
|
4242
|
+
height: 56px;
|
|
4243
|
+
font-size: 1.25em;
|
|
4244
|
+
background: #000000;
|
|
4245
|
+
color: #FFFFFF;
|
|
4246
|
+
border-radius: 18px;
|
|
3592
4247
|
}
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
min-width: 200px;
|
|
3601
|
-
min-height: 200px;
|
|
3602
|
-
background: linear-gradient(-60deg, #F7F8F8 30%, #ECEEEE 50%, #F7F8F8 70%);
|
|
3603
|
-
background-size: 200%;
|
|
3604
|
-
animation: placeholderAnimate 2.7s linear infinite;
|
|
3605
|
-
border-radius: 12px;
|
|
3606
|
-
}
|
|
3607
|
-
|
|
3608
|
-
.mobile-wallet-adapter-embedded-modal-divider {
|
|
3609
|
-
margin-top: 20px;
|
|
3610
|
-
padding-left: 10px;
|
|
3611
|
-
padding-right: 10px;
|
|
3612
|
-
}
|
|
3613
|
-
|
|
3614
|
-
.mobile-wallet-adapter-embedded-modal-divider hr {
|
|
3615
|
-
border-top: 1px solid #D9DEDE;
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
.mobile-wallet-adapter-embedded-modal-subtitle {
|
|
3619
|
-
margin: auto;
|
|
3620
|
-
margin-right: 60px;
|
|
3621
|
-
padding: 20px;
|
|
3622
|
-
color: #6E8286;
|
|
3623
|
-
}
|
|
3624
|
-
|
|
3625
|
-
.mobile-wallet-adapter-embedded-modal-progress-badge {
|
|
3626
|
-
display: flex;
|
|
3627
|
-
background: #F7F8F8;
|
|
3628
|
-
height: 56px;
|
|
3629
|
-
min-width: 200px;
|
|
3630
|
-
margin: auto;
|
|
3631
|
-
padding-left: 20px;
|
|
3632
|
-
padding-right: 20px;
|
|
3633
|
-
border-radius: 18px;
|
|
3634
|
-
color: #A8B6B8;
|
|
3635
|
-
align-items: center;
|
|
3636
|
-
}
|
|
3637
|
-
|
|
3638
|
-
.mobile-wallet-adapter-embedded-modal-progress-badge > div:first-child {
|
|
3639
|
-
margin-left: auto;
|
|
3640
|
-
margin-right: 20px;
|
|
3641
|
-
}
|
|
3642
|
-
|
|
3643
|
-
.mobile-wallet-adapter-embedded-modal-progress-badge > div:nth-child(2) {
|
|
3644
|
-
margin-right: auto;
|
|
3645
|
-
}
|
|
3646
|
-
|
|
3647
|
-
/* Smaller screens */
|
|
3648
|
-
@media all and (max-width: 600px) {
|
|
3649
|
-
.mobile-wallet-adapter-embedded-modal-card {
|
|
3650
|
-
text-align: center;
|
|
3651
|
-
}
|
|
3652
|
-
.mobile-wallet-adapter-embedded-modal-qr-content {
|
|
3653
|
-
flex-direction: column;
|
|
3654
|
-
}
|
|
3655
|
-
.mobile-wallet-adapter-embedded-modal-qr-content > div:first-child {
|
|
3656
|
-
margin: auto;
|
|
3657
|
-
}
|
|
3658
|
-
.mobile-wallet-adapter-embedded-modal-qr-content > div:nth-child(2) {
|
|
3659
|
-
margin: auto;
|
|
3660
|
-
flex: 2 auto;
|
|
3661
|
-
}
|
|
3662
|
-
.mobile-wallet-adapter-embedded-modal-footer {
|
|
3663
|
-
flex-direction: column;
|
|
3664
|
-
}
|
|
3665
|
-
.mobile-wallet-adapter-embedded-modal-icon {
|
|
3666
|
-
display: none;
|
|
3667
|
-
}
|
|
3668
|
-
.mobile-wallet-adapter-embedded-modal-title {
|
|
3669
|
-
font-size: 1.5em;
|
|
3670
|
-
}
|
|
3671
|
-
.mobile-wallet-adapter-embedded-modal-subtitle {
|
|
3672
|
-
margin-right: unset;
|
|
3673
|
-
}
|
|
3674
|
-
.mobile-wallet-adapter-embedded-modal-qr-label {
|
|
3675
|
-
text-align: center;
|
|
3676
|
-
}
|
|
3677
|
-
.mobile-wallet-adapter-embedded-modal-qr-code-container {
|
|
3678
|
-
margin: auto;
|
|
3679
|
-
}
|
|
3680
|
-
.mobile-wallet-adapter-embedded-modal-qr-placeholder {
|
|
3681
|
-
margin: auto;
|
|
3682
|
-
}
|
|
3683
|
-
}
|
|
3684
|
-
|
|
3685
|
-
/* QR Placeholder */
|
|
3686
|
-
@keyframes placeholderAnimate {
|
|
3687
|
-
0% { background-position: 200% 0; }
|
|
3688
|
-
100% { background-position: -200% 0; }
|
|
3689
|
-
}
|
|
3690
|
-
|
|
3691
|
-
/* Spinner */
|
|
3692
|
-
@keyframes spinLeft {
|
|
3693
|
-
0% {
|
|
3694
|
-
transform: rotate(20deg);
|
|
3695
|
-
}
|
|
3696
|
-
50% {
|
|
3697
|
-
transform: rotate(160deg);
|
|
3698
|
-
}
|
|
3699
|
-
100% {
|
|
3700
|
-
transform: rotate(20deg);
|
|
3701
|
-
}
|
|
3702
|
-
}
|
|
3703
|
-
@keyframes spinRight {
|
|
3704
|
-
0% {
|
|
3705
|
-
transform: rotate(160deg);
|
|
3706
|
-
}
|
|
3707
|
-
50% {
|
|
3708
|
-
transform: rotate(20deg);
|
|
3709
|
-
}
|
|
3710
|
-
100% {
|
|
3711
|
-
transform: rotate(160deg);
|
|
3712
|
-
}
|
|
3713
|
-
}
|
|
3714
|
-
@keyframes spin {
|
|
3715
|
-
0% {
|
|
3716
|
-
transform: rotate(0deg);
|
|
3717
|
-
}
|
|
3718
|
-
100% {
|
|
3719
|
-
transform: rotate(2520deg);
|
|
3720
|
-
}
|
|
3721
|
-
}
|
|
3722
|
-
|
|
3723
|
-
.spinner {
|
|
3724
|
-
position: relative;
|
|
3725
|
-
width: 1.5em;
|
|
3726
|
-
height: 1.5em;
|
|
3727
|
-
margin: auto;
|
|
3728
|
-
animation: spin 10s linear infinite;
|
|
3729
|
-
}
|
|
3730
|
-
.spinner::before {
|
|
3731
|
-
content: "";
|
|
3732
|
-
position: absolute;
|
|
3733
|
-
top: 0;
|
|
3734
|
-
bottom: 0;
|
|
3735
|
-
left: 0;
|
|
3736
|
-
right: 0;
|
|
3737
|
-
}
|
|
3738
|
-
.right, .rightWrapper, .left, .leftWrapper {
|
|
3739
|
-
position: absolute;
|
|
3740
|
-
top: 0;
|
|
3741
|
-
overflow: hidden;
|
|
3742
|
-
width: .75em;
|
|
3743
|
-
height: 1.5em;
|
|
3744
|
-
}
|
|
3745
|
-
.left, .leftWrapper {
|
|
3746
|
-
left: 0;
|
|
3747
|
-
}
|
|
3748
|
-
.right {
|
|
3749
|
-
left: -12px;
|
|
3750
|
-
}
|
|
3751
|
-
.rightWrapper {
|
|
3752
|
-
right: 0;
|
|
3753
|
-
}
|
|
3754
|
-
.circle {
|
|
3755
|
-
border: .125em solid #A8B6B8;
|
|
3756
|
-
width: 1.25em; /* 1.5em - 2*0.125em border */
|
|
3757
|
-
height: 1.25em; /* 1.5em - 2*0.125em border */
|
|
3758
|
-
border-radius: 0.75em; /* 0.5*1.5em spinner size 8 */
|
|
3759
|
-
}
|
|
3760
|
-
.left {
|
|
3761
|
-
transform-origin: 100% 50%;
|
|
3762
|
-
animation: spinLeft 2.5s cubic-bezier(.2,0,.8,1) infinite;
|
|
3763
|
-
}
|
|
3764
|
-
.right {
|
|
3765
|
-
transform-origin: 100% 50%;
|
|
3766
|
-
animation: spinRight 2.5s cubic-bezier(.2,0,.8,1) infinite;
|
|
3767
|
-
}
|
|
3768
|
-
`;
|
|
3769
|
-
//#endregion
|
|
3770
|
-
//#region src/embedded-modal/localConnectionModal.ts
|
|
3771
|
-
var LocalConnectionModal = class extends EmbeddedModal {
|
|
3772
|
-
contentStyles = css$3;
|
|
3773
|
-
contentHtml = ErrorDialogHtml$3;
|
|
3774
|
-
initWithCallback(callback) {
|
|
3775
|
-
super.init();
|
|
3776
|
-
this.#prepareLaunchAction(callback);
|
|
3777
|
-
}
|
|
3778
|
-
#prepareLaunchAction(callback) {
|
|
3779
|
-
const launchButton = this.dom?.getElementById("mobile-wallet-adapter-launch-action");
|
|
3780
|
-
const listener = async () => {
|
|
3781
|
-
launchButton?.removeEventListener("click", listener);
|
|
3782
|
-
this.close();
|
|
3783
|
-
callback();
|
|
3784
|
-
};
|
|
3785
|
-
launchButton?.addEventListener("click", listener);
|
|
3786
|
-
}
|
|
3787
|
-
};
|
|
3788
|
-
const ErrorDialogHtml$3 = `
|
|
3789
|
-
<svg class="mobile-wallet-adapter-embedded-modal-launch-icon" width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3790
|
-
<path d="M21.6 48C7.2 48 0 40.8 0 26.4V21.6C0 7.2 7.2 0 21.6 0H26.4C40.8 0 48 7.2 48 21.6V26.4C48 40.8 40.8 48 26.4 48H21.6Z" fill="#15994E"/>
|
|
3791
|
-
<mask id="mask0_189_522" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="8" width="32" height="32">
|
|
3792
|
-
<rect x="8" y="8" width="32" height="32" fill="#D9D9D9"/>
|
|
3793
|
-
</mask>
|
|
3794
|
-
<g mask="url(#mask0_189_522)">
|
|
3795
|
-
<mask id="mask1_189_522" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="8" width="32" height="32">
|
|
3796
|
-
<rect x="8" y="8" width="32" height="32" fill="#D9D9D9"/>
|
|
3797
|
-
</mask>
|
|
3798
|
-
<g mask="url(#mask1_189_522)">
|
|
3799
|
-
<path d="M22.1092 26.1208L19.4498 23.4615C19.1736 23.1851 18.8253 23.0468 18.4048 23.0468C17.9846 23.0468 17.6363 23.1851 17.3598 23.4615C17.0836 23.7377 16.9468 24.0861 16.9495 24.5065C16.9522 24.9267 17.0916 25.275 17.3678 25.5512L21.0405 29.2238C21.3463 29.5276 21.7031 29.6795 22.1108 29.6795C22.5184 29.6795 22.8742 29.5276 23.1782 29.2238L30.5918 21.8098C30.8683 21.5336 31.0065 21.1867 31.0065 20.7692C31.0065 20.3514 30.8683 20.0044 30.5918 19.7282C30.3156 19.4517 29.9673 19.3135 29.5468 19.3135C29.1266 19.3135 28.7784 19.4517 28.5022 19.7282L22.1092 26.1208ZM23.9998 37.6042C22.113 37.6042 20.3425 37.2473 18.6885 36.5335C17.0343 35.8197 15.5954 34.8512 14.3718 33.6278C13.1485 32.4043 12.18 30.9654 11.4662 29.3112C10.7524 27.6572 10.3955 25.8867 10.3955 23.9998C10.3955 22.113 10.7524 20.3425 11.4662 18.6885C12.18 17.0343 13.1485 15.5954 14.3718 14.3718C15.5954 13.1485 17.0343 12.18 18.6885 11.4662C20.3425 10.7524 22.113 10.3955 23.9998 10.3955C25.8867 10.3955 27.6572 10.7524 29.3112 11.4662C30.9654 12.18 32.4043 13.1485 33.6278 14.3718C34.8512 15.5954 35.8197 17.0343 36.5335 18.6885C37.2473 20.3425 37.6042 22.113 37.6042 23.9998C37.6042 25.8867 37.2473 27.6572 36.5335 29.3112C35.8197 30.9654 34.8512 32.4043 33.6278 33.6278C32.4043 34.8512 30.9654 35.8197 29.3112 36.5335C27.6572 37.2473 25.8867 37.6042 23.9998 37.6042Z" fill="white"/>
|
|
3800
|
-
</g>
|
|
3801
|
-
</g>
|
|
3802
|
-
</svg>
|
|
3803
|
-
<div class="mobile-wallet-adapter-embedded-modal-title">Ready to connect!</div>
|
|
3804
|
-
<div>
|
|
3805
|
-
<button data-modal-action id="mobile-wallet-adapter-launch-action" class="mobile-wallet-adapter-embedded-modal-launch-action">
|
|
3806
|
-
Connect Wallet
|
|
3807
|
-
</button>
|
|
3808
|
-
</div>
|
|
3809
|
-
`;
|
|
3810
|
-
const css$3 = `
|
|
3811
|
-
.mobile-wallet-adapter-embedded-modal-close {
|
|
3812
|
-
display: none;
|
|
3813
|
-
}
|
|
3814
|
-
.mobile-wallet-adapter-embedded-modal-content {
|
|
3815
|
-
text-align: center;
|
|
3816
|
-
min-width: 300px;
|
|
3817
|
-
}
|
|
3818
|
-
.mobile-wallet-adapter-embedded-modal-launch-icon {
|
|
3819
|
-
margin-top: 24px;
|
|
3820
|
-
}
|
|
3821
|
-
.mobile-wallet-adapter-embedded-modal-title {
|
|
3822
|
-
margin: 18px 100px 30px 100px;
|
|
3823
|
-
color: #000000;
|
|
3824
|
-
font-size: 2.75em;
|
|
3825
|
-
font-weight: 600;
|
|
3826
|
-
}
|
|
3827
|
-
.mobile-wallet-adapter-embedded-modal-launch-action {
|
|
3828
|
-
display: block;
|
|
3829
|
-
width: 100%;
|
|
3830
|
-
height: 56px;
|
|
3831
|
-
font-size: 1.25em;
|
|
3832
|
-
background: #000000;
|
|
3833
|
-
color: #FFFFFF;
|
|
3834
|
-
border-radius: 18px;
|
|
3835
|
-
}
|
|
3836
|
-
/* Smaller screens */
|
|
3837
|
-
@media all and (max-width: 600px) {
|
|
3838
|
-
.mobile-wallet-adapter-embedded-modal-title {
|
|
3839
|
-
font-size: 1.5em;
|
|
3840
|
-
margin-right: 12px;
|
|
3841
|
-
margin-left: 12px;
|
|
3842
|
-
}
|
|
4248
|
+
/* Smaller screens */
|
|
4249
|
+
@media all and (max-width: 600px) {
|
|
4250
|
+
.mobile-wallet-adapter-embedded-modal-title {
|
|
4251
|
+
font-size: 1.5em;
|
|
4252
|
+
margin-right: 12px;
|
|
4253
|
+
margin-left: 12px;
|
|
4254
|
+
}
|
|
3843
4255
|
}
|
|
3844
4256
|
`;
|
|
3845
4257
|
//#endregion
|
|
@@ -4097,17 +4509,6 @@ const css$1 = `
|
|
|
4097
4509
|
}
|
|
4098
4510
|
}
|
|
4099
4511
|
`;
|
|
4100
|
-
//#endregion
|
|
4101
|
-
//#region src/getIsSupported.ts
|
|
4102
|
-
function getIsLocalAssociationSupported() {
|
|
4103
|
-
return typeof window !== "undefined" && window.isSecureContext && typeof document !== "undefined" && /android/i.test(navigator.userAgent);
|
|
4104
|
-
}
|
|
4105
|
-
function getIsRemoteAssociationSupported() {
|
|
4106
|
-
return typeof window !== "undefined" && window.isSecureContext && typeof document !== "undefined" && !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
4107
|
-
}
|
|
4108
|
-
function isWebView(userAgentString) {
|
|
4109
|
-
return /(WebView|Version\/.+(Chrome)\/(\d+)\.(\d+)\.(\d+)\.(\d+)|; wv\).+(Chrome)\/(\d+)\.(\d+)\.(\d+)\.(\d+))/i.test(userAgentString);
|
|
4110
|
-
}
|
|
4111
4512
|
function isSolanaMobileWebShell(userAgentString) {
|
|
4112
4513
|
return userAgentString.includes("Solana Mobile Web Shell");
|
|
4113
4514
|
}
|
|
@@ -4128,12 +4529,12 @@ async function checkLocalNetworkAccessPermission() {
|
|
|
4128
4529
|
const modal = new LoopbackPermissionBlockedModal();
|
|
4129
4530
|
modal.init();
|
|
4130
4531
|
modal.open();
|
|
4131
|
-
throw new
|
|
4532
|
+
throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, "Local Network Access permission denied");
|
|
4132
4533
|
} else if (lnaPermission.state === "prompt") {
|
|
4133
4534
|
const modal = new LoopbackPermissionModal();
|
|
4134
4535
|
if (await new Promise((resolve, reject) => {
|
|
4135
4536
|
modal.addEventListener("close", (event) => {
|
|
4136
|
-
if (event) reject(new
|
|
4537
|
+
if (event) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection cancelled by user", { event }));
|
|
4137
4538
|
});
|
|
4138
4539
|
lnaPermission.onchange = () => {
|
|
4139
4540
|
lnaPermission.onchange = null;
|
|
@@ -4145,7 +4546,7 @@ async function checkLocalNetworkAccessPermission() {
|
|
|
4145
4546
|
const modal = new LocalConnectionModal();
|
|
4146
4547
|
await new Promise((resolve, reject) => {
|
|
4147
4548
|
modal.addEventListener("close", (event) => {
|
|
4148
|
-
if (event) reject(new
|
|
4549
|
+
if (event) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection cancelled by user", { event }));
|
|
4149
4550
|
});
|
|
4150
4551
|
modal.initWithCallback(async () => {
|
|
4151
4552
|
resolve(true);
|
|
@@ -4155,11 +4556,11 @@ async function checkLocalNetworkAccessPermission() {
|
|
|
4155
4556
|
return;
|
|
4156
4557
|
} else return await checkLocalNetworkAccessPermission();
|
|
4157
4558
|
}
|
|
4158
|
-
throw new
|
|
4559
|
+
throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, "Local Network Access permission unknown");
|
|
4159
4560
|
} catch (e) {
|
|
4160
4561
|
if (e instanceof TypeError && (e.message.includes("loopback-network") || e.message.includes("local-network-access"))) return;
|
|
4161
|
-
if (e instanceof
|
|
4162
|
-
throw new
|
|
4562
|
+
if (e instanceof SolanaMobileWalletAdapterError) throw e;
|
|
4563
|
+
throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, e instanceof Error ? e.message : "Local Network Access permission unknown");
|
|
4163
4564
|
}
|
|
4164
4565
|
}
|
|
4165
4566
|
//#endregion
|
|
@@ -4168,7 +4569,6 @@ const icon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZp
|
|
|
4168
4569
|
//#endregion
|
|
4169
4570
|
//#region src/wallet.ts
|
|
4170
4571
|
const SolanaMobileWalletAdapterWalletName = "Mobile Wallet Adapter";
|
|
4171
|
-
const SolanaMobileWalletAdapterRemoteWalletName = "Remote Mobile Wallet Adapter";
|
|
4172
4572
|
const SIGNATURE_LENGTH_IN_BYTES = 64;
|
|
4173
4573
|
const DEFAULT_FEATURES = [
|
|
4174
4574
|
SolanaSignAndSendTransaction,
|
|
@@ -4394,7 +4794,7 @@ var LocalSolanaMobileWalletAdapterWallet = class {
|
|
|
4394
4794
|
let timeout = void 0;
|
|
4395
4795
|
const result = await Promise.race([checkLocalNetworkAccessPermission().then(async () => {
|
|
4396
4796
|
loadingSpinner.init();
|
|
4397
|
-
const { wallet, close } = await
|
|
4797
|
+
const { wallet, close } = await startScenario(config);
|
|
4398
4798
|
associating = false;
|
|
4399
4799
|
loadingSpinner.addEventListener("close", (event) => {
|
|
4400
4800
|
if (event) close();
|
|
@@ -4406,7 +4806,7 @@ var LocalSolanaMobileWalletAdapterWallet = class {
|
|
|
4406
4806
|
return result;
|
|
4407
4807
|
}), new Promise((_, reject) => {
|
|
4408
4808
|
timeout = setTimeout(() => {
|
|
4409
|
-
if (associating) reject(new
|
|
4809
|
+
if (associating) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection timed out", { event: void 0 }));
|
|
4410
4810
|
}, WALLET_ASSOCIATION_TIMEOUT);
|
|
4411
4811
|
})]);
|
|
4412
4812
|
clearTimeout(timeout);
|
|
@@ -4429,7 +4829,7 @@ var LocalSolanaMobileWalletAdapterWallet = class {
|
|
|
4429
4829
|
return accounts.map((account) => {
|
|
4430
4830
|
const publicKey = toUint8Array(account.address);
|
|
4431
4831
|
return {
|
|
4432
|
-
address:
|
|
4832
|
+
address: index_native.base58.encode(publicKey),
|
|
4433
4833
|
publicKey,
|
|
4434
4834
|
label: account.label,
|
|
4435
4835
|
icon: account.icon,
|
|
@@ -4521,355 +4921,7 @@ var LocalSolanaMobileWalletAdapterWallet = class {
|
|
|
4521
4921
|
const signedInAccount = authorizationResult.accounts.find((acc) => acc.address == signedInAddress);
|
|
4522
4922
|
return {
|
|
4523
4923
|
account: {
|
|
4524
|
-
...signedInAccount ?? { address:
|
|
4525
|
-
publicKey: toUint8Array(signedInAddress),
|
|
4526
|
-
chains: signedInAccount?.chains ?? this.#chains,
|
|
4527
|
-
features: signedInAccount?.features ?? authorizationResult.capabilities.features
|
|
4528
|
-
},
|
|
4529
|
-
signedMessage: toUint8Array(authorizationResult.sign_in_result.signed_message),
|
|
4530
|
-
signature: toUint8Array(authorizationResult.sign_in_result.signature)
|
|
4531
|
-
};
|
|
4532
|
-
} catch (e) {
|
|
4533
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4534
|
-
} finally {
|
|
4535
|
-
this.#connecting = false;
|
|
4536
|
-
}
|
|
4537
|
-
};
|
|
4538
|
-
};
|
|
4539
|
-
var RemoteSolanaMobileWalletAdapterWallet = class {
|
|
4540
|
-
#listeners = {};
|
|
4541
|
-
#version = "1.0.0";
|
|
4542
|
-
#name = SolanaMobileWalletAdapterRemoteWalletName;
|
|
4543
|
-
#url = "https://solanamobile.com/wallets";
|
|
4544
|
-
#icon = icon;
|
|
4545
|
-
#appIdentity;
|
|
4546
|
-
#authorization;
|
|
4547
|
-
#authorizationCache;
|
|
4548
|
-
#connecting = false;
|
|
4549
|
-
/**
|
|
4550
|
-
* Every time the connection is recycled in some way (eg. `disconnect()` is called)
|
|
4551
|
-
* increment this and use it to make sure that `transact` calls from the previous
|
|
4552
|
-
* 'generation' don't continue to do work and throw exceptions.
|
|
4553
|
-
*/
|
|
4554
|
-
#connectionGeneration = 0;
|
|
4555
|
-
#chains = [];
|
|
4556
|
-
#chainSelector;
|
|
4557
|
-
#optionalFeatures;
|
|
4558
|
-
#onWalletNotFound;
|
|
4559
|
-
#hostAuthority;
|
|
4560
|
-
#session;
|
|
4561
|
-
get version() {
|
|
4562
|
-
return this.#version;
|
|
4563
|
-
}
|
|
4564
|
-
get name() {
|
|
4565
|
-
return this.#name;
|
|
4566
|
-
}
|
|
4567
|
-
get url() {
|
|
4568
|
-
return this.#url;
|
|
4569
|
-
}
|
|
4570
|
-
get icon() {
|
|
4571
|
-
return this.#icon;
|
|
4572
|
-
}
|
|
4573
|
-
get chains() {
|
|
4574
|
-
return this.#chains;
|
|
4575
|
-
}
|
|
4576
|
-
get features() {
|
|
4577
|
-
return {
|
|
4578
|
-
[StandardConnect]: {
|
|
4579
|
-
version: "1.0.0",
|
|
4580
|
-
connect: this.#connect
|
|
4581
|
-
},
|
|
4582
|
-
[StandardDisconnect]: {
|
|
4583
|
-
version: "1.0.0",
|
|
4584
|
-
disconnect: this.#disconnect
|
|
4585
|
-
},
|
|
4586
|
-
[StandardEvents]: {
|
|
4587
|
-
version: "1.0.0",
|
|
4588
|
-
on: this.#on
|
|
4589
|
-
},
|
|
4590
|
-
[SolanaSignMessage]: {
|
|
4591
|
-
version: "1.0.0",
|
|
4592
|
-
signMessage: this.#signMessage
|
|
4593
|
-
},
|
|
4594
|
-
[SolanaSignIn]: {
|
|
4595
|
-
version: "1.0.0",
|
|
4596
|
-
signIn: this.#signIn
|
|
4597
|
-
},
|
|
4598
|
-
...this.#optionalFeatures
|
|
4599
|
-
};
|
|
4600
|
-
}
|
|
4601
|
-
get accounts() {
|
|
4602
|
-
return this.#authorization?.accounts ?? [];
|
|
4603
|
-
}
|
|
4604
|
-
constructor(config) {
|
|
4605
|
-
this.#authorizationCache = config.authorizationCache;
|
|
4606
|
-
this.#appIdentity = config.appIdentity;
|
|
4607
|
-
this.#chains = config.chains;
|
|
4608
|
-
this.#chainSelector = config.chainSelector;
|
|
4609
|
-
this.#hostAuthority = config.remoteHostAuthority;
|
|
4610
|
-
this.#onWalletNotFound = config.onWalletNotFound;
|
|
4611
|
-
this.#optionalFeatures = {
|
|
4612
|
-
[SolanaSignAndSendTransaction]: {
|
|
4613
|
-
version: "1.0.0",
|
|
4614
|
-
supportedTransactionVersions: ["legacy", 0],
|
|
4615
|
-
signAndSendTransaction: this.#signAndSendTransaction
|
|
4616
|
-
},
|
|
4617
|
-
[SolanaSignTransaction]: {
|
|
4618
|
-
version: "1.0.0",
|
|
4619
|
-
supportedTransactionVersions: ["legacy", 0],
|
|
4620
|
-
signTransaction: this.#signTransaction
|
|
4621
|
-
}
|
|
4622
|
-
};
|
|
4623
|
-
}
|
|
4624
|
-
get connected() {
|
|
4625
|
-
return !!this.#session && !!this.#authorization;
|
|
4626
|
-
}
|
|
4627
|
-
get isAuthorized() {
|
|
4628
|
-
return !!this.#authorization;
|
|
4629
|
-
}
|
|
4630
|
-
get currentAuthorization() {
|
|
4631
|
-
return this.#authorization;
|
|
4632
|
-
}
|
|
4633
|
-
get cachedAuthorizationResult() {
|
|
4634
|
-
return this.#authorizationCache.get();
|
|
4635
|
-
}
|
|
4636
|
-
#on = (event, listener) => {
|
|
4637
|
-
this.#listeners[event]?.push(listener) || (this.#listeners[event] = [listener]);
|
|
4638
|
-
return () => this.#off(event, listener);
|
|
4639
|
-
};
|
|
4640
|
-
#emit(event, ...args) {
|
|
4641
|
-
this.#listeners[event]?.forEach((listener) => listener.apply(null, args));
|
|
4642
|
-
}
|
|
4643
|
-
#off(event, listener) {
|
|
4644
|
-
this.#listeners[event] = this.#listeners[event]?.filter((existingListener) => listener !== existingListener);
|
|
4645
|
-
}
|
|
4646
|
-
#connect = async (_input = {}) => {
|
|
4647
|
-
if (this.#connecting || this.connected) return { accounts: this.accounts };
|
|
4648
|
-
this.#connecting = true;
|
|
4649
|
-
try {
|
|
4650
|
-
await this.#performAuthorization();
|
|
4651
|
-
} catch (e) {
|
|
4652
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4653
|
-
} finally {
|
|
4654
|
-
this.#connecting = false;
|
|
4655
|
-
}
|
|
4656
|
-
return { accounts: this.accounts };
|
|
4657
|
-
};
|
|
4658
|
-
#performAuthorization = async (signInPayload) => {
|
|
4659
|
-
try {
|
|
4660
|
-
const cachedAuthorizationResult = await this.#authorizationCache.get();
|
|
4661
|
-
if (cachedAuthorizationResult) {
|
|
4662
|
-
this.#handleAuthorizationResult(cachedAuthorizationResult);
|
|
4663
|
-
return cachedAuthorizationResult;
|
|
4664
|
-
}
|
|
4665
|
-
if (this.#session) this.#session = void 0;
|
|
4666
|
-
const selectedChain = await this.#chainSelector.select(this.#chains);
|
|
4667
|
-
return await this.#transact(async (wallet) => {
|
|
4668
|
-
const [capabilities, mwaAuthorizationResult] = await Promise.all([wallet.getCapabilities(), wallet.authorize({
|
|
4669
|
-
chain: selectedChain,
|
|
4670
|
-
identity: this.#appIdentity,
|
|
4671
|
-
sign_in_payload: signInPayload
|
|
4672
|
-
})]);
|
|
4673
|
-
const accounts = this.#accountsToWalletStandardAccounts(mwaAuthorizationResult.accounts);
|
|
4674
|
-
const authorizationResult = {
|
|
4675
|
-
...mwaAuthorizationResult,
|
|
4676
|
-
accounts,
|
|
4677
|
-
chain: selectedChain,
|
|
4678
|
-
capabilities
|
|
4679
|
-
};
|
|
4680
|
-
Promise.all([
|
|
4681
|
-
this.#handleWalletCapabilitiesResult(capabilities),
|
|
4682
|
-
this.#authorizationCache.set(authorizationResult),
|
|
4683
|
-
this.#handleAuthorizationResult(authorizationResult)
|
|
4684
|
-
]);
|
|
4685
|
-
return authorizationResult;
|
|
4686
|
-
});
|
|
4687
|
-
} catch (e) {
|
|
4688
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4689
|
-
}
|
|
4690
|
-
};
|
|
4691
|
-
#handleAuthorizationResult = async (authorization) => {
|
|
4692
|
-
const didPublicKeysChange = this.#authorization == null || this.#authorization?.accounts.length !== authorization.accounts.length || this.#authorization.accounts.some((account, ii) => account.address !== authorization.accounts[ii].address);
|
|
4693
|
-
this.#authorization = authorization;
|
|
4694
|
-
if (didPublicKeysChange) this.#emit("change", { accounts: this.accounts });
|
|
4695
|
-
};
|
|
4696
|
-
#handleWalletCapabilitiesResult = async (capabilities) => {
|
|
4697
|
-
const supportsSignTransaction = capabilities.features.includes("solana:signTransactions");
|
|
4698
|
-
const supportsSignAndSendTransaction = capabilities.supports_sign_and_send_transactions || capabilities.features.includes("solana:signAndSendTransaction");
|
|
4699
|
-
const didCapabilitiesChange = SolanaSignAndSendTransaction in this.features !== supportsSignAndSendTransaction || SolanaSignTransaction in this.features !== supportsSignTransaction;
|
|
4700
|
-
this.#optionalFeatures = {
|
|
4701
|
-
...supportsSignAndSendTransaction && { [SolanaSignAndSendTransaction]: {
|
|
4702
|
-
version: "1.0.0",
|
|
4703
|
-
supportedTransactionVersions: capabilities.supported_transaction_versions,
|
|
4704
|
-
signAndSendTransaction: this.#signAndSendTransaction
|
|
4705
|
-
} },
|
|
4706
|
-
...supportsSignTransaction && { [SolanaSignTransaction]: {
|
|
4707
|
-
version: "1.0.0",
|
|
4708
|
-
supportedTransactionVersions: capabilities.supported_transaction_versions,
|
|
4709
|
-
signTransaction: this.#signTransaction
|
|
4710
|
-
} }
|
|
4711
|
-
};
|
|
4712
|
-
if (didCapabilitiesChange) this.#emit("change", { features: this.features });
|
|
4713
|
-
};
|
|
4714
|
-
#performReauthorization = async (wallet, authToken, chain) => {
|
|
4715
|
-
try {
|
|
4716
|
-
const [capabilities, mwaAuthorizationResult] = await Promise.all([this.#authorization?.capabilities ?? await wallet.getCapabilities(), wallet.authorize({
|
|
4717
|
-
auth_token: authToken,
|
|
4718
|
-
identity: this.#appIdentity,
|
|
4719
|
-
chain
|
|
4720
|
-
})]);
|
|
4721
|
-
const accounts = this.#accountsToWalletStandardAccounts(mwaAuthorizationResult.accounts);
|
|
4722
|
-
const authorization = {
|
|
4723
|
-
...mwaAuthorizationResult,
|
|
4724
|
-
accounts,
|
|
4725
|
-
chain,
|
|
4726
|
-
capabilities
|
|
4727
|
-
};
|
|
4728
|
-
Promise.all([this.#authorizationCache.set(authorization), this.#handleAuthorizationResult(authorization)]);
|
|
4729
|
-
} catch (e) {
|
|
4730
|
-
this.#disconnect();
|
|
4731
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4732
|
-
}
|
|
4733
|
-
};
|
|
4734
|
-
#disconnect = async () => {
|
|
4735
|
-
this.#session?.close();
|
|
4736
|
-
this.#authorizationCache.clear();
|
|
4737
|
-
this.#connecting = false;
|
|
4738
|
-
this.#connectionGeneration++;
|
|
4739
|
-
this.#authorization = void 0;
|
|
4740
|
-
this.#session = void 0;
|
|
4741
|
-
this.#emit("change", { accounts: this.accounts });
|
|
4742
|
-
};
|
|
4743
|
-
#transact = async (callback) => {
|
|
4744
|
-
const walletUriBase = this.#authorization?.wallet_uri_base;
|
|
4745
|
-
const remoteConfig = {
|
|
4746
|
-
...walletUriBase ? { baseUri: walletUriBase } : void 0,
|
|
4747
|
-
remoteHostAuthority: this.#hostAuthority
|
|
4748
|
-
};
|
|
4749
|
-
const currentConnectionGeneration = this.#connectionGeneration;
|
|
4750
|
-
const modal = new RemoteConnectionModal();
|
|
4751
|
-
if (this.#session) return callback(this.#session.wallet);
|
|
4752
|
-
try {
|
|
4753
|
-
modal.init();
|
|
4754
|
-
modal.open();
|
|
4755
|
-
const { associationUrl, close, wallet } = await index_browser.startRemoteScenario(remoteConfig);
|
|
4756
|
-
const removeCloseListener = modal.addEventListener("close", (event) => {
|
|
4757
|
-
if (event) close();
|
|
4758
|
-
});
|
|
4759
|
-
modal.populateQRCode(associationUrl.toString());
|
|
4760
|
-
this.#session = {
|
|
4761
|
-
close,
|
|
4762
|
-
wallet: await wallet
|
|
4763
|
-
};
|
|
4764
|
-
removeCloseListener();
|
|
4765
|
-
modal.close();
|
|
4766
|
-
return await callback(this.#session.wallet);
|
|
4767
|
-
} catch (e) {
|
|
4768
|
-
modal.close();
|
|
4769
|
-
if (this.#connectionGeneration !== currentConnectionGeneration) await new Promise(() => {});
|
|
4770
|
-
if (e instanceof Error && e.name === "SolanaMobileWalletAdapterError" && e.code === "ERROR_WALLET_NOT_FOUND") await this.#onWalletNotFound(this);
|
|
4771
|
-
throw e;
|
|
4772
|
-
}
|
|
4773
|
-
};
|
|
4774
|
-
#assertIsAuthorized = () => {
|
|
4775
|
-
if (!this.#authorization) throw new Error("Wallet not connected");
|
|
4776
|
-
return {
|
|
4777
|
-
authToken: this.#authorization.auth_token,
|
|
4778
|
-
chain: this.#authorization.chain
|
|
4779
|
-
};
|
|
4780
|
-
};
|
|
4781
|
-
#accountsToWalletStandardAccounts = (accounts) => {
|
|
4782
|
-
return accounts.map((account) => {
|
|
4783
|
-
const publicKey = toUint8Array(account.address);
|
|
4784
|
-
return {
|
|
4785
|
-
address: index.base58.encode(publicKey),
|
|
4786
|
-
publicKey,
|
|
4787
|
-
label: account.label,
|
|
4788
|
-
icon: account.icon,
|
|
4789
|
-
chains: account.chains ?? this.#chains,
|
|
4790
|
-
features: account.features ?? DEFAULT_FEATURES
|
|
4791
|
-
};
|
|
4792
|
-
});
|
|
4793
|
-
};
|
|
4794
|
-
#performSignTransactions = async (transactions) => {
|
|
4795
|
-
const { authToken, chain } = this.#assertIsAuthorized();
|
|
4796
|
-
try {
|
|
4797
|
-
return await this.#transact(async (wallet) => {
|
|
4798
|
-
await this.#performReauthorization(wallet, authToken, chain);
|
|
4799
|
-
return (await wallet.signTransactions({ payloads: transactions.map(fromUint8Array) })).signed_payloads.map(toUint8Array);
|
|
4800
|
-
});
|
|
4801
|
-
} catch (e) {
|
|
4802
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4803
|
-
}
|
|
4804
|
-
};
|
|
4805
|
-
#performSignAndSendTransaction = async (transaction, options) => {
|
|
4806
|
-
const { authToken, chain } = this.#assertIsAuthorized();
|
|
4807
|
-
try {
|
|
4808
|
-
return await this.#transact(async (wallet) => {
|
|
4809
|
-
const [capabilities] = await Promise.all([wallet.getCapabilities(), this.#performReauthorization(wallet, authToken, chain)]);
|
|
4810
|
-
if (capabilities.supports_sign_and_send_transactions) return (await wallet.signAndSendTransactions({
|
|
4811
|
-
...options,
|
|
4812
|
-
payloads: [fromUint8Array(transaction)]
|
|
4813
|
-
})).signatures.map(toUint8Array)[0];
|
|
4814
|
-
else throw new Error("connected wallet does not support signAndSendTransaction");
|
|
4815
|
-
});
|
|
4816
|
-
} catch (e) {
|
|
4817
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4818
|
-
}
|
|
4819
|
-
};
|
|
4820
|
-
#signAndSendTransaction = async (...inputs) => {
|
|
4821
|
-
const outputs = [];
|
|
4822
|
-
for (const input of inputs) {
|
|
4823
|
-
const signature = await this.#performSignAndSendTransaction(input.transaction, input.options);
|
|
4824
|
-
outputs.push({ signature });
|
|
4825
|
-
}
|
|
4826
|
-
return outputs;
|
|
4827
|
-
};
|
|
4828
|
-
#signTransaction = async (...inputs) => {
|
|
4829
|
-
return (await this.#performSignTransactions(inputs.map(({ transaction }) => transaction))).map((signedTransaction) => {
|
|
4830
|
-
return { signedTransaction };
|
|
4831
|
-
});
|
|
4832
|
-
};
|
|
4833
|
-
#signMessage = async (...inputs) => {
|
|
4834
|
-
const { authToken, chain } = this.#assertIsAuthorized();
|
|
4835
|
-
const addresses = inputs.map(({ account }) => fromUint8Array(new Uint8Array(account.publicKey)));
|
|
4836
|
-
const messages = inputs.map(({ message }) => fromUint8Array(message));
|
|
4837
|
-
try {
|
|
4838
|
-
return await this.#transact(async (wallet) => {
|
|
4839
|
-
await this.#performReauthorization(wallet, authToken, chain);
|
|
4840
|
-
return (await wallet.signMessages({
|
|
4841
|
-
addresses,
|
|
4842
|
-
payloads: messages
|
|
4843
|
-
})).signed_payloads.map(toUint8Array).map((signedMessage) => {
|
|
4844
|
-
return {
|
|
4845
|
-
signedMessage,
|
|
4846
|
-
signature: signedMessage.slice(-SIGNATURE_LENGTH_IN_BYTES)
|
|
4847
|
-
};
|
|
4848
|
-
});
|
|
4849
|
-
});
|
|
4850
|
-
} catch (e) {
|
|
4851
|
-
throw new Error(getErrorMessage(e), { cause: e });
|
|
4852
|
-
}
|
|
4853
|
-
};
|
|
4854
|
-
#signIn = async (...inputs) => {
|
|
4855
|
-
const outputs = [];
|
|
4856
|
-
if (inputs.length > 1) for (const input of inputs) outputs.push(await this.#performSignIn(input));
|
|
4857
|
-
else return [await this.#performSignIn(inputs[0])];
|
|
4858
|
-
return outputs;
|
|
4859
|
-
};
|
|
4860
|
-
#performSignIn = async (input) => {
|
|
4861
|
-
this.#connecting = true;
|
|
4862
|
-
try {
|
|
4863
|
-
const authorizationResult = await this.#performAuthorization({
|
|
4864
|
-
...input,
|
|
4865
|
-
domain: input?.domain ?? window.location.host
|
|
4866
|
-
});
|
|
4867
|
-
if (!authorizationResult.sign_in_result) throw new Error("Sign in failed, no sign in result returned by wallet");
|
|
4868
|
-
const signedInAddress = authorizationResult.sign_in_result.address;
|
|
4869
|
-
const signedInAccount = authorizationResult.accounts.find((acc) => acc.address == signedInAddress);
|
|
4870
|
-
return {
|
|
4871
|
-
account: {
|
|
4872
|
-
...signedInAccount ?? { address: index.base58.encode(toUint8Array(signedInAddress)) },
|
|
4924
|
+
...signedInAccount ?? { address: index_native.base58.encode(toUint8Array(signedInAddress)) },
|
|
4873
4925
|
publicKey: toUint8Array(signedInAddress),
|
|
4874
4926
|
chains: signedInAccount?.chains ?? this.#chains,
|
|
4875
4927
|
features: signedInAccount?.features ?? authorizationResult.capabilities.features
|
|
@@ -4885,24 +4937,6 @@ var RemoteSolanaMobileWalletAdapterWallet = class {
|
|
|
4885
4937
|
};
|
|
4886
4938
|
};
|
|
4887
4939
|
//#endregion
|
|
4888
|
-
//#region src/initialize.ts
|
|
4889
|
-
function registerMwa(config) {
|
|
4890
|
-
if (typeof window === "undefined") {
|
|
4891
|
-
console.warn(`MWA not registered: no window object`);
|
|
4892
|
-
return;
|
|
4893
|
-
}
|
|
4894
|
-
if (!window.isSecureContext) {
|
|
4895
|
-
console.warn(`MWA not registered: secure context required (https)`);
|
|
4896
|
-
return;
|
|
4897
|
-
}
|
|
4898
|
-
const userAgent = navigator.userAgent;
|
|
4899
|
-
if (getIsLocalAssociationSupported() && (!isWebView(userAgent) || isSolanaMobileWebShell(userAgent))) registerWallet(new LocalSolanaMobileWalletAdapterWallet(config));
|
|
4900
|
-
else if (getIsRemoteAssociationSupported() && config.remoteHostAuthority !== void 0) registerWallet(new RemoteSolanaMobileWalletAdapterWallet({
|
|
4901
|
-
...config,
|
|
4902
|
-
remoteHostAuthority: config.remoteHostAuthority
|
|
4903
|
-
}));
|
|
4904
|
-
}
|
|
4905
|
-
//#endregion
|
|
4906
4940
|
//#region src/embedded-modal/errorModal.ts
|
|
4907
4941
|
const WALLET_NOT_FOUND_ERROR_MESSAGE = "To use mobile wallet adapter, you must have a compatible mobile wallet application installed on your device.";
|
|
4908
4942
|
const BROWSER_NOT_SUPPORTED_ERROR_MESSAGE = "This browser appears to be incompatible with mobile wallet adapter. Open this page in a compatible mobile browser app and try again.";
|
|
@@ -5039,7 +5073,7 @@ function createDefaultAuthorizationCache() {
|
|
|
5039
5073
|
const parsedAccounts = parsed.accounts.map((account) => {
|
|
5040
5074
|
return {
|
|
5041
5075
|
...account,
|
|
5042
|
-
publicKey: "publicKey" in account ? new Uint8Array(Object.values(account.publicKey)) :
|
|
5076
|
+
publicKey: "publicKey" in account ? new Uint8Array(Object.values(account.publicKey)) : index_native.base58.decode(account.address)
|
|
5043
5077
|
};
|
|
5044
5078
|
});
|
|
5045
5079
|
return {
|
|
@@ -5068,12 +5102,9 @@ function createDefaultChainSelector() {
|
|
|
5068
5102
|
}
|
|
5069
5103
|
|
|
5070
5104
|
exports.LocalSolanaMobileWalletAdapterWallet = LocalSolanaMobileWalletAdapterWallet;
|
|
5071
|
-
exports.RemoteSolanaMobileWalletAdapterWallet = RemoteSolanaMobileWalletAdapterWallet;
|
|
5072
|
-
exports.SolanaMobileWalletAdapterRemoteWalletName = SolanaMobileWalletAdapterRemoteWalletName;
|
|
5073
5105
|
exports.SolanaMobileWalletAdapterWalletName = SolanaMobileWalletAdapterWalletName;
|
|
5074
5106
|
exports.createDefaultAuthorizationCache = createDefaultAuthorizationCache;
|
|
5075
5107
|
exports.createDefaultChainSelector = createDefaultChainSelector;
|
|
5076
5108
|
exports.createDefaultWalletNotFoundHandler = createDefaultWalletNotFoundHandler;
|
|
5077
5109
|
exports.defaultErrorModalWalletNotFoundHandler = defaultErrorModalWalletNotFoundHandler;
|
|
5078
|
-
|
|
5079
|
-
//# sourceMappingURL=index.browser-C1QL04xM.js.map
|
|
5110
|
+
//# sourceMappingURL=index.browser-BQSN-6X2.js.map
|