@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,116 @@
|
|
|
1
|
+
import type { NetworkId, Namespace } from '@meshconnect/uwc-types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse a WalletConnect account string into its components
|
|
5
|
+
* Account format: "namespace:chainId:address"
|
|
6
|
+
* Example: "eip155:1:0x1234..." or "solana:mainnet:ABC123..."
|
|
7
|
+
*/
|
|
8
|
+
export function parseAccount(account: string): {
|
|
9
|
+
namespace: Namespace
|
|
10
|
+
chainId: string
|
|
11
|
+
networkId: NetworkId
|
|
12
|
+
address: string
|
|
13
|
+
} {
|
|
14
|
+
const parts = account.split(':')
|
|
15
|
+
if (parts.length < 3) {
|
|
16
|
+
throw new Error(`Invalid account format: ${account}`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const namespace = parts[0] as Namespace
|
|
20
|
+
const chainId = parts[1]!
|
|
21
|
+
const networkId = `${namespace}:${chainId}` as NetworkId
|
|
22
|
+
// Handle addresses that might contain colons (like some Solana addresses)
|
|
23
|
+
const address = parts.slice(2).join(':')
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
namespace,
|
|
27
|
+
chainId,
|
|
28
|
+
networkId,
|
|
29
|
+
address
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Build a WalletConnect account string from components
|
|
35
|
+
*/
|
|
36
|
+
export function buildAccount(
|
|
37
|
+
namespace: Namespace,
|
|
38
|
+
chainId: string,
|
|
39
|
+
address: string
|
|
40
|
+
): string {
|
|
41
|
+
return `${namespace}:${chainId}:${address}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract namespace from a network ID
|
|
46
|
+
* Example: "eip155:1" -> "eip155"
|
|
47
|
+
*/
|
|
48
|
+
export function getNamespaceFromNetworkId(networkId: NetworkId): Namespace {
|
|
49
|
+
const [namespace] = networkId.split(':')
|
|
50
|
+
return namespace as Namespace
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extract chain ID from a network ID
|
|
55
|
+
* Example: "eip155:1" -> "1"
|
|
56
|
+
*/
|
|
57
|
+
export function getChainIdFromNetworkId(networkId: NetworkId): string {
|
|
58
|
+
const [, chainId] = networkId.split(':')
|
|
59
|
+
return chainId || ''
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Find an account in session namespaces that matches the given network and address
|
|
64
|
+
*/
|
|
65
|
+
export function findAccountInNamespaces(
|
|
66
|
+
namespaces: Record<string, any>,
|
|
67
|
+
targetNetworkId: NetworkId,
|
|
68
|
+
targetAddress: string
|
|
69
|
+
): string | null {
|
|
70
|
+
for (const [, namespaceData] of Object.entries(namespaces)) {
|
|
71
|
+
for (const account of namespaceData.accounts || []) {
|
|
72
|
+
const { networkId, address } = parseAccount(account)
|
|
73
|
+
if (networkId === targetNetworkId && address === targetAddress) {
|
|
74
|
+
return account
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Extract all accounts from session namespaces
|
|
83
|
+
*/
|
|
84
|
+
export function extractAccountsFromNamespaces(
|
|
85
|
+
namespaces: Record<string, any>
|
|
86
|
+
): Array<{
|
|
87
|
+
account: string
|
|
88
|
+
namespace: Namespace
|
|
89
|
+
chainId: string
|
|
90
|
+
networkId: NetworkId
|
|
91
|
+
address: string
|
|
92
|
+
}> {
|
|
93
|
+
const accounts: Array<{
|
|
94
|
+
account: string
|
|
95
|
+
namespace: Namespace
|
|
96
|
+
chainId: string
|
|
97
|
+
networkId: NetworkId
|
|
98
|
+
address: string
|
|
99
|
+
}> = []
|
|
100
|
+
|
|
101
|
+
Object.entries(namespaces).forEach(([, namespaceData]) => {
|
|
102
|
+
;(namespaceData.accounts || []).forEach((account: string) => {
|
|
103
|
+
try {
|
|
104
|
+
const parsed = parseAccount(account)
|
|
105
|
+
accounts.push({
|
|
106
|
+
account,
|
|
107
|
+
...parsed
|
|
108
|
+
})
|
|
109
|
+
} catch {
|
|
110
|
+
// Skip invalid accounts
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
return accounts
|
|
116
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import bs58 from 'bs58'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Encode a string message to base58 format (used for Solana message signing)
|
|
5
|
+
*/
|
|
6
|
+
export const base58Encode = (message: string) => {
|
|
7
|
+
// Use TextEncoder for browser compatibility
|
|
8
|
+
const encoder = new TextEncoder()
|
|
9
|
+
const messageBytes = encoder.encode(message)
|
|
10
|
+
return bs58.encode(messageBytes)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const standardizeSignature = (
|
|
14
|
+
rawSignature: string | Uint8Array
|
|
15
|
+
): string => {
|
|
16
|
+
// First ensure we have a string
|
|
17
|
+
let signature =
|
|
18
|
+
typeof rawSignature === 'string' ? rawSignature : bs58.encode(rawSignature)
|
|
19
|
+
|
|
20
|
+
// If signature is longer than standard 88 chars, decode and re-encode
|
|
21
|
+
if (signature.length > 88) {
|
|
22
|
+
try {
|
|
23
|
+
const bytes = bs58.decode(signature)
|
|
24
|
+
const truncatedBytes = bytes.slice(0, 64)
|
|
25
|
+
signature = bs58.encode(truncatedBytes)
|
|
26
|
+
} catch {
|
|
27
|
+
throw new Error('Failed to normalize signature')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return signature
|
|
32
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { WalletError } from '@meshconnect/uwc-types'
|
|
2
|
+
import { WalletConnectorError } from '@meshconnect/uwc-types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parse an error and throw a WalletConnectorError
|
|
6
|
+
* Detects if the error is a user rejection or an unknown error
|
|
7
|
+
*/
|
|
8
|
+
export function parseError(error: unknown): never {
|
|
9
|
+
let message: string
|
|
10
|
+
let isRejected = false
|
|
11
|
+
|
|
12
|
+
// Handle different error formats
|
|
13
|
+
if (error && typeof error === 'object') {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
const errorObj = error as any
|
|
16
|
+
|
|
17
|
+
// Check for EIP-1193 error code
|
|
18
|
+
if (errorObj.code === 4001 || errorObj.code === 'ACTION_REJECTED') {
|
|
19
|
+
isRejected = true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Extract message
|
|
23
|
+
if (errorObj.message) {
|
|
24
|
+
message = errorObj.message
|
|
25
|
+
} else if (errorObj.error?.message) {
|
|
26
|
+
message = errorObj.error.message
|
|
27
|
+
} else {
|
|
28
|
+
message = String(error)
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
message = String(error)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// If not already marked as rejected, check message patterns
|
|
35
|
+
if (!isRejected) {
|
|
36
|
+
const rejectionPatterns = [
|
|
37
|
+
'user rejected',
|
|
38
|
+
'user denied',
|
|
39
|
+
'user cancelled',
|
|
40
|
+
'user canceled',
|
|
41
|
+
'rejected by user',
|
|
42
|
+
'denied by user',
|
|
43
|
+
'cancelled by user',
|
|
44
|
+
'canceled by user',
|
|
45
|
+
'user disapproved',
|
|
46
|
+
'user declined',
|
|
47
|
+
'action_rejected'
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
const lowerMessage = message.toLowerCase()
|
|
51
|
+
isRejected = rejectionPatterns.some(pattern =>
|
|
52
|
+
lowerMessage.includes(pattern.toLowerCase())
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const walletError: WalletError = {
|
|
57
|
+
type: isRejected ? 'rejected' : 'unknown',
|
|
58
|
+
message
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
throw new WalletConnectorError(walletError)
|
|
62
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SolanaNativeTransferRequest } from '@meshconnect/uwc-types'
|
|
2
|
+
import {
|
|
3
|
+
PublicKey,
|
|
4
|
+
SystemProgram,
|
|
5
|
+
Transaction,
|
|
6
|
+
VersionedTransaction
|
|
7
|
+
} from '@solana/web3.js'
|
|
8
|
+
|
|
9
|
+
export function getSolanaTransaction(params: SolanaNativeTransferRequest) {
|
|
10
|
+
if (!params.blockhash) {
|
|
11
|
+
throw new Error('Blockhash is required for Solana transactions')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const transaction: Transaction | VersionedTransaction = new Transaction().add(
|
|
15
|
+
SystemProgram.transfer({
|
|
16
|
+
fromPubkey: new PublicKey(params.from),
|
|
17
|
+
toPubkey: new PublicKey(params.to),
|
|
18
|
+
lamports: Number(params.amount)
|
|
19
|
+
})
|
|
20
|
+
)
|
|
21
|
+
transaction.recentBlockhash = params.blockhash
|
|
22
|
+
transaction.feePayer = new PublicKey(params.from)
|
|
23
|
+
return transaction
|
|
24
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Network,
|
|
3
|
+
Connector,
|
|
4
|
+
ConnectorResult,
|
|
5
|
+
SwitchNetworkResult,
|
|
6
|
+
WalletConnectConfig,
|
|
7
|
+
WalletConnectProvider,
|
|
8
|
+
TransactionRequest,
|
|
9
|
+
TransactionResult,
|
|
10
|
+
NetworkRpcMap
|
|
11
|
+
} from '@meshconnect/uwc-types'
|
|
12
|
+
import { WalletConnectClient } from './services/walletconnect-client'
|
|
13
|
+
import { ConnectionService } from './services/connection-service'
|
|
14
|
+
import { NetworkSwitchService } from './services/network-switch-service'
|
|
15
|
+
import { SignatureService } from './services/signature-service'
|
|
16
|
+
import { TransactionService } from './services/transaction-service'
|
|
17
|
+
|
|
18
|
+
export class WalletConnectConnector implements Connector {
|
|
19
|
+
private walletConnectClient: WalletConnectClient
|
|
20
|
+
private connectionService: ConnectionService
|
|
21
|
+
private networkSwitchService: NetworkSwitchService
|
|
22
|
+
private signatureService: SignatureService
|
|
23
|
+
private transactionService: TransactionService
|
|
24
|
+
private networkRpcMap: NetworkRpcMap
|
|
25
|
+
|
|
26
|
+
constructor(config: WalletConnectConfig, networkRpcMap: NetworkRpcMap = {}) {
|
|
27
|
+
this.walletConnectClient = new WalletConnectClient(config)
|
|
28
|
+
this.networkRpcMap = networkRpcMap
|
|
29
|
+
this.connectionService = new ConnectionService(this.walletConnectClient)
|
|
30
|
+
this.networkSwitchService = new NetworkSwitchService(
|
|
31
|
+
this.walletConnectClient,
|
|
32
|
+
this.connectionService
|
|
33
|
+
)
|
|
34
|
+
this.signatureService = new SignatureService(
|
|
35
|
+
this.walletConnectClient,
|
|
36
|
+
this.connectionService
|
|
37
|
+
)
|
|
38
|
+
this.transactionService = new TransactionService(
|
|
39
|
+
this.walletConnectClient,
|
|
40
|
+
this.connectionService,
|
|
41
|
+
this.networkRpcMap
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async connect(
|
|
46
|
+
network: Network,
|
|
47
|
+
provider?: WalletConnectProvider
|
|
48
|
+
): Promise<ConnectorResult> {
|
|
49
|
+
if (!provider) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
'WalletConnectProvider is required for WalletConnect connection'
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return this.connectionService.connect(network, provider)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getConnectionURI(): string {
|
|
59
|
+
const uri = this.connectionService.getConnectionURI()
|
|
60
|
+
if (!uri) {
|
|
61
|
+
throw new Error('No connection URI available. Call connect() first.')
|
|
62
|
+
}
|
|
63
|
+
return uri
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async disconnect(): Promise<void> {
|
|
67
|
+
return this.connectionService.disconnect()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async switchNetwork(network: Network): Promise<SwitchNetworkResult> {
|
|
71
|
+
return this.networkSwitchService.switchNetwork(network)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async signMessage(message: string): Promise<string> {
|
|
75
|
+
return this.signatureService.signMessage(message)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async sendTransaction(
|
|
79
|
+
request: TransactionRequest
|
|
80
|
+
): Promise<TransactionResult> {
|
|
81
|
+
return this.transactionService.sendTransaction(request)
|
|
82
|
+
}
|
|
83
|
+
}
|