cosmos-connect-core 0.1.16 → 0.1.18
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/adapters/CosmostationWallet.d.ts +1 -0
- package/dist/adapters/CosmostationWallet.js +5 -0
- package/dist/adapters/GalaxyStationWallet.d.ts +1 -0
- package/dist/adapters/GalaxyStationWallet.js +5 -0
- package/dist/adapters/KeplrWallet.d.ts +1 -0
- package/dist/adapters/KeplrWallet.js +5 -0
- package/dist/adapters/KeystoneWallet.d.ts +48 -0
- package/dist/adapters/KeystoneWallet.js +121 -0
- package/dist/adapters/LeapWallet.d.ts +1 -0
- package/dist/adapters/LeapWallet.js +5 -0
- package/dist/adapters/LedgerWallet.d.ts +30 -0
- package/dist/adapters/LedgerWallet.js +117 -0
- package/dist/adapters/StationWallet.d.ts +1 -0
- package/dist/adapters/StationWallet.js +5 -0
- package/dist/adapters/WalletConnectWallet.js +1 -1
- package/dist/adapters/utils/WalletConnectV2.js +1 -1
- package/dist/core/createClient.js +4 -2
- package/dist/core/types.d.ts +4 -1
- package/package.json +1 -1
|
@@ -34,6 +34,7 @@ export declare class CosmostationWallet implements WalletAdapter {
|
|
|
34
34
|
installed(): boolean;
|
|
35
35
|
getUri(): string;
|
|
36
36
|
onUpdate(callback: () => void): void;
|
|
37
|
+
connectViaWalletConnect(chain: Chain): Promise<Account>;
|
|
37
38
|
connect(chain: Chain): Promise<Account>;
|
|
38
39
|
disconnect(): Promise<void>;
|
|
39
40
|
signTx(_bytes: Uint8Array): Promise<Uint8Array>;
|
|
@@ -37,6 +37,11 @@ export class CosmostationWallet {
|
|
|
37
37
|
onUpdate(callback) {
|
|
38
38
|
this.wc?.onUpdate(callback);
|
|
39
39
|
}
|
|
40
|
+
async connectViaWalletConnect(chain) {
|
|
41
|
+
if (!this.wc)
|
|
42
|
+
throw new Error('WalletConnect not initialized for Cosmostation');
|
|
43
|
+
return this.wc.connect(chain);
|
|
44
|
+
}
|
|
40
45
|
async connect(chain) {
|
|
41
46
|
const cosmostation = window.cosmostation?.providers.keplr;
|
|
42
47
|
if (!cosmostation) {
|
|
@@ -29,6 +29,7 @@ export declare class GalaxyStationWallet implements WalletAdapter {
|
|
|
29
29
|
installed(): boolean;
|
|
30
30
|
getUri(): string;
|
|
31
31
|
onUpdate(callback: () => void): void;
|
|
32
|
+
connectViaWalletConnect(chain: Chain): Promise<Account>;
|
|
32
33
|
connect(chain: Chain): Promise<Account>;
|
|
33
34
|
disconnect(): Promise<void>;
|
|
34
35
|
signTx(_bytes: Uint8Array): Promise<Uint8Array>;
|
|
@@ -44,6 +44,11 @@ export class GalaxyStationWallet {
|
|
|
44
44
|
onUpdate(callback) {
|
|
45
45
|
this.wc?.onUpdate(callback);
|
|
46
46
|
}
|
|
47
|
+
async connectViaWalletConnect(chain) {
|
|
48
|
+
if (!this.wc)
|
|
49
|
+
throw new Error('WalletConnect not initialized for Galaxy Station');
|
|
50
|
+
return this.wc.connect(chain);
|
|
51
|
+
}
|
|
47
52
|
async connect(chain) {
|
|
48
53
|
const galaxyStation = window.galaxyStation;
|
|
49
54
|
if (!galaxyStation) {
|
|
@@ -30,6 +30,7 @@ export declare class KeplrWallet implements WalletAdapter {
|
|
|
30
30
|
installed(): boolean;
|
|
31
31
|
getUri(): string;
|
|
32
32
|
onUpdate(callback: () => void): void;
|
|
33
|
+
connectViaWalletConnect(chain: Chain): Promise<Account>;
|
|
33
34
|
connect(chain: Chain): Promise<Account>;
|
|
34
35
|
disconnect(): Promise<void>;
|
|
35
36
|
signTx(_bytes: Uint8Array): Promise<Uint8Array>;
|
|
@@ -37,6 +37,11 @@ export class KeplrWallet {
|
|
|
37
37
|
onUpdate(callback) {
|
|
38
38
|
this.wc?.onUpdate(callback);
|
|
39
39
|
}
|
|
40
|
+
async connectViaWalletConnect(chain) {
|
|
41
|
+
if (!this.wc)
|
|
42
|
+
throw new Error('WalletConnect not initialized for Keplr');
|
|
43
|
+
return this.wc.connect(chain);
|
|
44
|
+
}
|
|
40
45
|
async connect(chain) {
|
|
41
46
|
const keplr = window.keplr;
|
|
42
47
|
if (!keplr) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { WalletAdapter, Chain, Account } from '../core/types.js';
|
|
2
|
+
export interface KeystoneWalletOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Callback to show the QR scanner UI for reading CryptoMultiAccounts
|
|
5
|
+
* from the Keystone device (account sync).
|
|
6
|
+
* Must return the decoded UR data from the scanned QR code.
|
|
7
|
+
*/
|
|
8
|
+
onScanAccountQR?: () => Promise<{
|
|
9
|
+
xfp: string;
|
|
10
|
+
keys: KeystoneKey[];
|
|
11
|
+
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Callback to show the animated QR code for the Keystone device to scan,
|
|
14
|
+
* and then read the signed result QR back via webcam.
|
|
15
|
+
* @param ur - The UR-encoded sign request to display
|
|
16
|
+
* @returns The parsed signature from the scanned response QR
|
|
17
|
+
*/
|
|
18
|
+
onSignQR?: (ur: {
|
|
19
|
+
type: string;
|
|
20
|
+
cbor: string;
|
|
21
|
+
}) => Promise<{
|
|
22
|
+
signature: string;
|
|
23
|
+
publicKey: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export interface KeystoneKey {
|
|
27
|
+
hdPath: string;
|
|
28
|
+
pubKey: Uint8Array;
|
|
29
|
+
index: number;
|
|
30
|
+
}
|
|
31
|
+
export declare class KeystoneWallet implements WalletAdapter {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
icon: string;
|
|
35
|
+
private xfp;
|
|
36
|
+
private keys;
|
|
37
|
+
private currentAddress;
|
|
38
|
+
private currentPubKey;
|
|
39
|
+
private onScanAccountQR?;
|
|
40
|
+
private onSignQR?;
|
|
41
|
+
private _updateCallback?;
|
|
42
|
+
constructor(options?: KeystoneWalletOptions);
|
|
43
|
+
installed(): boolean;
|
|
44
|
+
onUpdate(callback: () => void): void;
|
|
45
|
+
connect(chain: Chain): Promise<Account>;
|
|
46
|
+
disconnect(): Promise<void>;
|
|
47
|
+
signTx(bytes: Uint8Array): Promise<Uint8Array>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a Cosmos bech32 address from a compressed secp256k1 public key.
|
|
3
|
+
* Uses ripemd160(sha256(pubkey)) → bech32.encode(prefix, words)
|
|
4
|
+
*/
|
|
5
|
+
async function pubKeyToAddress(compressedPubKey, prefix) {
|
|
6
|
+
// Use SubtleCrypto for SHA-256
|
|
7
|
+
const buf = new ArrayBuffer(compressedPubKey.byteLength);
|
|
8
|
+
new Uint8Array(buf).set(compressedPubKey);
|
|
9
|
+
const sha256Hash = new Uint8Array(await crypto.subtle.digest('SHA-256', buf));
|
|
10
|
+
// Manually compute RIPEMD-160 is complex — we'll dynamically import if available
|
|
11
|
+
// or use a lightweight approach
|
|
12
|
+
try {
|
|
13
|
+
const { ripemd160 } = await import('@noble/hashes/ripemd160');
|
|
14
|
+
const hash = ripemd160(sha256Hash);
|
|
15
|
+
const { bech32 } = await import('bech32');
|
|
16
|
+
return bech32.encode(prefix, bech32.toWords(hash));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Fallback: try @cosmjs/crypto
|
|
20
|
+
try {
|
|
21
|
+
const cosmCrypto = await import('@cosmjs/crypto');
|
|
22
|
+
const cosmEncoding = await import('@cosmjs/encoding');
|
|
23
|
+
const sha = cosmCrypto.sha256(compressedPubKey);
|
|
24
|
+
const ripe = cosmCrypto.ripemd160(sha);
|
|
25
|
+
return cosmEncoding.toBech32(prefix, ripe);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error('Cannot derive address: install @noble/hashes + bech32, or @cosmjs/crypto + @cosmjs/encoding');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class KeystoneWallet {
|
|
33
|
+
id = 'keystone';
|
|
34
|
+
name = 'Keystone';
|
|
35
|
+
icon = 'https://keyst.one/favicon.ico';
|
|
36
|
+
xfp = '';
|
|
37
|
+
keys = [];
|
|
38
|
+
currentAddress = '';
|
|
39
|
+
currentPubKey = new Uint8Array();
|
|
40
|
+
onScanAccountQR;
|
|
41
|
+
onSignQR;
|
|
42
|
+
_updateCallback;
|
|
43
|
+
constructor(options) {
|
|
44
|
+
this.onScanAccountQR = options?.onScanAccountQR;
|
|
45
|
+
this.onSignQR = options?.onSignQR;
|
|
46
|
+
}
|
|
47
|
+
installed() {
|
|
48
|
+
// Keystone is always available — it uses QR codes, no extension needed.
|
|
49
|
+
// Only requires a camera for scanning.
|
|
50
|
+
return (typeof navigator !== 'undefined' &&
|
|
51
|
+
typeof navigator.mediaDevices !== 'undefined');
|
|
52
|
+
}
|
|
53
|
+
onUpdate(callback) {
|
|
54
|
+
this._updateCallback = callback;
|
|
55
|
+
}
|
|
56
|
+
async connect(chain) {
|
|
57
|
+
// If we don't have keys yet, trigger the QR scan flow
|
|
58
|
+
if (this.keys.length === 0) {
|
|
59
|
+
if (!this.onScanAccountQR) {
|
|
60
|
+
throw new Error('Keystone requires onScanAccountQR callback to read account data from the device.');
|
|
61
|
+
}
|
|
62
|
+
const result = await this.onScanAccountQR();
|
|
63
|
+
this.xfp = result.xfp;
|
|
64
|
+
this.keys = result.keys;
|
|
65
|
+
}
|
|
66
|
+
if (this.keys.length === 0) {
|
|
67
|
+
throw new Error('No keys found from Keystone device.');
|
|
68
|
+
}
|
|
69
|
+
// Use the first key to derive the address for this chain's bech32 prefix
|
|
70
|
+
const key = this.keys[0];
|
|
71
|
+
this.currentPubKey = key.pubKey;
|
|
72
|
+
this.currentAddress = await pubKeyToAddress(key.pubKey, chain.bech32Prefix);
|
|
73
|
+
return {
|
|
74
|
+
address: this.currentAddress,
|
|
75
|
+
pubKey: this.currentPubKey,
|
|
76
|
+
algo: 'secp256k1',
|
|
77
|
+
name: 'Keystone',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async disconnect() {
|
|
81
|
+
this.xfp = '';
|
|
82
|
+
this.keys = [];
|
|
83
|
+
this.currentAddress = '';
|
|
84
|
+
this.currentPubKey = new Uint8Array();
|
|
85
|
+
}
|
|
86
|
+
async signTx(bytes) {
|
|
87
|
+
if (!this.onSignQR) {
|
|
88
|
+
throw new Error('Keystone requires onSignQR callback for transaction signing.');
|
|
89
|
+
}
|
|
90
|
+
if (this.keys.length === 0) {
|
|
91
|
+
throw new Error('Keystone not connected.');
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const { KeystoneCosmosSDK } = await import('@keystonehq/keystone-sdk');
|
|
95
|
+
const sdk = new KeystoneCosmosSDK();
|
|
96
|
+
// Generate the sign request UR
|
|
97
|
+
const signDataHex = Buffer.from(bytes).toString('hex');
|
|
98
|
+
const requestId = crypto.randomUUID();
|
|
99
|
+
const ur = sdk.generateSignRequest({
|
|
100
|
+
requestId,
|
|
101
|
+
signData: signDataHex,
|
|
102
|
+
dataType: 1,
|
|
103
|
+
accounts: [
|
|
104
|
+
{
|
|
105
|
+
path: this.keys[0].hdPath,
|
|
106
|
+
xfp: this.xfp,
|
|
107
|
+
address: this.currentAddress,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
// Show QR and wait for user to scan back the signed result
|
|
112
|
+
const result = await this.onSignQR(ur);
|
|
113
|
+
// Convert hex signature to bytes
|
|
114
|
+
const sigBytes = new Uint8Array(result.signature.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
|
115
|
+
return sigBytes;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
throw new Error(`Keystone signing failed: ${error.message}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -28,6 +28,7 @@ export declare class LeapWallet implements WalletAdapter {
|
|
|
28
28
|
installed(): boolean;
|
|
29
29
|
getUri(): string;
|
|
30
30
|
onUpdate(callback: () => void): void;
|
|
31
|
+
connectViaWalletConnect(chain: Chain): Promise<Account>;
|
|
31
32
|
connect(chain: Chain): Promise<Account>;
|
|
32
33
|
disconnect(): Promise<void>;
|
|
33
34
|
signTx(_bytes: Uint8Array): Promise<Uint8Array>;
|
|
@@ -37,6 +37,11 @@ export class LeapWallet {
|
|
|
37
37
|
onUpdate(callback) {
|
|
38
38
|
this.wc?.onUpdate(callback);
|
|
39
39
|
}
|
|
40
|
+
async connectViaWalletConnect(chain) {
|
|
41
|
+
if (!this.wc)
|
|
42
|
+
throw new Error('WalletConnect not initialized for Leap');
|
|
43
|
+
return this.wc.connect(chain);
|
|
44
|
+
}
|
|
40
45
|
async connect(chain) {
|
|
41
46
|
const leap = window.leap;
|
|
42
47
|
if (!leap) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { WalletAdapter, Chain, Account } from '../core/types.js';
|
|
2
|
+
export interface LedgerWalletOptions {
|
|
3
|
+
/** Override coin type for specific chains */
|
|
4
|
+
coinTypePaths?: Record<string, number>;
|
|
5
|
+
}
|
|
6
|
+
export declare class LedgerWallet implements WalletAdapter {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
icon: string;
|
|
10
|
+
private transport;
|
|
11
|
+
private signer;
|
|
12
|
+
private coinTypePaths;
|
|
13
|
+
constructor(options?: LedgerWalletOptions);
|
|
14
|
+
installed(): boolean;
|
|
15
|
+
connect(chain: Chain): Promise<Account>;
|
|
16
|
+
disconnect(): Promise<void>;
|
|
17
|
+
signTx(bytes: Uint8Array): Promise<Uint8Array>;
|
|
18
|
+
/**
|
|
19
|
+
* Get the CosmJS-compatible offline signer for use with SigningStargateClient.
|
|
20
|
+
* This is the recommended way to sign transactions with Ledger.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const signer = ledgerWallet.getOfflineSigner();
|
|
25
|
+
* const client = await SigningStargateClient.connectWithSigner(rpcUrl, signer);
|
|
26
|
+
* await client.sendTokens(sender, recipient, amount, fee);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
getOfflineSigner(): any;
|
|
30
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HD derivation paths by coin type.
|
|
3
|
+
* Most Cosmos chains use coin_type 118; some have their own.
|
|
4
|
+
*/
|
|
5
|
+
const COIN_TYPE_PATHS = {
|
|
6
|
+
'columbus-5': 330,
|
|
7
|
+
'phoenix-1': 330,
|
|
8
|
+
'rebel-2': 330,
|
|
9
|
+
'secret-4': 529,
|
|
10
|
+
'injective-1': 60,
|
|
11
|
+
'evmos_9001-2': 60, // Evmos
|
|
12
|
+
};
|
|
13
|
+
const DEFAULT_COIN_TYPE = 118;
|
|
14
|
+
function makeHdPath(coinType, account = 0) {
|
|
15
|
+
// BIP44: m/44'/coinType'/account'/0/0
|
|
16
|
+
return [44, coinType, account, 0, 0];
|
|
17
|
+
}
|
|
18
|
+
export class LedgerWallet {
|
|
19
|
+
id = 'ledger';
|
|
20
|
+
name = 'Ledger';
|
|
21
|
+
icon = 'https://raw.githubusercontent.com/AstroportFinance/astroport-token-lists/main/logos/ledger.svg';
|
|
22
|
+
transport = null;
|
|
23
|
+
signer = null;
|
|
24
|
+
coinTypePaths;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.coinTypePaths = {
|
|
27
|
+
...COIN_TYPE_PATHS,
|
|
28
|
+
...options?.coinTypePaths,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
installed() {
|
|
32
|
+
// Ledger is available if browser supports WebHID
|
|
33
|
+
return typeof navigator !== 'undefined' && !!navigator?.hid;
|
|
34
|
+
}
|
|
35
|
+
async connect(chain) {
|
|
36
|
+
// Dynamically import Ledger packages to avoid bundling them for non-Ledger users
|
|
37
|
+
const [{ default: TransportWebHID }, { LedgerSigner }, { stringToPath }] = await Promise.all([
|
|
38
|
+
import('@ledgerhq/hw-transport-webhid'),
|
|
39
|
+
import('@cosmjs/ledger-amino'),
|
|
40
|
+
import('@cosmjs/crypto'),
|
|
41
|
+
]);
|
|
42
|
+
// Check WebHID support
|
|
43
|
+
if (!(await TransportWebHID.isSupported())) {
|
|
44
|
+
// Try WebUSB as fallback
|
|
45
|
+
try {
|
|
46
|
+
const { default: TransportWebUSB } = await import('@ledgerhq/hw-transport-webusb');
|
|
47
|
+
if (await TransportWebUSB.isSupported()) {
|
|
48
|
+
this.transport = await TransportWebUSB.create();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
throw new Error('No Ledger transport available. Use Chrome or a Chromium-based browser.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
throw new Error('No Ledger transport available. Use Chrome or a Chromium-based browser.');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.transport = await TransportWebHID.create();
|
|
60
|
+
}
|
|
61
|
+
const coinType = this.coinTypePaths[chain.chainId] ?? DEFAULT_COIN_TYPE;
|
|
62
|
+
const hdPath = stringToPath(`m/44'/${coinType}'/0'/0/0`);
|
|
63
|
+
this.signer = new LedgerSigner(this.transport, {
|
|
64
|
+
hdPaths: [hdPath],
|
|
65
|
+
prefix: chain.bech32Prefix,
|
|
66
|
+
});
|
|
67
|
+
const accounts = await this.signer.getAccounts();
|
|
68
|
+
if (!accounts || accounts.length === 0) {
|
|
69
|
+
throw new Error('No accounts found on Ledger. Make sure the Cosmos app is open.');
|
|
70
|
+
}
|
|
71
|
+
const acc = accounts[0];
|
|
72
|
+
return {
|
|
73
|
+
address: acc.address,
|
|
74
|
+
pubKey: acc.pubkey,
|
|
75
|
+
algo: acc.algo || 'secp256k1',
|
|
76
|
+
name: 'Ledger',
|
|
77
|
+
isNanoLedger: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async disconnect() {
|
|
81
|
+
if (this.transport) {
|
|
82
|
+
try {
|
|
83
|
+
await this.transport.close();
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Ignore close errors
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
this.transport = null;
|
|
90
|
+
this.signer = null;
|
|
91
|
+
}
|
|
92
|
+
async signTx(bytes) {
|
|
93
|
+
if (!this.signer) {
|
|
94
|
+
throw new Error('Ledger not connected');
|
|
95
|
+
}
|
|
96
|
+
// Ledger uses Amino signing — the bytes should be an Amino-encoded SignDoc.
|
|
97
|
+
// For full tx signing, use getOfflineSigner() with SigningStargateClient.
|
|
98
|
+
throw new Error('Ledger signTx requires Amino signing. Use getOfflineSigner() with SigningStargateClient for full tx support.');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the CosmJS-compatible offline signer for use with SigningStargateClient.
|
|
102
|
+
* This is the recommended way to sign transactions with Ledger.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* const signer = ledgerWallet.getOfflineSigner();
|
|
107
|
+
* const client = await SigningStargateClient.connectWithSigner(rpcUrl, signer);
|
|
108
|
+
* await client.sendTokens(sender, recipient, amount, fee);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
getOfflineSigner() {
|
|
112
|
+
if (!this.signer) {
|
|
113
|
+
throw new Error('Ledger not connected. Call connect() first.');
|
|
114
|
+
}
|
|
115
|
+
return this.signer;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -29,6 +29,7 @@ export declare class StationWallet implements WalletAdapter {
|
|
|
29
29
|
installed(): boolean;
|
|
30
30
|
getUri(): string;
|
|
31
31
|
onUpdate(callback: () => void): void;
|
|
32
|
+
connectViaWalletConnect(chain: Chain): Promise<Account>;
|
|
32
33
|
connect(chain: Chain): Promise<Account>;
|
|
33
34
|
disconnect(): Promise<void>;
|
|
34
35
|
signTx(_bytes: Uint8Array): Promise<Uint8Array>;
|
|
@@ -47,6 +47,11 @@ export class StationWallet {
|
|
|
47
47
|
onUpdate(callback) {
|
|
48
48
|
this.wc?.onUpdate(callback);
|
|
49
49
|
}
|
|
50
|
+
async connectViaWalletConnect(chain) {
|
|
51
|
+
if (!this.wc)
|
|
52
|
+
throw new Error('WalletConnect not initialized for Station');
|
|
53
|
+
return this.wc.connect(chain);
|
|
54
|
+
}
|
|
50
55
|
async connect(chain) {
|
|
51
56
|
const station = window.station;
|
|
52
57
|
if (!station) {
|
|
@@ -17,7 +17,7 @@ export class WalletConnectWallet {
|
|
|
17
17
|
this.icon = icon;
|
|
18
18
|
const details = mobileAppDetails || {
|
|
19
19
|
name: 'Cosmos Connect',
|
|
20
|
-
android: 'intent://wcV2#Intent;package=com.chainapsis.keplr;scheme=keplrwallet;end;',
|
|
20
|
+
android: 'intent://wcV2#Intent;package=com.chainapsis.keplr;scheme=keplrwallet;end;',
|
|
21
21
|
ios: 'keplrwallet://wcV2', // Default to Keplr for ios
|
|
22
22
|
};
|
|
23
23
|
const metadata = signerMetadata || {
|
|
@@ -127,7 +127,7 @@ export class WalletConnectV2 {
|
|
|
127
127
|
console.log(`WalletConnectV2: URI generated (attempt ${attempt + 1}/${maxRetries})`, uri);
|
|
128
128
|
this._uri = uri;
|
|
129
129
|
this.onUriCbs.forEach((cb) => cb(uri));
|
|
130
|
-
console.log(
|
|
130
|
+
console.log(`WalletConnectV2: Waiting for approval (timeout: ${pairingTimeout}ms)...`);
|
|
131
131
|
try {
|
|
132
132
|
const approvalPromise = approval();
|
|
133
133
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Connection approval timed out')), pairingTimeout));
|
|
@@ -29,7 +29,7 @@ export function createClient(config) {
|
|
|
29
29
|
function getWallet(walletId) {
|
|
30
30
|
return wallets.find((w) => w.id === walletId);
|
|
31
31
|
}
|
|
32
|
-
async function connect(walletId, chainId) {
|
|
32
|
+
async function connect(walletId, chainId, options) {
|
|
33
33
|
try {
|
|
34
34
|
const chain = getChain(chainId);
|
|
35
35
|
if (!chain)
|
|
@@ -41,7 +41,9 @@ export function createClient(config) {
|
|
|
41
41
|
if (!wallet.installed() && !wallet.getUri) {
|
|
42
42
|
throw new Error(`Wallet ${wallet.name} is not installed`);
|
|
43
43
|
}
|
|
44
|
-
const account =
|
|
44
|
+
const account = options?.forceWalletConnect && wallet.connectViaWalletConnect
|
|
45
|
+
? await wallet.connectViaWalletConnect(chain)
|
|
46
|
+
: await wallet.connect(chain);
|
|
45
47
|
setState({
|
|
46
48
|
currentChain: chain,
|
|
47
49
|
currentWallet: wallet,
|
package/dist/core/types.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface WalletAdapter {
|
|
|
19
19
|
icon?: string;
|
|
20
20
|
installed(): boolean;
|
|
21
21
|
connect(chain: Chain): Promise<Account>;
|
|
22
|
+
connectViaWalletConnect?(chain: Chain): Promise<Account>;
|
|
22
23
|
disconnect(): Promise<void>;
|
|
23
24
|
signTx(bytes: Uint8Array): Promise<Uint8Array>;
|
|
24
25
|
signMsg?(msg: string): Promise<Uint8Array>;
|
|
@@ -47,7 +48,9 @@ export interface StorageAdapter {
|
|
|
47
48
|
export type Listener<T> = (state: T) => void;
|
|
48
49
|
export interface Client {
|
|
49
50
|
readonly state: ClientState;
|
|
50
|
-
connect(walletId: string, chainId: string
|
|
51
|
+
connect(walletId: string, chainId: string, options?: {
|
|
52
|
+
forceWalletConnect?: boolean;
|
|
53
|
+
}): Promise<void>;
|
|
51
54
|
disconnect(): Promise<void>;
|
|
52
55
|
signAndBroadcast(txBytes: Uint8Array): Promise<string>;
|
|
53
56
|
subscribe(listener: Listener<ClientState>): () => void;
|