@meshconnect/uwc-wallet-connect-connector 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/services/connection-service.d.ts +60 -0
- package/dist/services/connection-service.d.ts.map +1 -0
- package/dist/services/connection-service.js +235 -0
- package/dist/services/connection-service.js.map +1 -0
- package/dist/services/network-switch-service.d.ts +16 -0
- package/dist/services/network-switch-service.d.ts.map +1 -0
- package/dist/services/network-switch-service.js +71 -0
- package/dist/services/network-switch-service.js.map +1 -0
- package/dist/services/signature-service.d.ts +15 -0
- package/dist/services/signature-service.d.ts.map +1 -0
- package/dist/services/signature-service.js +102 -0
- package/dist/services/signature-service.js.map +1 -0
- package/dist/services/transaction-service.d.ts +33 -0
- package/dist/services/transaction-service.d.ts.map +1 -0
- package/dist/services/transaction-service.js +287 -0
- package/dist/services/transaction-service.js.map +1 -0
- package/dist/services/walletconnect-client.d.ts +28 -0
- package/dist/services/walletconnect-client.d.ts.map +1 -0
- package/dist/services/walletconnect-client.js +92 -0
- package/dist/services/walletconnect-client.js.map +1 -0
- package/dist/utils/account-utils.d.ts +41 -0
- package/dist/utils/account-utils.d.ts.map +1 -0
- package/dist/utils/account-utils.js +81 -0
- package/dist/utils/account-utils.js.map +1 -0
- package/dist/utils/encoding-utils.d.ts +6 -0
- package/dist/utils/encoding-utils.d.ts.map +1 -0
- package/dist/utils/encoding-utils.js +27 -0
- package/dist/utils/encoding-utils.js.map +1 -0
- package/dist/utils/error-utils.d.ts +6 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/error-utils.js +55 -0
- package/dist/utils/error-utils.js.map +1 -0
- package/dist/utils/solana-transactions.d.ts +4 -0
- package/dist/utils/solana-transactions.d.ts.map +1 -0
- package/dist/utils/solana-transactions.js +15 -0
- package/dist/utils/solana-transactions.js.map +1 -0
- package/dist/wallet-connect-connector.d.ts +17 -0
- package/dist/wallet-connect-connector.d.ts.map +1 -0
- package/dist/wallet-connect-connector.js +47 -0
- package/dist/wallet-connect-connector.js.map +1 -0
- package/package.json +41 -0
- package/src/index.ts +1 -0
- package/src/services/connection-service.ts +304 -0
- package/src/services/network-switch-service.ts +83 -0
- package/src/services/signature-service.ts +128 -0
- package/src/services/transaction-service.ts +397 -0
- package/src/services/walletconnect-client.ts +103 -0
- package/src/utils/account-utils.ts +116 -0
- package/src/utils/encoding-utils.ts +32 -0
- package/src/utils/error-utils.ts +62 -0
- package/src/utils/solana-transactions.ts +24 -0
- package/src/wallet-connect-connector.ts +83 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { WalletConnectorError } from '@meshconnect/uwc-types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse an error and throw a WalletConnectorError
|
|
4
|
+
* Detects if the error is a user rejection or an unknown error
|
|
5
|
+
*/
|
|
6
|
+
export function parseError(error) {
|
|
7
|
+
let message;
|
|
8
|
+
let isRejected = false;
|
|
9
|
+
// Handle different error formats
|
|
10
|
+
if (error && typeof error === 'object') {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
const errorObj = error;
|
|
13
|
+
// Check for EIP-1193 error code
|
|
14
|
+
if (errorObj.code === 4001 || errorObj.code === 'ACTION_REJECTED') {
|
|
15
|
+
isRejected = true;
|
|
16
|
+
}
|
|
17
|
+
// Extract message
|
|
18
|
+
if (errorObj.message) {
|
|
19
|
+
message = errorObj.message;
|
|
20
|
+
}
|
|
21
|
+
else if (errorObj.error?.message) {
|
|
22
|
+
message = errorObj.error.message;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
message = String(error);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
message = String(error);
|
|
30
|
+
}
|
|
31
|
+
// If not already marked as rejected, check message patterns
|
|
32
|
+
if (!isRejected) {
|
|
33
|
+
const rejectionPatterns = [
|
|
34
|
+
'user rejected',
|
|
35
|
+
'user denied',
|
|
36
|
+
'user cancelled',
|
|
37
|
+
'user canceled',
|
|
38
|
+
'rejected by user',
|
|
39
|
+
'denied by user',
|
|
40
|
+
'cancelled by user',
|
|
41
|
+
'canceled by user',
|
|
42
|
+
'user disapproved',
|
|
43
|
+
'user declined',
|
|
44
|
+
'action_rejected'
|
|
45
|
+
];
|
|
46
|
+
const lowerMessage = message.toLowerCase();
|
|
47
|
+
isRejected = rejectionPatterns.some(pattern => lowerMessage.includes(pattern.toLowerCase()));
|
|
48
|
+
}
|
|
49
|
+
const walletError = {
|
|
50
|
+
type: isRejected ? 'rejected' : 'unknown',
|
|
51
|
+
message
|
|
52
|
+
};
|
|
53
|
+
throw new WalletConnectorError(walletError);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=error-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-utils.js","sourceRoot":"","sources":["../../src/utils/error-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,OAAe,CAAA;IACnB,IAAI,UAAU,GAAG,KAAK,CAAA;IAEtB,iCAAiC;IACjC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,8DAA8D;QAC9D,MAAM,QAAQ,GAAG,KAAY,CAAA;QAE7B,gCAAgC;QAChC,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YAClE,UAAU,GAAG,IAAI,CAAA;QACnB,CAAC;QAED,kBAAkB;QAClB,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAA;QAC5B,CAAC;aAAM,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;YACnC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAA;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAED,4DAA4D;IAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,iBAAiB,GAAG;YACxB,eAAe;YACf,aAAa;YACb,gBAAgB;YAChB,eAAe;YACf,kBAAkB;YAClB,gBAAgB;YAChB,mBAAmB;YACnB,kBAAkB;YAClB,kBAAkB;YAClB,eAAe;YACf,iBAAiB;SAClB,CAAA;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;QAC1C,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAC5C,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAC7C,CAAA;IACH,CAAC;IAED,MAAM,WAAW,GAAgB;QAC/B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;QACzC,OAAO;KACR,CAAA;IAED,MAAM,IAAI,oBAAoB,CAAC,WAAW,CAAC,CAAA;AAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solana-transactions.d.ts","sourceRoot":"","sources":["../../src/utils/solana-transactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAGL,WAAW,EAEZ,MAAM,iBAAiB,CAAA;AAExB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,2BAA2B,eAevE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
2
|
+
export function getSolanaTransaction(params) {
|
|
3
|
+
if (!params.blockhash) {
|
|
4
|
+
throw new Error('Blockhash is required for Solana transactions');
|
|
5
|
+
}
|
|
6
|
+
const transaction = new Transaction().add(SystemProgram.transfer({
|
|
7
|
+
fromPubkey: new PublicKey(params.from),
|
|
8
|
+
toPubkey: new PublicKey(params.to),
|
|
9
|
+
lamports: Number(params.amount)
|
|
10
|
+
}));
|
|
11
|
+
transaction.recentBlockhash = params.blockhash;
|
|
12
|
+
transaction.feePayer = new PublicKey(params.from);
|
|
13
|
+
return transaction;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=solana-transactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solana-transactions.js","sourceRoot":"","sources":["../../src/utils/solana-transactions.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,aAAa,EACb,WAAW,EACX,oBAAoB,EACrB,MAAM,iBAAiB,CAAA;AAExB,MAAM,UAAU,oBAAoB,CAAC,MAAmC;IACtE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IAED,MAAM,WAAW,GAAuC,IAAI,WAAW,EAAE,CAAC,GAAG,CAC3E,aAAa,CAAC,QAAQ,CAAC;QACrB,UAAU,EAAE,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;QACtC,QAAQ,EAAE,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;KAChC,CAAC,CACH,CAAA;IACD,WAAW,CAAC,eAAe,GAAG,MAAM,CAAC,SAAS,CAAA;IAC9C,WAAW,CAAC,QAAQ,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACjD,OAAO,WAAW,CAAA;AACpB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Network, Connector, ConnectorResult, SwitchNetworkResult, WalletConnectConfig, WalletConnectProvider, TransactionRequest, TransactionResult, NetworkRpcMap } from '@meshconnect/uwc-types';
|
|
2
|
+
export declare class WalletConnectConnector implements Connector {
|
|
3
|
+
private walletConnectClient;
|
|
4
|
+
private connectionService;
|
|
5
|
+
private networkSwitchService;
|
|
6
|
+
private signatureService;
|
|
7
|
+
private transactionService;
|
|
8
|
+
private networkRpcMap;
|
|
9
|
+
constructor(config: WalletConnectConfig, networkRpcMap?: NetworkRpcMap);
|
|
10
|
+
connect(network: Network, provider?: WalletConnectProvider): Promise<ConnectorResult>;
|
|
11
|
+
getConnectionURI(): string;
|
|
12
|
+
disconnect(): Promise<void>;
|
|
13
|
+
switchNetwork(network: Network): Promise<SwitchNetworkResult>;
|
|
14
|
+
signMessage(message: string): Promise<string>;
|
|
15
|
+
sendTransaction(request: TransactionRequest): Promise<TransactionResult>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=wallet-connect-connector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-connect-connector.d.ts","sourceRoot":"","sources":["../src/wallet-connect-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACd,MAAM,wBAAwB,CAAA;AAO/B,qBAAa,sBAAuB,YAAW,SAAS;IACtD,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,iBAAiB,CAAmB;IAC5C,OAAO,CAAC,oBAAoB,CAAsB;IAClD,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,aAAa,CAAe;gBAExB,MAAM,EAAE,mBAAmB,EAAE,aAAa,GAAE,aAAkB;IAmBpE,OAAO,CACX,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,qBAAqB,GAC/B,OAAO,CAAC,eAAe,CAAC;IAU3B,gBAAgB,IAAI,MAAM;IAQpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI7D,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7C,eAAe,CACnB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC;CAG9B"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { WalletConnectClient } from './services/walletconnect-client';
|
|
2
|
+
import { ConnectionService } from './services/connection-service';
|
|
3
|
+
import { NetworkSwitchService } from './services/network-switch-service';
|
|
4
|
+
import { SignatureService } from './services/signature-service';
|
|
5
|
+
import { TransactionService } from './services/transaction-service';
|
|
6
|
+
export class WalletConnectConnector {
|
|
7
|
+
walletConnectClient;
|
|
8
|
+
connectionService;
|
|
9
|
+
networkSwitchService;
|
|
10
|
+
signatureService;
|
|
11
|
+
transactionService;
|
|
12
|
+
networkRpcMap;
|
|
13
|
+
constructor(config, networkRpcMap = {}) {
|
|
14
|
+
this.walletConnectClient = new WalletConnectClient(config);
|
|
15
|
+
this.networkRpcMap = networkRpcMap;
|
|
16
|
+
this.connectionService = new ConnectionService(this.walletConnectClient);
|
|
17
|
+
this.networkSwitchService = new NetworkSwitchService(this.walletConnectClient, this.connectionService);
|
|
18
|
+
this.signatureService = new SignatureService(this.walletConnectClient, this.connectionService);
|
|
19
|
+
this.transactionService = new TransactionService(this.walletConnectClient, this.connectionService, this.networkRpcMap);
|
|
20
|
+
}
|
|
21
|
+
async connect(network, provider) {
|
|
22
|
+
if (!provider) {
|
|
23
|
+
throw new Error('WalletConnectProvider is required for WalletConnect connection');
|
|
24
|
+
}
|
|
25
|
+
return this.connectionService.connect(network, provider);
|
|
26
|
+
}
|
|
27
|
+
getConnectionURI() {
|
|
28
|
+
const uri = this.connectionService.getConnectionURI();
|
|
29
|
+
if (!uri) {
|
|
30
|
+
throw new Error('No connection URI available. Call connect() first.');
|
|
31
|
+
}
|
|
32
|
+
return uri;
|
|
33
|
+
}
|
|
34
|
+
async disconnect() {
|
|
35
|
+
return this.connectionService.disconnect();
|
|
36
|
+
}
|
|
37
|
+
async switchNetwork(network) {
|
|
38
|
+
return this.networkSwitchService.switchNetwork(network);
|
|
39
|
+
}
|
|
40
|
+
async signMessage(message) {
|
|
41
|
+
return this.signatureService.signMessage(message);
|
|
42
|
+
}
|
|
43
|
+
async sendTransaction(request) {
|
|
44
|
+
return this.transactionService.sendTransaction(request);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=wallet-connect-connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-connect-connector.js","sourceRoot":"","sources":["../src/wallet-connect-connector.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAEnE,MAAM,OAAO,sBAAsB;IACzB,mBAAmB,CAAqB;IACxC,iBAAiB,CAAmB;IACpC,oBAAoB,CAAsB;IAC1C,gBAAgB,CAAkB;IAClC,kBAAkB,CAAoB;IACtC,aAAa,CAAe;IAEpC,YAAY,MAA2B,EAAE,gBAA+B,EAAE;QACxE,IAAI,CAAC,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAC1D,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;QAClC,IAAI,CAAC,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QACxE,IAAI,CAAC,oBAAoB,GAAG,IAAI,oBAAoB,CAClD,IAAI,CAAC,mBAAmB,EACxB,IAAI,CAAC,iBAAiB,CACvB,CAAA;QACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,gBAAgB,CAC1C,IAAI,CAAC,mBAAmB,EACxB,IAAI,CAAC,iBAAiB,CACvB,CAAA;QACD,IAAI,CAAC,kBAAkB,GAAG,IAAI,kBAAkB,CAC9C,IAAI,CAAC,mBAAmB,EACxB,IAAI,CAAC,iBAAiB,EACtB,IAAI,CAAC,aAAa,CACnB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAAgB,EAChB,QAAgC;QAEhC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAA;QACH,CAAC;QAED,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAC1D,CAAC;IAED,gBAAgB;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,CAAA;QACrD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QACvE,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAgB;QAClC,OAAO,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IACzD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,OAAO,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,OAA2B;QAE3B,OAAO,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;IACzD,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meshconnect/uwc-wallet-connect-connector",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "WalletConnect connector for Universal Wallet Connector",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@solana/web3.js": "^1.98.4",
|
|
20
|
+
"@walletconnect/sign-client": "^2.21.8",
|
|
21
|
+
"@walletconnect/types": "^2.21.8",
|
|
22
|
+
"@walletconnect/utils": "^2.21.8",
|
|
23
|
+
"bs58": "^6.0.0",
|
|
24
|
+
"buffer": "^6.0.3",
|
|
25
|
+
"ethers": "^6.15.0",
|
|
26
|
+
"@meshconnect/uwc-types": "0.2.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.9.2"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"dev": "tsc --watch",
|
|
37
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
38
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
39
|
+
"type-check": "tsc --noEmit"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './wallet-connect-connector'
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import type { SessionTypes } from '@walletconnect/types'
|
|
2
|
+
import type {
|
|
3
|
+
Network,
|
|
4
|
+
AvailableAddress,
|
|
5
|
+
ConnectorResult,
|
|
6
|
+
WalletConnectProvider,
|
|
7
|
+
Namespace
|
|
8
|
+
} from '@meshconnect/uwc-types'
|
|
9
|
+
import { WalletConnectClient } from './walletconnect-client'
|
|
10
|
+
import { parseAccount, getNamespaceFromNetworkId } from '../utils/account-utils'
|
|
11
|
+
import { parseError } from '../utils/error-utils'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Service for handling WalletConnect connections
|
|
15
|
+
*/
|
|
16
|
+
export class ConnectionService {
|
|
17
|
+
private currentSession: SessionTypes.Struct | null = null
|
|
18
|
+
private connectionUri: string | null = null
|
|
19
|
+
private activeNetwork: Network | null = null
|
|
20
|
+
private activeAddress: string | null = null
|
|
21
|
+
|
|
22
|
+
constructor(private walletConnectClient: WalletConnectClient) {}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Connect to a wallet via WalletConnect
|
|
26
|
+
* This will store the URI and wait for approval
|
|
27
|
+
*/
|
|
28
|
+
async connect(
|
|
29
|
+
network: Network,
|
|
30
|
+
provider: WalletConnectProvider
|
|
31
|
+
): Promise<ConnectorResult> {
|
|
32
|
+
try {
|
|
33
|
+
const client = await this.walletConnectClient.getClient()
|
|
34
|
+
|
|
35
|
+
// Disconnect any existing sessions first
|
|
36
|
+
await this.walletConnectClient.disconnectAll()
|
|
37
|
+
|
|
38
|
+
// Build namespaces from the provider's supported network IDs
|
|
39
|
+
const optionalNamespaces = this.buildNamespacesFromProvider(provider)
|
|
40
|
+
|
|
41
|
+
// Initiate connection - this starts the connection process
|
|
42
|
+
const connectResult = await client.connect({
|
|
43
|
+
optionalNamespaces
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (!connectResult.uri) {
|
|
47
|
+
throw new Error('No connection URI generated')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Store the URI immediately so it can be retrieved via getConnectionURI
|
|
51
|
+
this.connectionUri = connectResult.uri
|
|
52
|
+
|
|
53
|
+
// Start the approval process in the background
|
|
54
|
+
// The main thread will poll for the URI while this waits for approval
|
|
55
|
+
const approvalPromise = connectResult.approval()
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
// Wait for approval (this resolves when user approves in wallet)
|
|
59
|
+
const session = await approvalPromise
|
|
60
|
+
this.currentSession = session
|
|
61
|
+
this.connectionUri = null // Clear URI after connection
|
|
62
|
+
|
|
63
|
+
// Extract addresses from session
|
|
64
|
+
const { address, availableAddresses } = this.extractAddresses(
|
|
65
|
+
session,
|
|
66
|
+
network,
|
|
67
|
+
provider
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
// Store the active network and address
|
|
71
|
+
this.activeNetwork = network
|
|
72
|
+
this.activeAddress = address
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
networkId: network.id,
|
|
76
|
+
address,
|
|
77
|
+
availableAddresses
|
|
78
|
+
}
|
|
79
|
+
} catch (approvalError) {
|
|
80
|
+
this.connectionUri = null // Clear URI on error
|
|
81
|
+
throw approvalError
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
this.connectionUri = null // Clear URI on error
|
|
85
|
+
throw parseError(error)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get the current connection URI
|
|
91
|
+
*/
|
|
92
|
+
getConnectionURI(): string | null {
|
|
93
|
+
return this.connectionUri
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Build WalletConnect namespaces from provider's supported network IDs
|
|
98
|
+
*/
|
|
99
|
+
private buildNamespacesFromProvider(provider: WalletConnectProvider): Record<
|
|
100
|
+
string,
|
|
101
|
+
{
|
|
102
|
+
chains: string[]
|
|
103
|
+
methods: string[]
|
|
104
|
+
events: string[]
|
|
105
|
+
}
|
|
106
|
+
> {
|
|
107
|
+
const namespaces: Record<
|
|
108
|
+
string,
|
|
109
|
+
{
|
|
110
|
+
chains: string[]
|
|
111
|
+
methods: string[]
|
|
112
|
+
events: string[]
|
|
113
|
+
}
|
|
114
|
+
> = {}
|
|
115
|
+
|
|
116
|
+
// Group networks by namespace
|
|
117
|
+
const namespaceGroups: Record<Namespace, string[]> = {} as Record<
|
|
118
|
+
Namespace,
|
|
119
|
+
string[]
|
|
120
|
+
>
|
|
121
|
+
|
|
122
|
+
provider.supportedNetworkIds.forEach(networkId => {
|
|
123
|
+
const namespace = getNamespaceFromNetworkId(networkId)
|
|
124
|
+
if (!namespaceGroups[namespace]) {
|
|
125
|
+
namespaceGroups[namespace] = []
|
|
126
|
+
}
|
|
127
|
+
namespaceGroups[namespace]!.push(networkId)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Build namespaces for each group
|
|
131
|
+
Object.entries(namespaceGroups).forEach(([namespace, chains]) => {
|
|
132
|
+
switch (namespace) {
|
|
133
|
+
case 'eip155':
|
|
134
|
+
namespaces['eip155'] = {
|
|
135
|
+
chains,
|
|
136
|
+
methods: [
|
|
137
|
+
'personal_sign',
|
|
138
|
+
'eth_sign',
|
|
139
|
+
'eth_signTypedData',
|
|
140
|
+
'eth_signTypedData_v4',
|
|
141
|
+
'eth_sendTransaction',
|
|
142
|
+
'eth_sendRawTransaction',
|
|
143
|
+
'eth_accounts',
|
|
144
|
+
'eth_requestAccounts',
|
|
145
|
+
'wallet_switchEthereumChain',
|
|
146
|
+
'wallet_addEthereumChain'
|
|
147
|
+
],
|
|
148
|
+
events: ['chainChanged', 'accountsChanged']
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
|
|
152
|
+
case 'solana':
|
|
153
|
+
namespaces['solana'] = {
|
|
154
|
+
chains,
|
|
155
|
+
methods: [
|
|
156
|
+
'solana_signMessage',
|
|
157
|
+
'solana_signTransaction',
|
|
158
|
+
'solana_signAndSendTransaction',
|
|
159
|
+
'solana_getAccounts',
|
|
160
|
+
'solana_requestAccounts'
|
|
161
|
+
],
|
|
162
|
+
events: []
|
|
163
|
+
}
|
|
164
|
+
break
|
|
165
|
+
|
|
166
|
+
case 'bip122':
|
|
167
|
+
namespaces['bip122'] = {
|
|
168
|
+
chains,
|
|
169
|
+
methods: [
|
|
170
|
+
'sendTransfer',
|
|
171
|
+
'getAccountAddresses',
|
|
172
|
+
'signPsbt',
|
|
173
|
+
'signMessage'
|
|
174
|
+
],
|
|
175
|
+
events: ['bip122_addressesChanged']
|
|
176
|
+
}
|
|
177
|
+
break
|
|
178
|
+
|
|
179
|
+
case 'tron':
|
|
180
|
+
namespaces['tron'] = {
|
|
181
|
+
chains,
|
|
182
|
+
methods: ['tron_signTransaction', 'tron_signMessage'],
|
|
183
|
+
events: []
|
|
184
|
+
}
|
|
185
|
+
break
|
|
186
|
+
|
|
187
|
+
default:
|
|
188
|
+
// For unknown namespaces, include basic methods
|
|
189
|
+
namespaces[namespace] = {
|
|
190
|
+
chains,
|
|
191
|
+
methods: [],
|
|
192
|
+
events: []
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
return namespaces
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Extract addresses from a WalletConnect session
|
|
202
|
+
*/
|
|
203
|
+
private extractAddresses(
|
|
204
|
+
session: SessionTypes.Struct,
|
|
205
|
+
network: Network,
|
|
206
|
+
provider: WalletConnectProvider
|
|
207
|
+
): {
|
|
208
|
+
address: string
|
|
209
|
+
availableAddresses: AvailableAddress[]
|
|
210
|
+
} {
|
|
211
|
+
const availableAddresses: AvailableAddress[] = []
|
|
212
|
+
let primaryAddress = ''
|
|
213
|
+
|
|
214
|
+
// Extract addresses from all namespaces
|
|
215
|
+
Object.entries(session.namespaces).forEach(([, data]) => {
|
|
216
|
+
data.accounts.forEach((account: string) => {
|
|
217
|
+
try {
|
|
218
|
+
const { networkId, address } = parseAccount(account)
|
|
219
|
+
|
|
220
|
+
// Only include addresses for networks that are supported by the provider
|
|
221
|
+
if (provider.supportedNetworkIds.includes(networkId)) {
|
|
222
|
+
availableAddresses.push({
|
|
223
|
+
address,
|
|
224
|
+
networkId
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
// Set the primary address based on the requested network
|
|
228
|
+
if (networkId === network.id && !primaryAddress) {
|
|
229
|
+
primaryAddress = address
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} catch {
|
|
233
|
+
// Skip invalid account formats
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
// If no address for the specific network, use the first available
|
|
239
|
+
if (!primaryAddress && availableAddresses.length > 0) {
|
|
240
|
+
primaryAddress = availableAddresses[0]?.address || ''
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (!primaryAddress) {
|
|
244
|
+
throw new Error('No addresses found in session')
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return { address: primaryAddress, availableAddresses }
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get current session
|
|
252
|
+
*/
|
|
253
|
+
getSession(): SessionTypes.Struct | null {
|
|
254
|
+
return this.currentSession
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Set session (for restoration)
|
|
259
|
+
*/
|
|
260
|
+
setSession(session: SessionTypes.Struct): void {
|
|
261
|
+
this.currentSession = session
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get active network
|
|
266
|
+
*/
|
|
267
|
+
getActiveNetwork(): Network | null {
|
|
268
|
+
return this.activeNetwork
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Set active network (for network switching)
|
|
273
|
+
*/
|
|
274
|
+
setActiveNetwork(network: Network): void {
|
|
275
|
+
this.activeNetwork = network
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Get active address
|
|
280
|
+
*/
|
|
281
|
+
getActiveAddress(): string | null {
|
|
282
|
+
return this.activeAddress
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Set active address (for network/address switching)
|
|
287
|
+
*/
|
|
288
|
+
setActiveAddress(address: string): void {
|
|
289
|
+
this.activeAddress = address
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Disconnect current session
|
|
294
|
+
*/
|
|
295
|
+
async disconnect(): Promise<void> {
|
|
296
|
+
if (this.currentSession) {
|
|
297
|
+
await this.walletConnectClient.disconnect(this.currentSession.topic)
|
|
298
|
+
this.currentSession = null
|
|
299
|
+
}
|
|
300
|
+
this.connectionUri = null
|
|
301
|
+
this.activeNetwork = null
|
|
302
|
+
this.activeAddress = null
|
|
303
|
+
}
|
|
304
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Network, SwitchNetworkResult } from '@meshconnect/uwc-types'
|
|
2
|
+
import { WalletConnectClient } from './walletconnect-client'
|
|
3
|
+
import { ConnectionService } from './connection-service'
|
|
4
|
+
import { parseAccount } from '../utils/account-utils'
|
|
5
|
+
import { parseError } from '../utils/error-utils'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Service for handling network switching in WalletConnect
|
|
9
|
+
*/
|
|
10
|
+
export class NetworkSwitchService {
|
|
11
|
+
constructor(
|
|
12
|
+
private walletConnectClient: WalletConnectClient,
|
|
13
|
+
private connectionService: ConnectionService
|
|
14
|
+
) {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Switch to a different network
|
|
18
|
+
*/
|
|
19
|
+
async switchNetwork(network: Network): Promise<SwitchNetworkResult> {
|
|
20
|
+
try {
|
|
21
|
+
const session = this.connectionService.getSession()
|
|
22
|
+
if (!session) {
|
|
23
|
+
throw new Error('No active session. Please connect first.')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const client = await this.walletConnectClient.getClient()
|
|
27
|
+
|
|
28
|
+
// Check if the requested network is available in the session
|
|
29
|
+
const networkChain = network.id
|
|
30
|
+
const namespace = network.namespace
|
|
31
|
+
|
|
32
|
+
if (!session.namespaces[namespace]?.chains?.includes(networkChain)) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Network ${networkChain} is not available in the current session`
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// For WalletConnect, we can't directly switch networks
|
|
39
|
+
// The wallet controls the active network
|
|
40
|
+
// We can only request methods on specific chains
|
|
41
|
+
// Return the current address for the requested network
|
|
42
|
+
|
|
43
|
+
const accounts = session.namespaces[namespace]?.accounts || []
|
|
44
|
+
const matchingAccount = accounts.find(account =>
|
|
45
|
+
account.startsWith(networkChain)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
if (!matchingAccount) {
|
|
49
|
+
throw new Error(`No account found for network ${networkChain}`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Extract address from account string
|
|
53
|
+
const { address } = parseAccount(matchingAccount)
|
|
54
|
+
|
|
55
|
+
// Update the active network and address in the connection service
|
|
56
|
+
this.connectionService.setActiveNetwork(network)
|
|
57
|
+
this.connectionService.setActiveAddress(address)
|
|
58
|
+
|
|
59
|
+
// Emit a chainChanged event if switching within the same namespace
|
|
60
|
+
if (namespace === 'eip155') {
|
|
61
|
+
try {
|
|
62
|
+
await client.emit({
|
|
63
|
+
topic: session.topic,
|
|
64
|
+
event: {
|
|
65
|
+
name: 'chainChanged',
|
|
66
|
+
data: networkChain
|
|
67
|
+
},
|
|
68
|
+
chainId: networkChain
|
|
69
|
+
})
|
|
70
|
+
} catch {
|
|
71
|
+
// Some wallets may not support this event
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
networkId: network.id,
|
|
77
|
+
address
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw parseError(error)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|