@reown/appkit-solana-react-native 0.0.0-chore-bump-builder-20250728195048 → 0.0.0-chore-solflare-20250730210452
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/lib/commonjs/connectors/PhantomConnector.js +15 -224
- package/lib/commonjs/connectors/PhantomConnector.js.map +1 -1
- package/lib/commonjs/connectors/SolanaDeeplinkConnector.js +242 -0
- package/lib/commonjs/connectors/SolanaDeeplinkConnector.js.map +1 -0
- package/lib/commonjs/connectors/SolflareConnector.js +35 -0
- package/lib/commonjs/connectors/SolflareConnector.js.map +1 -0
- package/lib/commonjs/index.js +27 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/providers/{PhantomProvider.js → SolanaDeeplinkProvider.js} +58 -56
- package/lib/commonjs/providers/SolanaDeeplinkProvider.js.map +1 -0
- package/lib/module/connectors/PhantomConnector.js +16 -224
- package/lib/module/connectors/PhantomConnector.js.map +1 -1
- package/lib/module/connectors/SolanaDeeplinkConnector.js +236 -0
- package/lib/module/connectors/SolanaDeeplinkConnector.js.map +1 -0
- package/lib/module/connectors/SolflareConnector.js +30 -0
- package/lib/module/connectors/SolflareConnector.js.map +1 -0
- package/lib/module/index.js +7 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/providers/{PhantomProvider.js → SolanaDeeplinkProvider.js} +56 -54
- package/lib/module/providers/SolanaDeeplinkProvider.js.map +1 -0
- package/lib/typescript/connectors/PhantomConnector.d.ts +9 -25
- package/lib/typescript/connectors/PhantomConnector.d.ts.map +1 -1
- package/lib/typescript/connectors/SolanaDeeplinkConnector.d.ts +32 -0
- package/lib/typescript/connectors/SolanaDeeplinkConnector.d.ts.map +1 -0
- package/lib/typescript/connectors/SolflareConnector.d.ts +11 -0
- package/lib/typescript/connectors/SolflareConnector.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +4 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/providers/{PhantomProvider.d.ts → SolanaDeeplinkProvider.d.ts} +9 -8
- package/lib/typescript/providers/SolanaDeeplinkProvider.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +30 -35
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/connectors/PhantomConnector.ts +17 -314
- package/src/connectors/SolanaDeeplinkConnector.ts +336 -0
- package/src/connectors/SolflareConnector.ts +32 -0
- package/src/index.ts +23 -3
- package/src/providers/{PhantomProvider.ts → SolanaDeeplinkProvider.ts} +109 -82
- package/src/types.ts +44 -45
- package/lib/commonjs/providers/PhantomProvider.js.map +0 -1
- package/lib/module/providers/PhantomProvider.js.map +0 -1
- package/lib/typescript/providers/PhantomProvider.d.ts.map +0 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ConstantsUtil, type WalletInfo } from '@reown/appkit-common-react-native';
|
|
2
|
+
import { SolanaDeeplinkConnector } from './SolanaDeeplinkConnector';
|
|
3
|
+
|
|
4
|
+
const SOLFLARE_BASE_URL = 'https://solflare.com/ul/v1';
|
|
5
|
+
const SOLFLARE_CONNECTOR_STORAGE_KEY = '@appkit/solflare-connector-data';
|
|
6
|
+
const SOLFLARE_DAPP_KEYPAIR_STORAGE_KEY = '@appkit/solflare-dapp-secret-key';
|
|
7
|
+
|
|
8
|
+
export class SolflareConnector extends SolanaDeeplinkConnector {
|
|
9
|
+
constructor() {
|
|
10
|
+
super({ walletType: 'solflare' });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override getWalletInfo(): WalletInfo {
|
|
14
|
+
return ConstantsUtil.SOLFLARE_CUSTOM_WALLET;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
protected getBaseUrl(): string {
|
|
18
|
+
return SOLFLARE_BASE_URL;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected getStorageKey(): string {
|
|
22
|
+
return SOLFLARE_CONNECTOR_STORAGE_KEY;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
protected getDappKeypairStorageKey(): string {
|
|
26
|
+
return SOLFLARE_DAPP_KEYPAIR_STORAGE_KEY;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected getEncryptionKeyFieldName(): string {
|
|
30
|
+
return 'solflare_encryption_public_key';
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
// Adapter
|
|
2
2
|
export { SolanaAdapter } from './adapter';
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
export
|
|
4
|
+
// Generic exports
|
|
5
|
+
export { SolanaDeeplinkProvider, SOLANA_SIGNING_METHODS } from './providers/SolanaDeeplinkProvider';
|
|
6
|
+
export { SolanaDeeplinkConnector } from './connectors/SolanaDeeplinkConnector';
|
|
6
7
|
|
|
7
|
-
//
|
|
8
|
+
// Wallet-specific exports
|
|
8
9
|
export { PhantomConnector } from './connectors/PhantomConnector';
|
|
10
|
+
export { SolflareConnector } from './connectors/SolflareConnector';
|
|
11
|
+
|
|
12
|
+
// Types
|
|
13
|
+
export type {
|
|
14
|
+
SolanaWalletType,
|
|
15
|
+
SolanaCluster,
|
|
16
|
+
SolanaDeeplinkProviderConfig,
|
|
17
|
+
SolanaWalletSession,
|
|
18
|
+
SolanaConnectResult,
|
|
19
|
+
SolanaDeeplinkResponse,
|
|
20
|
+
SolanaRpcMethod,
|
|
21
|
+
SolanaConnectParams,
|
|
22
|
+
SolanaDisconnectParams,
|
|
23
|
+
SolanaSignTransactionParams,
|
|
24
|
+
SolanaSignAllTransactionsParams,
|
|
25
|
+
SolanaSignMessageParams,
|
|
26
|
+
SolanaConnectorConfig,
|
|
27
|
+
SolanaConnectorSessionData
|
|
28
|
+
} from './types';
|
|
@@ -9,27 +9,24 @@ import type {
|
|
|
9
9
|
Storage
|
|
10
10
|
} from '@reown/appkit-common-react-native';
|
|
11
11
|
import type {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
SolanaDeeplinkProviderConfig,
|
|
13
|
+
SolanaConnectResult,
|
|
14
|
+
SolanaWalletSession,
|
|
15
15
|
DecryptedConnectData,
|
|
16
|
-
|
|
16
|
+
SolanaDeeplinkResponse,
|
|
17
17
|
SignAllTransactionsRequestParams,
|
|
18
18
|
SignMessageRequestParams,
|
|
19
19
|
SignTransactionRequestParams,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
SolanaRpcMethod,
|
|
21
|
+
SolanaConnectParams,
|
|
22
|
+
SolanaDisconnectParams,
|
|
23
|
+
SolanaSignTransactionParams,
|
|
24
|
+
SolanaSignMessageParams,
|
|
25
|
+
SolanaSignAllTransactionsParams,
|
|
26
|
+
SolanaCluster
|
|
27
27
|
} from '../types';
|
|
28
28
|
import EventEmitter from 'events';
|
|
29
29
|
|
|
30
|
-
const PHANTOM_BASE_URL = 'https://phantom.app/ul/v1';
|
|
31
|
-
const PHANTOM_PROVIDER_STORAGE_KEY = '@appkit/phantom-provider-session';
|
|
32
|
-
|
|
33
30
|
export const SOLANA_SIGNING_METHODS = {
|
|
34
31
|
SOLANA_SIGN_TRANSACTION: 'solana_signTransaction',
|
|
35
32
|
SOLANA_SIGN_MESSAGE: 'solana_signMessage',
|
|
@@ -43,24 +40,28 @@ function isValidSolanaSigningMethod(method: string): method is SolanaSigningMeth
|
|
|
43
40
|
return Object.values(SOLANA_SIGNING_METHODS).includes(method as SolanaSigningMethod);
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
export class
|
|
47
|
-
private readonly config:
|
|
43
|
+
export class SolanaDeeplinkProvider extends EventEmitter implements Provider {
|
|
44
|
+
private readonly config: SolanaDeeplinkProviderConfig;
|
|
48
45
|
private dappEncryptionKeyPair: nacl.BoxKeyPair;
|
|
49
|
-
private currentCluster:
|
|
46
|
+
private currentCluster: SolanaCluster = 'mainnet-beta';
|
|
50
47
|
|
|
51
48
|
private storage: Storage;
|
|
52
49
|
|
|
53
50
|
private sessionToken: string | null = null;
|
|
54
51
|
private userPublicKey: string | null = null;
|
|
55
|
-
private
|
|
52
|
+
private walletEncryptionPublicKeyBs58: string | null = null;
|
|
56
53
|
|
|
57
|
-
constructor(config:
|
|
54
|
+
constructor(config: SolanaDeeplinkProviderConfig) {
|
|
58
55
|
super();
|
|
59
56
|
this.config = config;
|
|
60
57
|
this.dappEncryptionKeyPair = config.dappEncryptionKeyPair;
|
|
61
58
|
this.storage = config.storage;
|
|
62
59
|
}
|
|
63
60
|
|
|
61
|
+
private getStorageKey(): string {
|
|
62
|
+
return `@appkit/${this.config.walletType}-provider-session`;
|
|
63
|
+
}
|
|
64
|
+
|
|
64
65
|
getUserPublicKey(): string | null {
|
|
65
66
|
return this.userPublicKey;
|
|
66
67
|
}
|
|
@@ -69,13 +70,13 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
69
70
|
return !!this.sessionToken && !!this.userPublicKey && !!this.dappEncryptionKeyPair;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
private buildUrl(rpcMethod:
|
|
73
|
+
private buildUrl(rpcMethod: SolanaRpcMethod, params: Record<string, string>): string {
|
|
73
74
|
const query = new URLSearchParams(params).toString();
|
|
74
75
|
|
|
75
|
-
return `${
|
|
76
|
+
return `${this.config.baseUrl}/${rpcMethod}?${query}`;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
private getRpcMethodName(method: SolanaSigningMethod):
|
|
79
|
+
private getRpcMethodName(method: SolanaSigningMethod): SolanaRpcMethod {
|
|
79
80
|
switch (method) {
|
|
80
81
|
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_TRANSACTION:
|
|
81
82
|
return 'signTransaction';
|
|
@@ -93,19 +94,19 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
93
94
|
|
|
94
95
|
private encryptPayload(
|
|
95
96
|
payload: Record<string, unknown>,
|
|
96
|
-
|
|
97
|
+
walletPublicKeyBs58ToEncryptFor: string
|
|
97
98
|
): { nonce: string; encryptedPayload: string } | null {
|
|
98
|
-
if (!
|
|
99
|
+
if (!walletPublicKeyBs58ToEncryptFor) {
|
|
99
100
|
return null;
|
|
100
101
|
}
|
|
101
102
|
try {
|
|
102
|
-
const
|
|
103
|
+
const walletPublicKeyBytes = bs58.decode(walletPublicKeyBs58ToEncryptFor);
|
|
103
104
|
const nonce = nacl.randomBytes(nacl.box.nonceLength);
|
|
104
105
|
const payloadBytes = Buffer.from(JSON.stringify(payload), 'utf8');
|
|
105
106
|
const encryptedPayload = nacl.box(
|
|
106
107
|
payloadBytes,
|
|
107
108
|
nonce,
|
|
108
|
-
|
|
109
|
+
walletPublicKeyBytes,
|
|
109
110
|
this.dappEncryptionKeyPair.secretKey
|
|
110
111
|
);
|
|
111
112
|
|
|
@@ -121,16 +122,16 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
121
122
|
private decryptPayload<T>(
|
|
122
123
|
encryptedDataBs58: string,
|
|
123
124
|
nonceBs58: string,
|
|
124
|
-
|
|
125
|
+
walletSenderPublicKeyBs58: string
|
|
125
126
|
): T | null {
|
|
126
127
|
try {
|
|
127
128
|
const encryptedDataBytes = bs58.decode(encryptedDataBs58);
|
|
128
129
|
const nonceBytes = bs58.decode(nonceBs58);
|
|
129
|
-
const
|
|
130
|
+
const walletSenderPublicKeyBytes = bs58.decode(walletSenderPublicKeyBs58);
|
|
130
131
|
const decryptedPayloadBytes = nacl.box.open(
|
|
131
132
|
encryptedDataBytes,
|
|
132
133
|
nonceBytes,
|
|
133
|
-
|
|
134
|
+
walletSenderPublicKeyBytes,
|
|
134
135
|
this.dappEncryptionKeyPair.secretKey
|
|
135
136
|
);
|
|
136
137
|
if (!decryptedPayloadBytes) {
|
|
@@ -145,7 +146,7 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
145
146
|
|
|
146
147
|
public async restoreSession(): Promise<boolean> {
|
|
147
148
|
try {
|
|
148
|
-
const session = await this.storage.getItem<
|
|
149
|
+
const session = await this.storage.getItem<SolanaWalletSession>(this.getStorageKey());
|
|
149
150
|
if (session) {
|
|
150
151
|
this.setSession(session);
|
|
151
152
|
|
|
@@ -154,7 +155,7 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
154
155
|
|
|
155
156
|
return false;
|
|
156
157
|
} catch (error) {
|
|
157
|
-
// console.error(
|
|
158
|
+
// console.error(`${this.config.walletType}Provider: Failed to restore session.`, error);
|
|
158
159
|
await this.clearSessionStorage(); // Clear potentially corrupt data
|
|
159
160
|
|
|
160
161
|
return false;
|
|
@@ -162,36 +163,34 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
private async saveSession(): Promise<void> {
|
|
165
|
-
if (!this.sessionToken || !this.userPublicKey || !this.
|
|
166
|
+
if (!this.sessionToken || !this.userPublicKey || !this.walletEncryptionPublicKeyBs58) {
|
|
166
167
|
return; // Cannot save incomplete session
|
|
167
168
|
}
|
|
168
|
-
const session:
|
|
169
|
+
const session: SolanaWalletSession = {
|
|
169
170
|
sessionToken: this.sessionToken,
|
|
170
171
|
userPublicKey: this.userPublicKey,
|
|
171
|
-
|
|
172
|
+
walletEncryptionPublicKeyBs58: this.walletEncryptionPublicKeyBs58,
|
|
172
173
|
cluster: this.currentCluster
|
|
173
174
|
};
|
|
174
175
|
try {
|
|
175
|
-
await this.storage.setItem(
|
|
176
|
+
await this.storage.setItem(this.getStorageKey(), session);
|
|
176
177
|
} catch (error) {
|
|
177
|
-
// console.error(
|
|
178
|
+
// console.error(`${this.config.walletType}Provider: Failed to save session.`, error);
|
|
178
179
|
}
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
private async clearSessionStorage(): Promise<void> {
|
|
182
183
|
try {
|
|
183
|
-
await this.storage.removeItem(
|
|
184
|
+
await this.storage.removeItem(this.getStorageKey());
|
|
184
185
|
} catch (error) {
|
|
185
|
-
// console.error(
|
|
186
|
+
// console.error(`${this.config.walletType}Provider: Failed to clear session storage.`, error);
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
public async connect<T =
|
|
190
|
-
cluster?: PhantomCluster;
|
|
191
|
-
}): Promise<T> {
|
|
190
|
+
public async connect<T = SolanaConnectResult>(params?: { cluster?: SolanaCluster }): Promise<T> {
|
|
192
191
|
const cluster = params?.cluster ?? 'mainnet-beta';
|
|
193
192
|
this.currentCluster = cluster;
|
|
194
|
-
const connectDeeplinkParams:
|
|
193
|
+
const connectDeeplinkParams: SolanaConnectParams = {
|
|
195
194
|
app_url: this.config.dappUrl,
|
|
196
195
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
197
196
|
redirect_link: this.config.appScheme,
|
|
@@ -199,7 +198,7 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
199
198
|
};
|
|
200
199
|
const url = this.buildUrl('connect', connectDeeplinkParams as any);
|
|
201
200
|
|
|
202
|
-
return new Promise<
|
|
201
|
+
return new Promise<SolanaConnectResult>((resolve, reject) => {
|
|
203
202
|
let subscription: { remove: () => void } | null = null;
|
|
204
203
|
const handleDeepLink = async (event: { url: string }) => {
|
|
205
204
|
if (subscription) {
|
|
@@ -215,35 +214,45 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
215
214
|
if (errorCode) {
|
|
216
215
|
return reject(
|
|
217
216
|
new Error(
|
|
218
|
-
|
|
217
|
+
`${this.config.walletType} Connection Failed: ${
|
|
218
|
+
errorMessage || 'Unknown error'
|
|
219
|
+
} (Code: ${errorCode})`
|
|
219
220
|
)
|
|
220
221
|
);
|
|
221
222
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
223
|
+
const walletEncryptionPublicKey = responseUrlParams.get(
|
|
224
|
+
this.config.encryptionKeyFieldName
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const responsePayload: SolanaDeeplinkResponse = {
|
|
228
|
+
wallet_encryption_public_key: walletEncryptionPublicKey!,
|
|
224
229
|
nonce: responseUrlParams.get('nonce')!,
|
|
225
230
|
data: responseUrlParams.get('data')!
|
|
226
231
|
};
|
|
227
232
|
if (
|
|
228
|
-
!responsePayload.
|
|
233
|
+
!responsePayload.wallet_encryption_public_key ||
|
|
229
234
|
!responsePayload.nonce ||
|
|
230
235
|
!responsePayload.data
|
|
231
236
|
) {
|
|
232
|
-
return reject(
|
|
237
|
+
return reject(
|
|
238
|
+
new Error(`${this.config.walletType} Connect: Invalid response - missing parameters.`)
|
|
239
|
+
);
|
|
233
240
|
}
|
|
234
241
|
const decryptedData = this.decryptPayload<DecryptedConnectData>(
|
|
235
242
|
responsePayload.data,
|
|
236
243
|
responsePayload.nonce,
|
|
237
|
-
responsePayload.
|
|
244
|
+
responsePayload.wallet_encryption_public_key
|
|
238
245
|
);
|
|
239
246
|
if (!decryptedData || !decryptedData.public_key || !decryptedData.session) {
|
|
240
247
|
return reject(
|
|
241
|
-
new Error(
|
|
248
|
+
new Error(
|
|
249
|
+
`${this.config.walletType} Connect: Failed to decrypt or invalid decrypted data.`
|
|
250
|
+
)
|
|
242
251
|
);
|
|
243
252
|
}
|
|
244
253
|
this.userPublicKey = decryptedData.public_key;
|
|
245
254
|
this.sessionToken = decryptedData.session;
|
|
246
|
-
this.
|
|
255
|
+
this.walletEncryptionPublicKeyBs58 = responsePayload.wallet_encryption_public_key;
|
|
247
256
|
|
|
248
257
|
// Save session on successful connect
|
|
249
258
|
this.saveSession();
|
|
@@ -251,11 +260,11 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
251
260
|
resolve({
|
|
252
261
|
userPublicKey: this.userPublicKey,
|
|
253
262
|
sessionToken: this.sessionToken,
|
|
254
|
-
|
|
263
|
+
walletEncryptionPublicKeyBs58: this.walletEncryptionPublicKeyBs58,
|
|
255
264
|
cluster
|
|
256
265
|
});
|
|
257
266
|
} else {
|
|
258
|
-
reject(new Error(
|
|
267
|
+
reject(new Error(`${this.config.walletType} Connect: Unexpected redirect URI.`));
|
|
259
268
|
}
|
|
260
269
|
};
|
|
261
270
|
subscription = Linking.addEventListener('url', handleDeepLink);
|
|
@@ -263,13 +272,17 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
263
272
|
if (subscription) {
|
|
264
273
|
subscription.remove();
|
|
265
274
|
}
|
|
266
|
-
reject(
|
|
275
|
+
reject(
|
|
276
|
+
new Error(
|
|
277
|
+
`Failed to open ${this.config.walletType} wallet: ${err.message}. Is it installed?`
|
|
278
|
+
)
|
|
279
|
+
);
|
|
267
280
|
});
|
|
268
281
|
}) as Promise<T>;
|
|
269
282
|
}
|
|
270
283
|
|
|
271
284
|
public async disconnect(): Promise<void> {
|
|
272
|
-
if (!this.sessionToken || !this.
|
|
285
|
+
if (!this.sessionToken || !this.walletEncryptionPublicKeyBs58) {
|
|
273
286
|
await this.clearSession();
|
|
274
287
|
this.emit('disconnect');
|
|
275
288
|
|
|
@@ -279,18 +292,18 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
279
292
|
const payloadToEncrypt = { session: this.sessionToken };
|
|
280
293
|
const encryptedDisconnectPayload = this.encryptPayload(
|
|
281
294
|
payloadToEncrypt,
|
|
282
|
-
this.
|
|
295
|
+
this.walletEncryptionPublicKeyBs58
|
|
283
296
|
);
|
|
284
297
|
|
|
285
298
|
if (!encryptedDisconnectPayload) {
|
|
286
|
-
// console.warn(
|
|
299
|
+
// console.warn(`${this.config.walletType}Provider: Failed to encrypt disconnect payload. Clearing session locally.`);
|
|
287
300
|
await this.clearSession();
|
|
288
301
|
this.emit('disconnect');
|
|
289
302
|
|
|
290
303
|
return Promise.resolve(); // Or reject, depending on desired strictness
|
|
291
304
|
}
|
|
292
305
|
|
|
293
|
-
const disconnectDeeplinkParams:
|
|
306
|
+
const disconnectDeeplinkParams: SolanaDisconnectParams = {
|
|
294
307
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
295
308
|
redirect_link: this.config.appScheme,
|
|
296
309
|
payload: encryptedDisconnectPayload.encryptedPayload,
|
|
@@ -309,7 +322,7 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
309
322
|
resolve();
|
|
310
323
|
} else {
|
|
311
324
|
this.clearSession();
|
|
312
|
-
reject(new Error(
|
|
325
|
+
reject(new Error(`${this.config.walletType} Disconnect: Unexpected redirect URI.`));
|
|
313
326
|
}
|
|
314
327
|
};
|
|
315
328
|
subscription = Linking.addEventListener('url', handleDeepLink);
|
|
@@ -318,7 +331,9 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
318
331
|
subscription.remove();
|
|
319
332
|
}
|
|
320
333
|
this.clearSession();
|
|
321
|
-
reject(
|
|
334
|
+
reject(
|
|
335
|
+
new Error(`Failed to open ${this.config.walletType} for disconnection: ${err.message}.`)
|
|
336
|
+
);
|
|
322
337
|
});
|
|
323
338
|
});
|
|
324
339
|
}
|
|
@@ -326,29 +341,29 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
326
341
|
public async clearSession(): Promise<void> {
|
|
327
342
|
this.sessionToken = null;
|
|
328
343
|
this.userPublicKey = null;
|
|
329
|
-
this.
|
|
344
|
+
this.walletEncryptionPublicKeyBs58 = null;
|
|
330
345
|
await this.clearSessionStorage();
|
|
331
346
|
}
|
|
332
347
|
|
|
333
|
-
public setSession(session:
|
|
348
|
+
public setSession(session: SolanaWalletSession): void {
|
|
334
349
|
this.sessionToken = session.sessionToken;
|
|
335
350
|
this.userPublicKey = session.userPublicKey;
|
|
336
|
-
this.
|
|
351
|
+
this.walletEncryptionPublicKeyBs58 = session.walletEncryptionPublicKeyBs58;
|
|
337
352
|
this.currentCluster = session.cluster;
|
|
338
353
|
}
|
|
339
354
|
|
|
340
355
|
public async request<T>(args: RequestArguments, _chainId?: CaipNetworkId): Promise<T> {
|
|
341
356
|
if (!isValidSolanaSigningMethod(args.method)) {
|
|
342
357
|
throw new Error(
|
|
343
|
-
|
|
358
|
+
`${this.config.walletType}Provider: Unsupported method: ${args.method}. Only Solana signing methods are supported.`
|
|
344
359
|
);
|
|
345
360
|
}
|
|
346
361
|
const signingMethod = args.method as SolanaSigningMethod;
|
|
347
362
|
const requestParams = args.params as any;
|
|
348
363
|
|
|
349
|
-
if (!this.isConnected() || !this.sessionToken || !this.
|
|
364
|
+
if (!this.isConnected() || !this.sessionToken || !this.walletEncryptionPublicKeyBs58) {
|
|
350
365
|
throw new Error(
|
|
351
|
-
|
|
366
|
+
`${this.config.walletType}Provider: Not connected or session details missing. Cannot process request.`
|
|
352
367
|
);
|
|
353
368
|
}
|
|
354
369
|
|
|
@@ -371,13 +386,15 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
371
386
|
};
|
|
372
387
|
const encryptedData = this.encryptPayload(
|
|
373
388
|
dataToEncrypt,
|
|
374
|
-
this.
|
|
389
|
+
this.walletEncryptionPublicKeyBs58!
|
|
375
390
|
);
|
|
376
391
|
if (!encryptedData) {
|
|
377
|
-
throw new Error(
|
|
392
|
+
throw new Error(
|
|
393
|
+
`${this.config.walletType}Provider: Failed to encrypt payload for ${signingMethod}.`
|
|
394
|
+
);
|
|
378
395
|
}
|
|
379
396
|
|
|
380
|
-
const signTxDeeplinkParams:
|
|
397
|
+
const signTxDeeplinkParams: SolanaSignTransactionParams = {
|
|
381
398
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
382
399
|
redirect_link: this.config.appScheme,
|
|
383
400
|
cluster: this.currentCluster,
|
|
@@ -415,14 +432,16 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
415
432
|
|
|
416
433
|
const encryptedPayloadData = this.encryptPayload(
|
|
417
434
|
dataToEncrypt,
|
|
418
|
-
this.
|
|
435
|
+
this.walletEncryptionPublicKeyBs58!
|
|
419
436
|
);
|
|
420
437
|
|
|
421
438
|
if (!encryptedPayloadData) {
|
|
422
|
-
throw new Error(
|
|
439
|
+
throw new Error(
|
|
440
|
+
`${this.config.walletType}Provider: Failed to encrypt payload for signMessage.`
|
|
441
|
+
);
|
|
423
442
|
}
|
|
424
443
|
|
|
425
|
-
const signMsgDeeplinkQueryPayload:
|
|
444
|
+
const signMsgDeeplinkQueryPayload: SolanaSignMessageParams = {
|
|
426
445
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
427
446
|
redirect_link: this.config.appScheme,
|
|
428
447
|
payload: encryptedPayloadData.encryptedPayload,
|
|
@@ -449,13 +468,15 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
449
468
|
};
|
|
450
469
|
const encryptedData = this.encryptPayload(
|
|
451
470
|
dataToEncrypt,
|
|
452
|
-
this.
|
|
471
|
+
this.walletEncryptionPublicKeyBs58!
|
|
453
472
|
);
|
|
454
473
|
if (!encryptedData) {
|
|
455
|
-
throw new Error(
|
|
474
|
+
throw new Error(
|
|
475
|
+
`${this.config.walletType}Provider: Failed to encrypt payload for ${signingMethod}.`
|
|
476
|
+
);
|
|
456
477
|
}
|
|
457
478
|
|
|
458
|
-
const signAllTxDeeplinkParams:
|
|
479
|
+
const signAllTxDeeplinkParams: SolanaSignAllTransactionsParams = {
|
|
459
480
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
460
481
|
redirect_link: this.config.appScheme,
|
|
461
482
|
cluster: this.currentCluster,
|
|
@@ -466,7 +487,9 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
466
487
|
break;
|
|
467
488
|
}
|
|
468
489
|
default: {
|
|
469
|
-
throw new Error(
|
|
490
|
+
throw new Error(
|
|
491
|
+
`${this.config.walletType}Provider: Unhandled signing method: ${signingMethod}`
|
|
492
|
+
);
|
|
470
493
|
}
|
|
471
494
|
}
|
|
472
495
|
|
|
@@ -486,7 +509,7 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
486
509
|
if (errorCode) {
|
|
487
510
|
return reject(
|
|
488
511
|
new Error(
|
|
489
|
-
|
|
512
|
+
`${this.config.walletType} ${signingMethod} Failed: ${
|
|
490
513
|
errorMessage || 'Unknown error'
|
|
491
514
|
} (Code: ${errorCode})`
|
|
492
515
|
)
|
|
@@ -496,24 +519,26 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
496
519
|
const responseData = responseUrlParams.get('data');
|
|
497
520
|
if (!responseNonce || !responseData) {
|
|
498
521
|
return reject(
|
|
499
|
-
new Error(
|
|
522
|
+
new Error(
|
|
523
|
+
`${this.config.walletType} ${signingMethod}: Invalid response - missing nonce or data.`
|
|
524
|
+
)
|
|
500
525
|
);
|
|
501
526
|
}
|
|
502
527
|
const decryptedResult = this.decryptPayload<any>(
|
|
503
528
|
responseData,
|
|
504
529
|
responseNonce,
|
|
505
|
-
this.
|
|
530
|
+
this.walletEncryptionPublicKeyBs58!
|
|
506
531
|
);
|
|
507
532
|
if (!decryptedResult) {
|
|
508
533
|
return reject(
|
|
509
534
|
new Error(
|
|
510
|
-
|
|
535
|
+
`${this.config.walletType} ${signingMethod}: Failed to decrypt response or invalid decrypted data.`
|
|
511
536
|
)
|
|
512
537
|
);
|
|
513
538
|
}
|
|
514
539
|
resolve(decryptedResult as T);
|
|
515
540
|
} else {
|
|
516
|
-
reject(new Error(
|
|
541
|
+
reject(new Error(`${this.config.walletType} ${signingMethod}: Unexpected redirect URI.`));
|
|
517
542
|
}
|
|
518
543
|
};
|
|
519
544
|
subscription = Linking.addEventListener('url', handleDeepLink);
|
|
@@ -522,7 +547,9 @@ export class PhantomProvider extends EventEmitter implements Provider {
|
|
|
522
547
|
subscription.remove();
|
|
523
548
|
}
|
|
524
549
|
reject(
|
|
525
|
-
new Error(
|
|
550
|
+
new Error(
|
|
551
|
+
`Failed to open ${this.config.walletType} for ${signingMethod}: ${err.message}. Is it installed?`
|
|
552
|
+
)
|
|
526
553
|
);
|
|
527
554
|
});
|
|
528
555
|
});
|