@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,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { WalletConnector, solana, solanaDevnet, solanaTestnet } from '@reown/appkit-common-react-native';
|
|
4
|
+
import nacl from 'tweetnacl';
|
|
5
|
+
import bs58 from 'bs58';
|
|
6
|
+
import { SolanaDeeplinkProvider, SOLANA_SIGNING_METHODS } from '../providers/SolanaDeeplinkProvider';
|
|
7
|
+
const SOLANA_CLUSTER_TO_CHAIN_ID_PART = {
|
|
8
|
+
'mainnet-beta': solana.id,
|
|
9
|
+
'testnet': solanaTestnet.id,
|
|
10
|
+
'devnet': solanaDevnet.id
|
|
11
|
+
};
|
|
12
|
+
export class SolanaDeeplinkConnector extends WalletConnector {
|
|
13
|
+
currentCaipNetworkId = null;
|
|
14
|
+
static SUPPORTED_NAMESPACE = 'solana';
|
|
15
|
+
constructor(config) {
|
|
16
|
+
super({
|
|
17
|
+
type: config.walletType
|
|
18
|
+
});
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Abstract methods that wallet-specific connectors must implement
|
|
23
|
+
|
|
24
|
+
async init(ops) {
|
|
25
|
+
super.init(ops);
|
|
26
|
+
this.storage = ops.storage;
|
|
27
|
+
await this.initializeKeyPair();
|
|
28
|
+
const appScheme = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
|
|
29
|
+
if (!appScheme) {
|
|
30
|
+
throw new Error(`${this.config.walletType} Connector: No redirect link found in metadata. Please add redirect.universal or redirect.native to the metadata.`);
|
|
31
|
+
}
|
|
32
|
+
const providerConfig = {
|
|
33
|
+
appScheme,
|
|
34
|
+
dappUrl: ops.metadata.url,
|
|
35
|
+
storage: ops.storage,
|
|
36
|
+
dappEncryptionKeyPair: this.dappEncryptionKeyPair,
|
|
37
|
+
walletType: this.config.walletType,
|
|
38
|
+
baseUrl: this.getBaseUrl(),
|
|
39
|
+
encryptionKeyFieldName: this.getEncryptionKeyFieldName()
|
|
40
|
+
};
|
|
41
|
+
this.provider = new SolanaDeeplinkProvider(providerConfig);
|
|
42
|
+
await this.restoreSession();
|
|
43
|
+
}
|
|
44
|
+
async initializeKeyPair() {
|
|
45
|
+
try {
|
|
46
|
+
const secretKeyB58 = await this.getStorage().getItem(this.getDappKeypairStorageKey());
|
|
47
|
+
if (secretKeyB58) {
|
|
48
|
+
const secretKey = bs58.decode(secretKeyB58);
|
|
49
|
+
this.dappEncryptionKeyPair = nacl.box.keyPair.fromSecretKey(secretKey);
|
|
50
|
+
} else {
|
|
51
|
+
const newKeyPair = nacl.box.keyPair();
|
|
52
|
+
this.dappEncryptionKeyPair = newKeyPair;
|
|
53
|
+
await this.getStorage().setItem(this.getDappKeypairStorageKey(), bs58.encode(newKeyPair.secretKey));
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
await this.disconnect();
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async connect(opts) {
|
|
61
|
+
if (this.isConnected()) {
|
|
62
|
+
return this.namespaces;
|
|
63
|
+
}
|
|
64
|
+
const defaultChain = opts?.defaultChain?.split(':')?.[0] === 'solana' ? opts?.defaultChain?.split(':')[1] : opts?.namespaces?.['solana']?.chains?.[0]?.split(':')[1];
|
|
65
|
+
const requestedCluster = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID_PART).find(key => SOLANA_CLUSTER_TO_CHAIN_ID_PART[key] === defaultChain);
|
|
66
|
+
try {
|
|
67
|
+
const connectResult = await this.getProvider().connect({
|
|
68
|
+
cluster: requestedCluster
|
|
69
|
+
});
|
|
70
|
+
const solanaChainIdPart = SOLANA_CLUSTER_TO_CHAIN_ID_PART[connectResult.cluster];
|
|
71
|
+
if (!solanaChainIdPart) {
|
|
72
|
+
throw new Error(`${this.config.walletType} Connect: Internal - Unknown cluster mapping for ${connectResult.cluster}`);
|
|
73
|
+
}
|
|
74
|
+
this.currentCaipNetworkId = `solana:${solanaChainIdPart}`;
|
|
75
|
+
this.wallet = this.getWalletInfo();
|
|
76
|
+
const userPublicKey = this.getProvider().getUserPublicKey();
|
|
77
|
+
if (!userPublicKey) {
|
|
78
|
+
throw new Error(`${this.config.walletType} Connect: Provider failed to return a user public key.`);
|
|
79
|
+
}
|
|
80
|
+
const caipAddress = `${this.currentCaipNetworkId}:${userPublicKey}`;
|
|
81
|
+
this.namespaces = {
|
|
82
|
+
[SolanaDeeplinkConnector.SUPPORTED_NAMESPACE]: {
|
|
83
|
+
accounts: [caipAddress],
|
|
84
|
+
methods: Object.values(SOLANA_SIGNING_METHODS),
|
|
85
|
+
events: [],
|
|
86
|
+
chains: [this.currentCaipNetworkId]
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
await this.saveSession();
|
|
90
|
+
return this.namespaces;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
this.clearSession();
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async disconnect() {
|
|
97
|
+
try {
|
|
98
|
+
if (this.isConnected()) {
|
|
99
|
+
await super.disconnect();
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
// console.warn(`${this.config.walletType}Connector: Error during provider disconnect: ${error.message}. Proceeding with local clear.`);
|
|
103
|
+
}
|
|
104
|
+
await this.clearSession();
|
|
105
|
+
}
|
|
106
|
+
async clearSession() {
|
|
107
|
+
this.namespaces = undefined;
|
|
108
|
+
this.wallet = undefined;
|
|
109
|
+
this.currentCaipNetworkId = null;
|
|
110
|
+
await this.clearSessionStorage();
|
|
111
|
+
}
|
|
112
|
+
getProvider() {
|
|
113
|
+
if (!this.provider) {
|
|
114
|
+
throw new Error(`${this.config.walletType} Connector: Provider not initialized. Call init() first.`);
|
|
115
|
+
}
|
|
116
|
+
return this.provider;
|
|
117
|
+
}
|
|
118
|
+
getStorage() {
|
|
119
|
+
if (!this.storage) {
|
|
120
|
+
throw new Error(`${this.config.walletType} Connector: Storage not initialized. Call init() first.`);
|
|
121
|
+
}
|
|
122
|
+
return this.storage;
|
|
123
|
+
}
|
|
124
|
+
getNamespaces() {
|
|
125
|
+
if (!this.namespaces) {
|
|
126
|
+
throw new Error(`${this.config.walletType} Connector: Not connected. Call connect() first.`);
|
|
127
|
+
}
|
|
128
|
+
return this.namespaces;
|
|
129
|
+
}
|
|
130
|
+
getChainId(namespace) {
|
|
131
|
+
if (namespace === SolanaDeeplinkConnector.SUPPORTED_NAMESPACE) {
|
|
132
|
+
return this.currentCaipNetworkId ?? undefined;
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
getProperties() {
|
|
137
|
+
return this.properties;
|
|
138
|
+
}
|
|
139
|
+
getWalletInfo() {
|
|
140
|
+
if (!this.isConnected()) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
return this.wallet;
|
|
144
|
+
}
|
|
145
|
+
isConnected() {
|
|
146
|
+
// Rely solely on the provider as the source of truth for connection status.
|
|
147
|
+
return this.getProvider().isConnected() && !!this.getProvider().getUserPublicKey();
|
|
148
|
+
}
|
|
149
|
+
async switchNetwork(network) {
|
|
150
|
+
const targetClusterName = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID_PART).find(key => SOLANA_CLUSTER_TO_CHAIN_ID_PART[key] === network.id);
|
|
151
|
+
if (!targetClusterName) {
|
|
152
|
+
throw new Error(`Cannot switch to unsupported network ID: ${network.id}`);
|
|
153
|
+
}
|
|
154
|
+
const currentClusterName = Object.keys(SOLANA_CLUSTER_TO_CHAIN_ID_PART).find(key => `solana:${SOLANA_CLUSTER_TO_CHAIN_ID_PART[key]}` === this.currentCaipNetworkId);
|
|
155
|
+
if (targetClusterName === currentClusterName && this.isConnected()) {
|
|
156
|
+
return Promise.resolve();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Solana wallets don't provide a way to switch network, so we need to disconnect and reconnect.
|
|
160
|
+
await this.disconnect(); // Clear current session
|
|
161
|
+
|
|
162
|
+
// Create a temporary options object to guide the new connection
|
|
163
|
+
const tempConnectOpts = {
|
|
164
|
+
defaultChain: `solana:${SOLANA_CLUSTER_TO_CHAIN_ID_PART[targetClusterName]}`
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// Attempt to connect to the new cluster
|
|
168
|
+
// The connect method will use the defaultChain from opts to determine the cluster.
|
|
169
|
+
await this.connect(tempConnectOpts);
|
|
170
|
+
this.getProvider().emit('chainChanged', network.id);
|
|
171
|
+
|
|
172
|
+
// Verify if the connection was successful and to the correct new network
|
|
173
|
+
if (!this.isConnected() || this.getChainId(SolanaDeeplinkConnector.SUPPORTED_NAMESPACE) !== tempConnectOpts.defaultChain) {
|
|
174
|
+
throw new Error(`Failed to switch network to ${targetClusterName}. Please try connecting manually.`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Orchestrates session restoration
|
|
179
|
+
async restoreSession() {
|
|
180
|
+
try {
|
|
181
|
+
const providerSession = await this.getProvider().restoreSession();
|
|
182
|
+
if (!providerSession) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// If provider session is restored, try to restore connector data
|
|
187
|
+
const connectorData = await this.getStorage().getItem(this.getStorageKey());
|
|
188
|
+
if (!connectorData) {
|
|
189
|
+
return false; // Provider session exists but connector data is missing
|
|
190
|
+
}
|
|
191
|
+
this.namespaces = connectorData.namespaces;
|
|
192
|
+
this.wallet = connectorData.wallet;
|
|
193
|
+
this.currentCaipNetworkId = connectorData.currentCaipNetworkId;
|
|
194
|
+
|
|
195
|
+
// Final validation
|
|
196
|
+
if (this.isConnected()) {
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// If validation fails, something is out of sync. Clear everything.
|
|
201
|
+
await this.disconnect();
|
|
202
|
+
return false;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
// On any error, disconnect to ensure a clean state
|
|
205
|
+
await this.disconnect();
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Saves only connector-specific data
|
|
211
|
+
async saveSession() {
|
|
212
|
+
if (!this.namespaces || !this.wallet || !this.currentCaipNetworkId) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const connectorData = {
|
|
216
|
+
namespaces: this.namespaces,
|
|
217
|
+
wallet: this.wallet,
|
|
218
|
+
currentCaipNetworkId: this.currentCaipNetworkId
|
|
219
|
+
};
|
|
220
|
+
try {
|
|
221
|
+
await this.getStorage().setItem(this.getStorageKey(), connectorData);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
// console.error(`${this.config.walletType}Connector: Failed to save session.`, error);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Clears only connector-specific data from storage
|
|
228
|
+
async clearSessionStorage() {
|
|
229
|
+
try {
|
|
230
|
+
await this.getStorage().removeItem(this.getStorageKey());
|
|
231
|
+
} catch (error) {
|
|
232
|
+
// console.error(`${this.config.walletType}Connector: Failed to clear session from storage.`, error);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=SolanaDeeplinkConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["WalletConnector","solana","solanaDevnet","solanaTestnet","nacl","bs58","SolanaDeeplinkProvider","SOLANA_SIGNING_METHODS","SOLANA_CLUSTER_TO_CHAIN_ID_PART","id","SolanaDeeplinkConnector","currentCaipNetworkId","SUPPORTED_NAMESPACE","constructor","config","type","walletType","init","ops","storage","initializeKeyPair","appScheme","metadata","redirect","universal","native","Error","providerConfig","dappUrl","url","dappEncryptionKeyPair","baseUrl","getBaseUrl","encryptionKeyFieldName","getEncryptionKeyFieldName","provider","restoreSession","secretKeyB58","getStorage","getItem","getDappKeypairStorageKey","secretKey","decode","box","keyPair","fromSecretKey","newKeyPair","setItem","encode","error","disconnect","connect","opts","isConnected","namespaces","defaultChain","split","chains","requestedCluster","Object","keys","find","key","connectResult","getProvider","cluster","solanaChainIdPart","wallet","getWalletInfo","userPublicKey","getUserPublicKey","caipAddress","accounts","methods","values","events","saveSession","clearSession","undefined","clearSessionStorage","getNamespaces","getChainId","namespace","getProperties","properties","switchNetwork","network","targetClusterName","currentClusterName","Promise","resolve","tempConnectOpts","emit","providerSession","connectorData","getStorageKey","removeItem"],"sourceRoot":"../../../src","sources":["connectors/SolanaDeeplinkConnector.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { ConstantsUtil } from '@reown/appkit-common-react-native';
|
|
4
|
+
import { SolanaDeeplinkConnector } from './SolanaDeeplinkConnector';
|
|
5
|
+
const SOLFLARE_BASE_URL = 'https://solflare.com/ul/v1';
|
|
6
|
+
const SOLFLARE_CONNECTOR_STORAGE_KEY = '@appkit/solflare-connector-data';
|
|
7
|
+
const SOLFLARE_DAPP_KEYPAIR_STORAGE_KEY = '@appkit/solflare-dapp-secret-key';
|
|
8
|
+
export class SolflareConnector extends SolanaDeeplinkConnector {
|
|
9
|
+
constructor() {
|
|
10
|
+
super({
|
|
11
|
+
walletType: 'solflare'
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
getWalletInfo() {
|
|
15
|
+
return ConstantsUtil.SOLFLARE_CUSTOM_WALLET;
|
|
16
|
+
}
|
|
17
|
+
getBaseUrl() {
|
|
18
|
+
return SOLFLARE_BASE_URL;
|
|
19
|
+
}
|
|
20
|
+
getStorageKey() {
|
|
21
|
+
return SOLFLARE_CONNECTOR_STORAGE_KEY;
|
|
22
|
+
}
|
|
23
|
+
getDappKeypairStorageKey() {
|
|
24
|
+
return SOLFLARE_DAPP_KEYPAIR_STORAGE_KEY;
|
|
25
|
+
}
|
|
26
|
+
getEncryptionKeyFieldName() {
|
|
27
|
+
return 'solflare_encryption_public_key';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=SolflareConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ConstantsUtil","SolanaDeeplinkConnector","SOLFLARE_BASE_URL","SOLFLARE_CONNECTOR_STORAGE_KEY","SOLFLARE_DAPP_KEYPAIR_STORAGE_KEY","SolflareConnector","constructor","walletType","getWalletInfo","SOLFLARE_CUSTOM_WALLET","getBaseUrl","getStorageKey","getDappKeypairStorageKey","getEncryptionKeyFieldName"],"sourceRoot":"../../../src","sources":["connectors/SolflareConnector.ts"],"mappings":";;AAAA,SAASA,aAAa,QAAyB,mCAAmC;AAClF,SAASC,uBAAuB,QAAQ,2BAA2B;AAEnE,MAAMC,iBAAiB,GAAG,4BAA4B;AACtD,MAAMC,8BAA8B,GAAG,iCAAiC;AACxE,MAAMC,iCAAiC,GAAG,kCAAkC;AAE5E,OAAO,MAAMC,iBAAiB,SAASJ,uBAAuB,CAAC;EAC7DK,WAAWA,CAAA,EAAG;IACZ,KAAK,CAAC;MAAEC,UAAU,EAAE;IAAW,CAAC,CAAC;EACnC;EAESC,aAAaA,CAAA,EAAe;IACnC,OAAOR,aAAa,CAACS,sBAAsB;EAC7C;EAEUC,UAAUA,CAAA,EAAW;IAC7B,OAAOR,iBAAiB;EAC1B;EAEUS,aAAaA,CAAA,EAAW;IAChC,OAAOR,8BAA8B;EACvC;EAEUS,wBAAwBA,CAAA,EAAW;IAC3C,OAAOR,iCAAiC;EAC1C;EAEUS,yBAAyBA,CAAA,EAAW;IAC5C,OAAO,gCAAgC;EACzC;AACF","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -3,8 +3,13 @@
|
|
|
3
3
|
// Adapter
|
|
4
4
|
export { SolanaAdapter } from './adapter';
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// Generic exports
|
|
7
|
+
export { SolanaDeeplinkProvider, SOLANA_SIGNING_METHODS } from './providers/SolanaDeeplinkProvider';
|
|
8
|
+
export { SolanaDeeplinkConnector } from './connectors/SolanaDeeplinkConnector';
|
|
7
9
|
|
|
8
|
-
//
|
|
10
|
+
// Wallet-specific exports
|
|
9
11
|
export { PhantomConnector } from './connectors/PhantomConnector';
|
|
12
|
+
export { SolflareConnector } from './connectors/SolflareConnector';
|
|
13
|
+
|
|
14
|
+
// Types
|
|
10
15
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["SolanaAdapter","PhantomConnector"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA;AACA,SAASA,aAAa,QAAQ,WAAW;;AAEzC;;
|
|
1
|
+
{"version":3,"names":["SolanaAdapter","SolanaDeeplinkProvider","SOLANA_SIGNING_METHODS","SolanaDeeplinkConnector","PhantomConnector","SolflareConnector"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA;AACA,SAASA,aAAa,QAAQ,WAAW;;AAEzC;AACA,SAASC,sBAAsB,EAAEC,sBAAsB,QAAQ,oCAAoC;AACnG,SAASC,uBAAuB,QAAQ,sCAAsC;;AAE9E;AACA,SAASC,gBAAgB,QAAQ,+BAA+B;AAChE,SAASC,iBAAiB,QAAQ,gCAAgC;;AAElE","ignoreList":[]}
|
|
@@ -5,8 +5,6 @@ import nacl from 'tweetnacl';
|
|
|
5
5
|
import bs58 from 'bs58';
|
|
6
6
|
import { Buffer } from 'buffer';
|
|
7
7
|
import EventEmitter from 'events';
|
|
8
|
-
const PHANTOM_BASE_URL = 'https://phantom.app/ul/v1';
|
|
9
|
-
const PHANTOM_PROVIDER_STORAGE_KEY = '@appkit/phantom-provider-session';
|
|
10
8
|
export const SOLANA_SIGNING_METHODS = {
|
|
11
9
|
SOLANA_SIGN_TRANSACTION: 'solana_signTransaction',
|
|
12
10
|
SOLANA_SIGN_MESSAGE: 'solana_signMessage',
|
|
@@ -16,17 +14,20 @@ export const SOLANA_SIGNING_METHODS = {
|
|
|
16
14
|
function isValidSolanaSigningMethod(method) {
|
|
17
15
|
return Object.values(SOLANA_SIGNING_METHODS).includes(method);
|
|
18
16
|
}
|
|
19
|
-
export class
|
|
17
|
+
export class SolanaDeeplinkProvider extends EventEmitter {
|
|
20
18
|
currentCluster = 'mainnet-beta';
|
|
21
19
|
sessionToken = null;
|
|
22
20
|
userPublicKey = null;
|
|
23
|
-
|
|
21
|
+
walletEncryptionPublicKeyBs58 = null;
|
|
24
22
|
constructor(config) {
|
|
25
23
|
super();
|
|
26
24
|
this.config = config;
|
|
27
25
|
this.dappEncryptionKeyPair = config.dappEncryptionKeyPair;
|
|
28
26
|
this.storage = config.storage;
|
|
29
27
|
}
|
|
28
|
+
getStorageKey() {
|
|
29
|
+
return `@appkit/${this.config.walletType}-provider-session`;
|
|
30
|
+
}
|
|
30
31
|
getUserPublicKey() {
|
|
31
32
|
return this.userPublicKey;
|
|
32
33
|
}
|
|
@@ -35,7 +36,7 @@ export class PhantomProvider extends EventEmitter {
|
|
|
35
36
|
}
|
|
36
37
|
buildUrl(rpcMethod, params) {
|
|
37
38
|
const query = new URLSearchParams(params).toString();
|
|
38
|
-
return `${
|
|
39
|
+
return `${this.config.baseUrl}/${rpcMethod}?${query}`;
|
|
39
40
|
}
|
|
40
41
|
getRpcMethodName(method) {
|
|
41
42
|
switch (method) {
|
|
@@ -52,15 +53,15 @@ export class PhantomProvider extends EventEmitter {
|
|
|
52
53
|
throw new Error(`Unsupported Solana signing method: ${method}`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
|
-
encryptPayload(payload,
|
|
56
|
-
if (!
|
|
56
|
+
encryptPayload(payload, walletPublicKeyBs58ToEncryptFor) {
|
|
57
|
+
if (!walletPublicKeyBs58ToEncryptFor) {
|
|
57
58
|
return null;
|
|
58
59
|
}
|
|
59
60
|
try {
|
|
60
|
-
const
|
|
61
|
+
const walletPublicKeyBytes = bs58.decode(walletPublicKeyBs58ToEncryptFor);
|
|
61
62
|
const nonce = nacl.randomBytes(nacl.box.nonceLength);
|
|
62
63
|
const payloadBytes = Buffer.from(JSON.stringify(payload), 'utf8');
|
|
63
|
-
const encryptedPayload = nacl.box(payloadBytes, nonce,
|
|
64
|
+
const encryptedPayload = nacl.box(payloadBytes, nonce, walletPublicKeyBytes, this.dappEncryptionKeyPair.secretKey);
|
|
64
65
|
return {
|
|
65
66
|
nonce: bs58.encode(nonce),
|
|
66
67
|
encryptedPayload: bs58.encode(encryptedPayload)
|
|
@@ -69,12 +70,12 @@ export class PhantomProvider extends EventEmitter {
|
|
|
69
70
|
return null;
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
decryptPayload(encryptedDataBs58, nonceBs58,
|
|
73
|
+
decryptPayload(encryptedDataBs58, nonceBs58, walletSenderPublicKeyBs58) {
|
|
73
74
|
try {
|
|
74
75
|
const encryptedDataBytes = bs58.decode(encryptedDataBs58);
|
|
75
76
|
const nonceBytes = bs58.decode(nonceBs58);
|
|
76
|
-
const
|
|
77
|
-
const decryptedPayloadBytes = nacl.box.open(encryptedDataBytes, nonceBytes,
|
|
77
|
+
const walletSenderPublicKeyBytes = bs58.decode(walletSenderPublicKeyBs58);
|
|
78
|
+
const decryptedPayloadBytes = nacl.box.open(encryptedDataBytes, nonceBytes, walletSenderPublicKeyBytes, this.dappEncryptionKeyPair.secretKey);
|
|
78
79
|
if (!decryptedPayloadBytes) {
|
|
79
80
|
return null;
|
|
80
81
|
}
|
|
@@ -85,40 +86,40 @@ export class PhantomProvider extends EventEmitter {
|
|
|
85
86
|
}
|
|
86
87
|
async restoreSession() {
|
|
87
88
|
try {
|
|
88
|
-
const session = await this.storage.getItem(
|
|
89
|
+
const session = await this.storage.getItem(this.getStorageKey());
|
|
89
90
|
if (session) {
|
|
90
91
|
this.setSession(session);
|
|
91
92
|
return true;
|
|
92
93
|
}
|
|
93
94
|
return false;
|
|
94
95
|
} catch (error) {
|
|
95
|
-
// console.error(
|
|
96
|
+
// console.error(`${this.config.walletType}Provider: Failed to restore session.`, error);
|
|
96
97
|
await this.clearSessionStorage(); // Clear potentially corrupt data
|
|
97
98
|
|
|
98
99
|
return false;
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
async saveSession() {
|
|
102
|
-
if (!this.sessionToken || !this.userPublicKey || !this.
|
|
103
|
+
if (!this.sessionToken || !this.userPublicKey || !this.walletEncryptionPublicKeyBs58) {
|
|
103
104
|
return; // Cannot save incomplete session
|
|
104
105
|
}
|
|
105
106
|
const session = {
|
|
106
107
|
sessionToken: this.sessionToken,
|
|
107
108
|
userPublicKey: this.userPublicKey,
|
|
108
|
-
|
|
109
|
+
walletEncryptionPublicKeyBs58: this.walletEncryptionPublicKeyBs58,
|
|
109
110
|
cluster: this.currentCluster
|
|
110
111
|
};
|
|
111
112
|
try {
|
|
112
|
-
await this.storage.setItem(
|
|
113
|
+
await this.storage.setItem(this.getStorageKey(), session);
|
|
113
114
|
} catch (error) {
|
|
114
|
-
// console.error(
|
|
115
|
+
// console.error(`${this.config.walletType}Provider: Failed to save session.`, error);
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
async clearSessionStorage() {
|
|
118
119
|
try {
|
|
119
|
-
await this.storage.removeItem(
|
|
120
|
+
await this.storage.removeItem(this.getStorageKey());
|
|
120
121
|
} catch (error) {
|
|
121
|
-
// console.error(
|
|
122
|
+
// console.error(`${this.config.walletType}Provider: Failed to clear session storage.`, error);
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
125
|
async connect(params) {
|
|
@@ -143,34 +144,35 @@ export class PhantomProvider extends EventEmitter {
|
|
|
143
144
|
const errorCode = responseUrlParams.get('errorCode');
|
|
144
145
|
const errorMessage = responseUrlParams.get('errorMessage');
|
|
145
146
|
if (errorCode) {
|
|
146
|
-
return reject(new Error(
|
|
147
|
+
return reject(new Error(`${this.config.walletType} Connection Failed: ${errorMessage || 'Unknown error'} (Code: ${errorCode})`));
|
|
147
148
|
}
|
|
149
|
+
const walletEncryptionPublicKey = responseUrlParams.get(this.config.encryptionKeyFieldName);
|
|
148
150
|
const responsePayload = {
|
|
149
|
-
|
|
151
|
+
wallet_encryption_public_key: walletEncryptionPublicKey,
|
|
150
152
|
nonce: responseUrlParams.get('nonce'),
|
|
151
153
|
data: responseUrlParams.get('data')
|
|
152
154
|
};
|
|
153
|
-
if (!responsePayload.
|
|
154
|
-
return reject(new Error(
|
|
155
|
+
if (!responsePayload.wallet_encryption_public_key || !responsePayload.nonce || !responsePayload.data) {
|
|
156
|
+
return reject(new Error(`${this.config.walletType} Connect: Invalid response - missing parameters.`));
|
|
155
157
|
}
|
|
156
|
-
const decryptedData = this.decryptPayload(responsePayload.data, responsePayload.nonce, responsePayload.
|
|
158
|
+
const decryptedData = this.decryptPayload(responsePayload.data, responsePayload.nonce, responsePayload.wallet_encryption_public_key);
|
|
157
159
|
if (!decryptedData || !decryptedData.public_key || !decryptedData.session) {
|
|
158
|
-
return reject(new Error(
|
|
160
|
+
return reject(new Error(`${this.config.walletType} Connect: Failed to decrypt or invalid decrypted data.`));
|
|
159
161
|
}
|
|
160
162
|
this.userPublicKey = decryptedData.public_key;
|
|
161
163
|
this.sessionToken = decryptedData.session;
|
|
162
|
-
this.
|
|
164
|
+
this.walletEncryptionPublicKeyBs58 = responsePayload.wallet_encryption_public_key;
|
|
163
165
|
|
|
164
166
|
// Save session on successful connect
|
|
165
167
|
this.saveSession();
|
|
166
168
|
resolve({
|
|
167
169
|
userPublicKey: this.userPublicKey,
|
|
168
170
|
sessionToken: this.sessionToken,
|
|
169
|
-
|
|
171
|
+
walletEncryptionPublicKeyBs58: this.walletEncryptionPublicKeyBs58,
|
|
170
172
|
cluster
|
|
171
173
|
});
|
|
172
174
|
} else {
|
|
173
|
-
reject(new Error(
|
|
175
|
+
reject(new Error(`${this.config.walletType} Connect: Unexpected redirect URI.`));
|
|
174
176
|
}
|
|
175
177
|
};
|
|
176
178
|
subscription = Linking.addEventListener('url', handleDeepLink);
|
|
@@ -178,12 +180,12 @@ export class PhantomProvider extends EventEmitter {
|
|
|
178
180
|
if (subscription) {
|
|
179
181
|
subscription.remove();
|
|
180
182
|
}
|
|
181
|
-
reject(new Error(`Failed to open
|
|
183
|
+
reject(new Error(`Failed to open ${this.config.walletType} wallet: ${err.message}. Is it installed?`));
|
|
182
184
|
});
|
|
183
185
|
});
|
|
184
186
|
}
|
|
185
187
|
async disconnect() {
|
|
186
|
-
if (!this.sessionToken || !this.
|
|
188
|
+
if (!this.sessionToken || !this.walletEncryptionPublicKeyBs58) {
|
|
187
189
|
await this.clearSession();
|
|
188
190
|
this.emit('disconnect');
|
|
189
191
|
return Promise.resolve();
|
|
@@ -191,9 +193,9 @@ export class PhantomProvider extends EventEmitter {
|
|
|
191
193
|
const payloadToEncrypt = {
|
|
192
194
|
session: this.sessionToken
|
|
193
195
|
};
|
|
194
|
-
const encryptedDisconnectPayload = this.encryptPayload(payloadToEncrypt, this.
|
|
196
|
+
const encryptedDisconnectPayload = this.encryptPayload(payloadToEncrypt, this.walletEncryptionPublicKeyBs58);
|
|
195
197
|
if (!encryptedDisconnectPayload) {
|
|
196
|
-
// console.warn(
|
|
198
|
+
// console.warn(`${this.config.walletType}Provider: Failed to encrypt disconnect payload. Clearing session locally.`);
|
|
197
199
|
await this.clearSession();
|
|
198
200
|
this.emit('disconnect');
|
|
199
201
|
return Promise.resolve(); // Or reject, depending on desired strictness
|
|
@@ -216,7 +218,7 @@ export class PhantomProvider extends EventEmitter {
|
|
|
216
218
|
resolve();
|
|
217
219
|
} else {
|
|
218
220
|
this.clearSession();
|
|
219
|
-
reject(new Error(
|
|
221
|
+
reject(new Error(`${this.config.walletType} Disconnect: Unexpected redirect URI.`));
|
|
220
222
|
}
|
|
221
223
|
};
|
|
222
224
|
subscription = Linking.addEventListener('url', handleDeepLink);
|
|
@@ -225,30 +227,30 @@ export class PhantomProvider extends EventEmitter {
|
|
|
225
227
|
subscription.remove();
|
|
226
228
|
}
|
|
227
229
|
this.clearSession();
|
|
228
|
-
reject(new Error(`Failed to open
|
|
230
|
+
reject(new Error(`Failed to open ${this.config.walletType} for disconnection: ${err.message}.`));
|
|
229
231
|
});
|
|
230
232
|
});
|
|
231
233
|
}
|
|
232
234
|
async clearSession() {
|
|
233
235
|
this.sessionToken = null;
|
|
234
236
|
this.userPublicKey = null;
|
|
235
|
-
this.
|
|
237
|
+
this.walletEncryptionPublicKeyBs58 = null;
|
|
236
238
|
await this.clearSessionStorage();
|
|
237
239
|
}
|
|
238
240
|
setSession(session) {
|
|
239
241
|
this.sessionToken = session.sessionToken;
|
|
240
242
|
this.userPublicKey = session.userPublicKey;
|
|
241
|
-
this.
|
|
243
|
+
this.walletEncryptionPublicKeyBs58 = session.walletEncryptionPublicKeyBs58;
|
|
242
244
|
this.currentCluster = session.cluster;
|
|
243
245
|
}
|
|
244
246
|
async request(args, _chainId) {
|
|
245
247
|
if (!isValidSolanaSigningMethod(args.method)) {
|
|
246
|
-
throw new Error(
|
|
248
|
+
throw new Error(`${this.config.walletType}Provider: Unsupported method: ${args.method}. Only Solana signing methods are supported.`);
|
|
247
249
|
}
|
|
248
250
|
const signingMethod = args.method;
|
|
249
251
|
const requestParams = args.params;
|
|
250
|
-
if (!this.isConnected() || !this.sessionToken || !this.
|
|
251
|
-
throw new Error(
|
|
252
|
+
if (!this.isConnected() || !this.sessionToken || !this.walletEncryptionPublicKeyBs58) {
|
|
253
|
+
throw new Error(`${this.config.walletType}Provider: Not connected or session details missing. Cannot process request.`);
|
|
252
254
|
}
|
|
253
255
|
const rpcMethodName = this.getRpcMethodName(signingMethod);
|
|
254
256
|
let deeplinkUrl = '';
|
|
@@ -264,9 +266,9 @@ export class PhantomProvider extends EventEmitter {
|
|
|
264
266
|
session: this.sessionToken,
|
|
265
267
|
transaction: typedParams.transaction
|
|
266
268
|
};
|
|
267
|
-
const encryptedData = this.encryptPayload(dataToEncrypt, this.
|
|
269
|
+
const encryptedData = this.encryptPayload(dataToEncrypt, this.walletEncryptionPublicKeyBs58);
|
|
268
270
|
if (!encryptedData) {
|
|
269
|
-
throw new Error(
|
|
271
|
+
throw new Error(`${this.config.walletType}Provider: Failed to encrypt payload for ${signingMethod}.`);
|
|
270
272
|
}
|
|
271
273
|
const signTxDeeplinkParams = {
|
|
272
274
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
@@ -302,9 +304,9 @@ export class PhantomProvider extends EventEmitter {
|
|
|
302
304
|
session: this.sessionToken,
|
|
303
305
|
display: typedParams.display || 'utf8'
|
|
304
306
|
};
|
|
305
|
-
const encryptedPayloadData = this.encryptPayload(dataToEncrypt, this.
|
|
307
|
+
const encryptedPayloadData = this.encryptPayload(dataToEncrypt, this.walletEncryptionPublicKeyBs58);
|
|
306
308
|
if (!encryptedPayloadData) {
|
|
307
|
-
throw new Error(
|
|
309
|
+
throw new Error(`${this.config.walletType}Provider: Failed to encrypt payload for signMessage.`);
|
|
308
310
|
}
|
|
309
311
|
const signMsgDeeplinkQueryPayload = {
|
|
310
312
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
@@ -325,9 +327,9 @@ export class PhantomProvider extends EventEmitter {
|
|
|
325
327
|
session: this.sessionToken,
|
|
326
328
|
transactions: typedParams.transactions
|
|
327
329
|
};
|
|
328
|
-
const encryptedData = this.encryptPayload(dataToEncrypt, this.
|
|
330
|
+
const encryptedData = this.encryptPayload(dataToEncrypt, this.walletEncryptionPublicKeyBs58);
|
|
329
331
|
if (!encryptedData) {
|
|
330
|
-
throw new Error(
|
|
332
|
+
throw new Error(`${this.config.walletType}Provider: Failed to encrypt payload for ${signingMethod}.`);
|
|
331
333
|
}
|
|
332
334
|
const signAllTxDeeplinkParams = {
|
|
333
335
|
dapp_encryption_public_key: bs58.encode(this.dappEncryptionKeyPair.publicKey),
|
|
@@ -341,7 +343,7 @@ export class PhantomProvider extends EventEmitter {
|
|
|
341
343
|
}
|
|
342
344
|
default:
|
|
343
345
|
{
|
|
344
|
-
throw new Error(
|
|
346
|
+
throw new Error(`${this.config.walletType}Provider: Unhandled signing method: ${signingMethod}`);
|
|
345
347
|
}
|
|
346
348
|
}
|
|
347
349
|
return new Promise((resolve, reject) => {
|
|
@@ -356,20 +358,20 @@ export class PhantomProvider extends EventEmitter {
|
|
|
356
358
|
const errorCode = responseUrlParams.get('errorCode');
|
|
357
359
|
const errorMessage = responseUrlParams.get('errorMessage');
|
|
358
360
|
if (errorCode) {
|
|
359
|
-
return reject(new Error(
|
|
361
|
+
return reject(new Error(`${this.config.walletType} ${signingMethod} Failed: ${errorMessage || 'Unknown error'} (Code: ${errorCode})`));
|
|
360
362
|
}
|
|
361
363
|
const responseNonce = responseUrlParams.get('nonce');
|
|
362
364
|
const responseData = responseUrlParams.get('data');
|
|
363
365
|
if (!responseNonce || !responseData) {
|
|
364
|
-
return reject(new Error(
|
|
366
|
+
return reject(new Error(`${this.config.walletType} ${signingMethod}: Invalid response - missing nonce or data.`));
|
|
365
367
|
}
|
|
366
|
-
const decryptedResult = this.decryptPayload(responseData, responseNonce, this.
|
|
368
|
+
const decryptedResult = this.decryptPayload(responseData, responseNonce, this.walletEncryptionPublicKeyBs58);
|
|
367
369
|
if (!decryptedResult) {
|
|
368
|
-
return reject(new Error(
|
|
370
|
+
return reject(new Error(`${this.config.walletType} ${signingMethod}: Failed to decrypt response or invalid decrypted data.`));
|
|
369
371
|
}
|
|
370
372
|
resolve(decryptedResult);
|
|
371
373
|
} else {
|
|
372
|
-
reject(new Error(
|
|
374
|
+
reject(new Error(`${this.config.walletType} ${signingMethod}: Unexpected redirect URI.`));
|
|
373
375
|
}
|
|
374
376
|
};
|
|
375
377
|
subscription = Linking.addEventListener('url', handleDeepLink);
|
|
@@ -377,9 +379,9 @@ export class PhantomProvider extends EventEmitter {
|
|
|
377
379
|
if (subscription) {
|
|
378
380
|
subscription.remove();
|
|
379
381
|
}
|
|
380
|
-
reject(new Error(`Failed to open
|
|
382
|
+
reject(new Error(`Failed to open ${this.config.walletType} for ${signingMethod}: ${err.message}. Is it installed?`));
|
|
381
383
|
});
|
|
382
384
|
});
|
|
383
385
|
}
|
|
384
386
|
}
|
|
385
|
-
//# sourceMappingURL=
|
|
387
|
+
//# sourceMappingURL=SolanaDeeplinkProvider.js.map
|