@rango-dev/provider-walletconnect-2 0.57.0 → 0.57.1-next.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/CHANGELOG.md +4 -0
- package/dist/adapter/adapter.d.ts +39 -0
- package/dist/adapter/adapter.d.ts.map +1 -0
- package/dist/adapter/index.d.ts +3 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/modal-cache.d.ts +14 -0
- package/dist/adapter/modal-cache.d.ts.map +1 -0
- package/dist/adapter/modal.d.ts +25 -0
- package/dist/adapter/modal.d.ts.map +1 -0
- package/dist/adapter/networks.d.ts +60 -0
- package/dist/adapter/networks.d.ts.map +1 -0
- package/dist/adapter/provider-client.d.ts +3 -0
- package/dist/adapter/provider-client.d.ts.map +1 -0
- package/dist/adapter/registry.d.ts +4 -0
- package/dist/adapter/registry.d.ts.map +1 -0
- package/dist/adapter/session-cache.d.ts +17 -0
- package/dist/adapter/session-cache.d.ts.map +1 -0
- package/dist/adapter/task-queue.d.ts +11 -0
- package/dist/adapter/task-queue.d.ts.map +1 -0
- package/dist/chunk-GEAT645O.js +2 -0
- package/dist/chunk-GEAT645O.js.map +7 -0
- package/dist/constants.d.ts +4 -48
- package/dist/constants.d.ts.map +1 -0
- package/dist/evm-3KFL5N77.js +2 -0
- package/dist/evm-3KFL5N77.js.map +7 -0
- package/dist/mod.d.ts +4 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +2 -0
- package/dist/mod.js.map +7 -0
- package/dist/namespaces/evm/hooks.d.ts +18 -0
- package/dist/namespaces/evm/hooks.d.ts.map +1 -0
- package/dist/namespaces/evm/namespace.d.ts +4 -0
- package/dist/namespaces/evm/namespace.d.ts.map +1 -0
- package/dist/namespaces/subscriber.d.ts +24 -0
- package/dist/namespaces/subscriber.d.ts.map +1 -0
- package/dist/provider.d.ts +3 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/session/accounts.d.ts +17 -0
- package/dist/session/accounts.d.ts.map +1 -0
- package/dist/session/bip122.d.ts +23 -0
- package/dist/session/bip122.d.ts.map +1 -0
- package/dist/session/chain-state.d.ts +6 -0
- package/dist/session/chain-state.d.ts.map +1 -0
- package/dist/session/evm-chain.d.ts +29 -0
- package/dist/session/evm-chain.d.ts.map +1 -0
- package/dist/session/evm.d.ts +25 -0
- package/dist/session/evm.d.ts.map +1 -0
- package/dist/session/lifecycle.d.ts +30 -0
- package/dist/session/lifecycle.d.ts.map +1 -0
- package/dist/session/lookup.d.ts +6 -0
- package/dist/session/lookup.d.ts.map +1 -0
- package/dist/session/proposals.d.ts +27 -0
- package/dist/session/proposals.d.ts.map +1 -0
- package/dist/session/restore-cache.d.ts +6 -0
- package/dist/session/restore-cache.d.ts.map +1 -0
- package/dist/session/teardown.d.ts +24 -0
- package/dist/session/teardown.d.ts.map +1 -0
- package/dist/signer.d.ts +2 -2
- package/dist/signer.d.ts.map +1 -0
- package/dist/signers/evm.d.ts +6 -4
- package/dist/signers/evm.d.ts.map +1 -0
- package/dist/types.d.ts +28 -11
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +17 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/wcConstants.d.ts +61 -0
- package/dist/wcConstants.d.ts.map +1 -0
- package/package.json +18 -13
- package/readme.md +14 -2
- package/src/adapter/adapter.ts +289 -0
- package/src/adapter/index.ts +2 -0
- package/src/adapter/modal-cache.ts +23 -0
- package/src/adapter/modal.ts +121 -0
- package/src/adapter/networks.ts +85 -0
- package/src/adapter/provider-client.ts +13 -0
- package/src/adapter/registry.ts +17 -0
- package/src/adapter/session-cache.ts +38 -0
- package/src/adapter/task-queue.ts +32 -0
- package/src/constants.ts +41 -76
- package/src/mod.ts +10 -0
- package/src/namespaces/evm/hooks.ts +148 -0
- package/src/namespaces/evm/namespace.ts +102 -0
- package/src/namespaces/subscriber.ts +106 -0
- package/src/provider.ts +35 -0
- package/src/session/accounts.ts +44 -0
- package/src/session/bip122.ts +225 -0
- package/src/session/chain-state.ts +38 -0
- package/src/session/evm-chain.ts +185 -0
- package/src/session/evm.ts +198 -0
- package/src/session/lifecycle.ts +241 -0
- package/src/session/lookup.ts +54 -0
- package/src/session/proposals.ts +96 -0
- package/src/session/restore-cache.ts +38 -0
- package/src/session/teardown.ts +181 -0
- package/src/signer.ts +9 -17
- package/src/signers/evm.ts +19 -17
- package/src/types.ts +31 -12
- package/src/utils.ts +68 -0
- package/src/wcConstants.ts +94 -0
- package/dist/chunk-6V3WUFOU.js +0 -2
- package/dist/chunk-6V3WUFOU.js.map +0 -7
- package/dist/chunk-BPSEZJUF.js +0 -2
- package/dist/chunk-BPSEZJUF.js.map +0 -7
- package/dist/chunk-DXVBX5XQ.js +0 -2
- package/dist/chunk-DXVBX5XQ.js.map +0 -7
- package/dist/dist-6GI3ECE5.js +0 -139
- package/dist/dist-6GI3ECE5.js.map +0 -7
- package/dist/evm-3ID4XY4Y.js +0 -2
- package/dist/evm-3ID4XY4Y.js.map +0 -7
- package/dist/helpers.d.ts +0 -31
- package/dist/index.d.ts +0 -21
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -7
- package/dist/session.d.ts +0 -63
- package/dist/signers/solana.d.ts +0 -14
- package/dist/solana-MFA7C5XI.js +0 -2
- package/dist/solana-MFA7C5XI.js.map +0 -7
- package/src/helpers.ts +0 -238
- package/src/index.ts +0 -234
- package/src/session.ts +0 -376
- package/src/signers/solana.ts +0 -160
- package/src/wc-types.d.ts +0 -31
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { WalletConnectNamespace } from '../types.js';
|
|
2
|
+
import type { ChainIdParams } from 'caip';
|
|
3
|
+
|
|
4
|
+
import { CAIP_BITCOIN_CHAIN_ID } from '@rango-dev/wallets-core/namespaces/utxo';
|
|
5
|
+
import { ChainId } from 'caip';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
DEFAULT_BITCOIN_EVENTS,
|
|
9
|
+
DEFAULT_BITCOIN_METHODS,
|
|
10
|
+
DEFAULT_ETHEREUM_EVENTS,
|
|
11
|
+
DEFAULT_ETHEREUM_METHODS,
|
|
12
|
+
NAMESPACES,
|
|
13
|
+
WC_NAMESPACE_TO_CAIP,
|
|
14
|
+
} from '../wcConstants.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* `chains` is required here so the same shape is assignable both to the
|
|
18
|
+
* SignClient `ProposalTypes` (chains optional) and to the UniversalProvider
|
|
19
|
+
* `NamespaceConfig` (chains required).
|
|
20
|
+
*/
|
|
21
|
+
export type FinalNamespaces = Record<
|
|
22
|
+
string,
|
|
23
|
+
{ chains: string[]; methods: string[]; events: string[] }
|
|
24
|
+
>;
|
|
25
|
+
|
|
26
|
+
type NamespaceProposal = {
|
|
27
|
+
methods: string[];
|
|
28
|
+
events: string[];
|
|
29
|
+
resolveChains: (
|
|
30
|
+
chains: ChainIdParams[],
|
|
31
|
+
targetChainReference?: string
|
|
32
|
+
) => ChainIdParams[];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Per-namespace proposal facts as data, keyed by `WalletConnectNamespace` so a
|
|
37
|
+
* newly-added alias is a compile error until it's configured here. The CAIP
|
|
38
|
+
* prefix comes from the shared `WC_NAMESPACE_TO_CAIP` map.
|
|
39
|
+
*/
|
|
40
|
+
const NAMESPACE_PROPOSALS: Record<WalletConnectNamespace, NamespaceProposal> = {
|
|
41
|
+
evm: {
|
|
42
|
+
methods: DEFAULT_ETHEREUM_METHODS,
|
|
43
|
+
events: DEFAULT_ETHEREUM_EVENTS,
|
|
44
|
+
resolveChains: (chains, targetChainReference) => {
|
|
45
|
+
if (targetChainReference) {
|
|
46
|
+
return [
|
|
47
|
+
{ namespace: NAMESPACES.ETHEREUM, reference: targetChainReference },
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
return chains.length > 0
|
|
51
|
+
? chains
|
|
52
|
+
: [{ namespace: NAMESPACES.ETHEREUM, reference: '1' }];
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
utxo: {
|
|
56
|
+
methods: DEFAULT_BITCOIN_METHODS,
|
|
57
|
+
events: DEFAULT_BITCOIN_EVENTS,
|
|
58
|
+
resolveChains: () => [
|
|
59
|
+
{ namespace: NAMESPACES.BITCOIN, reference: CAIP_BITCOIN_CHAIN_ID },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Builds a WalletConnect namespace proposal (chains, methods, events).
|
|
66
|
+
*
|
|
67
|
+
* The result always goes to `optionalNamespaces`: sign-client merges
|
|
68
|
+
* `requiredNamespaces` into `optionalNamespaces` and clears it before sending
|
|
69
|
+
* the proposal, so passing anything as required only earns a deprecation
|
|
70
|
+
* warning. Narrowing the proposal (see `targetChainReference`) is what actually
|
|
71
|
+
* constrains what the wallet can approve.
|
|
72
|
+
*
|
|
73
|
+
* @param targetChainReference - When set for EVM, limits the proposal to this
|
|
74
|
+
* single chain id (decimal string, e.g. `"137"`). Omit to include all EVM
|
|
75
|
+
* chains from `chains`.
|
|
76
|
+
*/
|
|
77
|
+
export function generateOptionalNamespace(
|
|
78
|
+
chains: ChainIdParams[],
|
|
79
|
+
namespaces: WalletConnectNamespace[],
|
|
80
|
+
targetChainReference?: string
|
|
81
|
+
): FinalNamespaces | undefined {
|
|
82
|
+
const proposal: FinalNamespaces = {};
|
|
83
|
+
|
|
84
|
+
for (const namespace of namespaces) {
|
|
85
|
+
const config = NAMESPACE_PROPOSALS[namespace];
|
|
86
|
+
proposal[WC_NAMESPACE_TO_CAIP[namespace]] = {
|
|
87
|
+
methods: config.methods,
|
|
88
|
+
events: config.events,
|
|
89
|
+
chains: config
|
|
90
|
+
.resolveChains(chains, targetChainReference)
|
|
91
|
+
.map((chain) => new ChainId(chain).toString()),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return Object.keys(proposal).length > 0 ? proposal : undefined;
|
|
96
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SessionCache } from '../adapter/session-cache.js';
|
|
2
|
+
import type { SignClientInstance, WalletConnectNamespace } from '../types.js';
|
|
3
|
+
import type { SessionTypes } from '@walletconnect/types';
|
|
4
|
+
|
|
5
|
+
import { debug } from '@rango-dev/logging-core';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
restoreWalletConnectSession,
|
|
9
|
+
type RestoreWalletConnectSessionOptions,
|
|
10
|
+
} from './lifecycle.js';
|
|
11
|
+
|
|
12
|
+
export async function restoreAndCacheSession(
|
|
13
|
+
client: SignClientInstance,
|
|
14
|
+
namespace: WalletConnectNamespace,
|
|
15
|
+
cache: SessionCache,
|
|
16
|
+
options?: RestoreWalletConnectSessionOptions,
|
|
17
|
+
onDisconnect?: (namespace: WalletConnectNamespace) => Promise<void>
|
|
18
|
+
): Promise<SessionTypes.Struct | null> {
|
|
19
|
+
try {
|
|
20
|
+
const session = await restoreWalletConnectSession(
|
|
21
|
+
client,
|
|
22
|
+
namespace,
|
|
23
|
+
options
|
|
24
|
+
);
|
|
25
|
+
if (!session) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
cache.set(namespace, session);
|
|
30
|
+
return session;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
debug(error instanceof Error ? error : new Error(String(error)));
|
|
33
|
+
if (cache.get(namespace)) {
|
|
34
|
+
await onDisconnect?.(namespace);
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { SignClientInstance, WalletConnectNamespace } from '../types.js';
|
|
2
|
+
import type { ISignClient, SessionTypes } from '@walletconnect/types';
|
|
3
|
+
import type UniversalProvider from '@walletconnect/universal-provider';
|
|
4
|
+
|
|
5
|
+
import { debug } from '@rango-dev/logging-core';
|
|
6
|
+
import { getSdkError } from '@walletconnect/utils';
|
|
7
|
+
|
|
8
|
+
import { NAMESPACES } from '../wcConstants.js';
|
|
9
|
+
|
|
10
|
+
import { persistCurrentChainId } from './chain-state.js';
|
|
11
|
+
import { getSessionNamespace } from './lookup.js';
|
|
12
|
+
|
|
13
|
+
function isNoMatchingKeyError(error: unknown): boolean {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
return message.includes('No matching key');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function hasActiveSession(client: ISignClient, topic: string): boolean {
|
|
19
|
+
try {
|
|
20
|
+
return !!client.session.get(topic);
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function hasActivePairing(
|
|
27
|
+
client: SignClientInstance,
|
|
28
|
+
topic: string
|
|
29
|
+
): boolean {
|
|
30
|
+
return client.pairing.getAll().some((pairing) => pairing.topic === topic);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function expireWalletConnectTopic(
|
|
34
|
+
client: SignClientInstance,
|
|
35
|
+
topic: string
|
|
36
|
+
) {
|
|
37
|
+
const sessions = client.session.getAll();
|
|
38
|
+
const pairings = client.pairing.getAll();
|
|
39
|
+
|
|
40
|
+
sessions.forEach((session: SessionTypes.Struct) => {
|
|
41
|
+
if (session.topic === topic || session.pairingTopic === topic) {
|
|
42
|
+
const requestForDeleteTopic =
|
|
43
|
+
session.pairingTopic === topic ? session.pairingTopic : session.topic;
|
|
44
|
+
client.core.expirer.set(requestForDeleteTopic, 0);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
pairings.forEach((pairing) => {
|
|
49
|
+
if (pairing.topic === topic) {
|
|
50
|
+
client.core.expirer.set(topic, 0);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function removeSessionRecord(
|
|
56
|
+
client: SignClientInstance,
|
|
57
|
+
session: SessionTypes.Struct
|
|
58
|
+
) {
|
|
59
|
+
const namespace = getSessionNamespace(session);
|
|
60
|
+
const pairingTopic = session.pairingTopic;
|
|
61
|
+
|
|
62
|
+
if (hasActiveSession(client, session.topic)) {
|
|
63
|
+
try {
|
|
64
|
+
await client.disconnect({
|
|
65
|
+
topic: session.topic,
|
|
66
|
+
reason: getSdkError('USER_DISCONNECTED'),
|
|
67
|
+
});
|
|
68
|
+
} catch (error) {
|
|
69
|
+
debug(error instanceof Error ? error : new Error(String(error)));
|
|
70
|
+
if (isNoMatchingKeyError(error)) {
|
|
71
|
+
await expireWalletConnectTopic(client, session.topic);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
await expireWalletConnectTopic(client, session.topic);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const remainingOnPairing = client.session
|
|
79
|
+
.getAll()
|
|
80
|
+
.filter((item) => item.pairingTopic === pairingTopic);
|
|
81
|
+
|
|
82
|
+
if (!remainingOnPairing.length && pairingTopic) {
|
|
83
|
+
if (hasActivePairing(client, pairingTopic)) {
|
|
84
|
+
try {
|
|
85
|
+
await client.disconnect({
|
|
86
|
+
topic: pairingTopic,
|
|
87
|
+
reason: getSdkError('USER_DISCONNECTED'),
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
debug(error instanceof Error ? error : new Error(String(error)));
|
|
91
|
+
if (isNoMatchingKeyError(error)) {
|
|
92
|
+
await expireWalletConnectTopic(client, pairingTopic);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
await expireWalletConnectTopic(client, pairingTopic);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (namespace === 'evm') {
|
|
101
|
+
void persistCurrentChainId(client, undefined);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function purgeOrphanedSessions(
|
|
106
|
+
client: SignClientInstance
|
|
107
|
+
): Promise<void> {
|
|
108
|
+
const pairingTopics = new Set(
|
|
109
|
+
client.pairing.getAll().map((pairing) => pairing.topic)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
for (const session of [...client.session.getAll()]) {
|
|
113
|
+
const pairingOrphaned =
|
|
114
|
+
!!session.pairingTopic && !pairingTopics.has(session.pairingTopic);
|
|
115
|
+
const sessionMissing = !hasActiveSession(client, session.topic);
|
|
116
|
+
|
|
117
|
+
if (pairingOrphaned || sessionMissing) {
|
|
118
|
+
await removeSessionRecord(client, session);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Drops pairings that no session is using.
|
|
125
|
+
*
|
|
126
|
+
* The inverse of {@link purgeOrphanedSessions}, and the only thing that collects
|
|
127
|
+
* them: a cancelled connect leaves behind the pairing `client.connect()` minted,
|
|
128
|
+
* and `cleanupPendingPairings` only unsubscribes pairings - it never deletes the
|
|
129
|
+
* record. Without this they accumulate in `client.pairing` and in storage for the
|
|
130
|
+
* lifetime of the origin.
|
|
131
|
+
*
|
|
132
|
+
* Only safe to call while no connect is in flight (the adapter's `#sessionQueue`
|
|
133
|
+
* guarantees that): a pairing awaiting its first approval has no session yet, so
|
|
134
|
+
* dropping it would kill that handshake.
|
|
135
|
+
*/
|
|
136
|
+
export async function purgeOrphanedPairings(
|
|
137
|
+
client: SignClientInstance
|
|
138
|
+
): Promise<void> {
|
|
139
|
+
const usedPairingTopics = new Set(
|
|
140
|
+
client.session
|
|
141
|
+
.getAll()
|
|
142
|
+
.map((session) => session.pairingTopic)
|
|
143
|
+
.filter((topic): topic is string => !!topic)
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
for (const pairing of [...client.pairing.getAll()]) {
|
|
147
|
+
if (usedPairingTopics.has(pairing.topic)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
await client.disconnect({
|
|
153
|
+
topic: pairing.topic,
|
|
154
|
+
reason: getSdkError('USER_DISCONNECTED'),
|
|
155
|
+
});
|
|
156
|
+
} catch (error) {
|
|
157
|
+
debug(error instanceof Error ? error : new Error(String(error)));
|
|
158
|
+
await expireWalletConnectTopic(client, pairing.topic);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function cleanupStaleSessionsForNamespace(
|
|
164
|
+
client: UniversalProvider['client'],
|
|
165
|
+
namespace: WalletConnectNamespace
|
|
166
|
+
): Promise<void> {
|
|
167
|
+
for (const existing of client.session.getAll()) {
|
|
168
|
+
if (getSessionNamespace(existing) !== namespace) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const btc = existing.namespaces[NAMESPACES.BITCOIN];
|
|
173
|
+
if (
|
|
174
|
+
btc &&
|
|
175
|
+
(btc.chains?.length ?? 0) > 0 &&
|
|
176
|
+
(btc.accounts?.length ?? 0) === 0
|
|
177
|
+
) {
|
|
178
|
+
await removeSessionRecord(client, existing);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
package/src/signer.ts
CHANGED
|
@@ -1,35 +1,27 @@
|
|
|
1
|
-
import type { WCInstance } from './types.js';
|
|
2
1
|
import type { SignerFactory } from 'rango-types';
|
|
3
2
|
|
|
4
3
|
import { dynamicImportWithRefinedError } from '@rango-dev/wallets-shared';
|
|
5
4
|
import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
): Promise<SignerFactory> {
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import { getAdapter } from './adapter/registry.js';
|
|
7
|
+
|
|
8
|
+
export default async function getSigners(): Promise<SignerFactory> {
|
|
9
|
+
const adapter = getAdapter();
|
|
10
|
+
if (!adapter) {
|
|
11
|
+
throw new Error('WalletConnect provider has not been initialized.');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
const client = await adapter.getClient();
|
|
15
|
+
|
|
14
16
|
const signers = new DefaultSignerFactory();
|
|
15
17
|
const EVMSigner = (
|
|
16
18
|
await dynamicImportWithRefinedError(
|
|
17
19
|
async () => await import('./signers/evm.js')
|
|
18
20
|
)
|
|
19
21
|
).default;
|
|
20
|
-
const SOLANASigner = (
|
|
21
|
-
await dynamicImportWithRefinedError(
|
|
22
|
-
async () => await import('./signers/solana.js')
|
|
23
|
-
)
|
|
24
|
-
).default;
|
|
25
|
-
|
|
26
22
|
signers.registerSigner(
|
|
27
23
|
TxType.EVM,
|
|
28
|
-
new EVMSigner(
|
|
29
|
-
);
|
|
30
|
-
signers.registerSigner(
|
|
31
|
-
TxType.SOLANA,
|
|
32
|
-
new SOLANASigner(instance.client, instance.session)
|
|
24
|
+
new EVMSigner(client, () => adapter.getSession('evm'))
|
|
33
25
|
);
|
|
34
26
|
|
|
35
27
|
return signers;
|
package/src/signers/evm.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { SessionTypes } from '@walletconnect/types';
|
|
1
|
+
import type { ISignClient, SessionTypes } from '@walletconnect/types';
|
|
3
2
|
import type { EvmTransaction } from 'rango-types/mainApi';
|
|
4
3
|
|
|
5
4
|
import { cleanEvmError, toHexQuantity } from '@rango-dev/signer-evm';
|
|
6
|
-
import * as encoding from '@walletconnect/encoding';
|
|
7
5
|
import { AccountId, ChainId } from 'caip';
|
|
8
6
|
import { type GenericSigner } from 'rango-types';
|
|
9
7
|
|
|
10
|
-
import {
|
|
8
|
+
import { utf8ToHex } from '../utils.js';
|
|
9
|
+
import { EthereumRPCMethods, NAMESPACES } from '../wcConstants.js';
|
|
11
10
|
|
|
12
11
|
const NAMESPACE_NAME = NAMESPACES.ETHEREUM;
|
|
13
12
|
|
|
13
|
+
type SessionGetter = () => SessionTypes.Struct | null;
|
|
14
|
+
|
|
14
15
|
type WalletConnectEvmTx = {
|
|
15
16
|
from?: string;
|
|
16
17
|
to?: string;
|
|
@@ -24,12 +25,20 @@ type WalletConnectEvmTx = {
|
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
class EVMSigner implements GenericSigner<EvmTransaction> {
|
|
27
|
-
private client:
|
|
28
|
-
private
|
|
28
|
+
private client: ISignClient;
|
|
29
|
+
private getSession: SessionGetter;
|
|
29
30
|
|
|
30
|
-
constructor(client:
|
|
31
|
+
constructor(client: ISignClient, getSession: SessionGetter) {
|
|
31
32
|
this.client = client;
|
|
32
|
-
this.
|
|
33
|
+
this.getSession = getSession;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private get session(): SessionTypes.Struct {
|
|
37
|
+
const session = this.getSession();
|
|
38
|
+
if (!session) {
|
|
39
|
+
throw new Error('EVM WalletConnect session is not available.');
|
|
40
|
+
}
|
|
41
|
+
return session;
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
/**
|
|
@@ -89,7 +98,7 @@ class EVMSigner implements GenericSigner<EvmTransaction> {
|
|
|
89
98
|
namespace: NAMESPACE_NAME,
|
|
90
99
|
reference: requestedFor.chainId,
|
|
91
100
|
});
|
|
92
|
-
const hexMsg =
|
|
101
|
+
const hexMsg = utf8ToHex(msg, true);
|
|
93
102
|
|
|
94
103
|
const params = [hexMsg, address];
|
|
95
104
|
|
|
@@ -141,6 +150,7 @@ class EVMSigner implements GenericSigner<EvmTransaction> {
|
|
|
141
150
|
`Received an invalid hash on signing the transaction. (hash=${hash})`
|
|
142
151
|
);
|
|
143
152
|
}
|
|
153
|
+
|
|
144
154
|
return {
|
|
145
155
|
hash,
|
|
146
156
|
};
|
|
@@ -165,7 +175,6 @@ class EVMSigner implements GenericSigner<EvmTransaction> {
|
|
|
165
175
|
const { address, chainId } = requestedFor;
|
|
166
176
|
|
|
167
177
|
if (!chainId) {
|
|
168
|
-
console.log('isNetworkAndAccountExistInSession', requestedFor);
|
|
169
178
|
throw new Error(
|
|
170
179
|
'You need to set your chain for signing message/transaction.'
|
|
171
180
|
);
|
|
@@ -191,13 +200,6 @@ class EVMSigner implements GenericSigner<EvmTransaction> {
|
|
|
191
200
|
);
|
|
192
201
|
|
|
193
202
|
if (!addresses || !addresses.includes(caipAddress.toString())) {
|
|
194
|
-
console.warn(
|
|
195
|
-
'Available adresses and requested address:',
|
|
196
|
-
addresses,
|
|
197
|
-
caipAddress.toString(),
|
|
198
|
-
chainId,
|
|
199
|
-
address
|
|
200
|
-
);
|
|
201
203
|
throw new Error(
|
|
202
204
|
`Your requested address doesn't exist on your wallect connect session. Please reconnect your wallet.`
|
|
203
205
|
);
|
package/src/types.ts
CHANGED
|
@@ -1,26 +1,45 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { ProposalTypes } from '@walletconnect/types';
|
|
2
|
+
import type { ChainIdParams } from 'caip';
|
|
3
3
|
import type { BlockchainMeta } from 'rango-types';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { SignClient } from '@walletconnect/sign-client';
|
|
6
|
+
|
|
7
|
+
export { SignClient };
|
|
8
|
+
|
|
9
|
+
export type SignClientInstance = InstanceType<typeof SignClient>;
|
|
10
|
+
|
|
11
|
+
export interface Environments {
|
|
6
12
|
WC_PROJECT_ID: string;
|
|
7
13
|
// This is useful for directly opening a listed WC wallet. you will need to pass a url.
|
|
8
14
|
DISABLE_MODAL_AND_OPEN_LINK?: string;
|
|
15
|
+
meta?: BlockchainMeta[];
|
|
16
|
+
themeMode?: 'light' | 'dark';
|
|
17
|
+
modalZIndex?: number;
|
|
9
18
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
session: SessionTypes.Struct | null;
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
-
request: (params: any) => Promise<string>;
|
|
15
|
-
}
|
|
19
|
+
|
|
20
|
+
export type WalletConnectNamespace = 'evm' | 'utxo';
|
|
16
21
|
|
|
17
22
|
export interface CreateSessionParams {
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The whole proposal goes here - sign-client folds `requiredNamespaces` into
|
|
25
|
+
* this and clears it, so proposing anything as required is deprecated.
|
|
26
|
+
*/
|
|
27
|
+
optionalNamespaces: ProposalTypes.OptionalNamespaces;
|
|
20
28
|
pairingTopic?: string;
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
export interface ConnectParams {
|
|
24
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Chains to propose, as CAIP-2 ids. Callers convert rango `BlockchainMeta`
|
|
34
|
+
* at the boundary (see `evmMetaToCaipChainIds`) so the connect path stays
|
|
35
|
+
* decoupled from rango-types' chain shape.
|
|
36
|
+
*/
|
|
37
|
+
chains: ChainIdParams[];
|
|
25
38
|
envs: Environments;
|
|
39
|
+
namespace: WalletConnectNamespace;
|
|
40
|
+
/**
|
|
41
|
+
* Decimal EVM chain reference (e.g. `"137"`).
|
|
42
|
+
* When set, it is the only EVM chain proposed during session creation.
|
|
43
|
+
*/
|
|
44
|
+
chainReference?: string;
|
|
26
45
|
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Chain } from '@hub3js/evm';
|
|
2
|
+
import type { ChainIdParams } from 'caip';
|
|
3
|
+
import type { BlockchainMeta } from 'rango-types';
|
|
4
|
+
|
|
5
|
+
import { isEvmBlockchain } from 'rango-types';
|
|
6
|
+
|
|
7
|
+
import { NAMESPACES } from './wcConstants.js';
|
|
8
|
+
|
|
9
|
+
const HEX_RADIX = 16;
|
|
10
|
+
|
|
11
|
+
export function utf8ToHex(value: string, prefixed = false): string {
|
|
12
|
+
const hex = Array.from(new TextEncoder().encode(value))
|
|
13
|
+
.map((byte) => byte.toString(HEX_RADIX).padStart(2, '0'))
|
|
14
|
+
.join('');
|
|
15
|
+
|
|
16
|
+
return prefixed ? `0x${hex}` : hex;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Normalizes hub chain input (hex, decimal, or AddEthereumChainParameter) to a decimal reference. */
|
|
20
|
+
export function parseChainReference(
|
|
21
|
+
chain?: string | Chain
|
|
22
|
+
): string | undefined {
|
|
23
|
+
if (!chain) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (typeof chain === 'string') {
|
|
28
|
+
return chain.startsWith('0x')
|
|
29
|
+
? String(parseInt(chain))
|
|
30
|
+
: String(parseInt(chain, 10) || chain);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return String(parseInt(chain.chainId));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Maps a chain reference to a Rango network name using blockchain meta. */
|
|
37
|
+
export function resolveNetworkName(
|
|
38
|
+
chain: string | Chain | null | undefined,
|
|
39
|
+
meta: BlockchainMeta[]
|
|
40
|
+
): string | undefined {
|
|
41
|
+
const reference = parseChainReference(chain ?? undefined);
|
|
42
|
+
if (!reference) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return meta.find(
|
|
47
|
+
(blockchain) =>
|
|
48
|
+
isEvmBlockchain(blockchain) &&
|
|
49
|
+
String(parseInt(blockchain.chainId)) === reference
|
|
50
|
+
)?.name;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Converts a decimal EVM chain reference to the `0x`-prefixed hex expected by hub EVM actions. */
|
|
54
|
+
export function chainReferenceToHex(reference: string): `0x${string}` {
|
|
55
|
+
return `0x${parseInt(reference).toString(HEX_RADIX)}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Converts rango EVM blockchain meta to CAIP-2 chain ids - the only chain data the
|
|
60
|
+
* connect/proposal path needs. This is the single boundary where rango-types' chain
|
|
61
|
+
* shape is translated; everything downstream uses caip's ChainIdParams.
|
|
62
|
+
*/
|
|
63
|
+
export function evmMetaToCaipChainIds(meta: BlockchainMeta[]): ChainIdParams[] {
|
|
64
|
+
return meta.filter(isEvmBlockchain).map((blockchain) => ({
|
|
65
|
+
namespace: NAMESPACES.ETHEREUM,
|
|
66
|
+
reference: String(parseInt(blockchain.chainId)),
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WalletConnect protocol constants shared across the hub path (session/,
|
|
3
|
+
* adapter/, signers/, namespaces/). Kept separate from `constants.ts` (which
|
|
4
|
+
* holds the hub provider identity/metadata) so this module stays a dependency
|
|
5
|
+
* leaf and importing it never pulls in the signer/provider graph (the
|
|
6
|
+
* `WalletConnectNamespace` import below is type-only, so it is erased at runtime).
|
|
7
|
+
*/
|
|
8
|
+
import type { WalletConnectNamespace } from './types.js';
|
|
9
|
+
|
|
10
|
+
export const PING_TIMEOUT = 10_000;
|
|
11
|
+
|
|
12
|
+
export enum NAMESPACES {
|
|
13
|
+
ETHEREUM = 'eip155',
|
|
14
|
+
BITCOIN = 'bip122',
|
|
15
|
+
POLKADOT = 'polkadot',
|
|
16
|
+
CARDANO = 'cip34',
|
|
17
|
+
ERLOND = 'elrond',
|
|
18
|
+
MULTIVERSX = 'multiversx',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Single source of truth for the namespace-alias -> CAIP-2 prefix relationship
|
|
23
|
+
* (`evm -> eip155`, `utxo -> bip122`). `proposals` and `lookup` read from this
|
|
24
|
+
* instead of re-encoding it. `Record<WalletConnectNamespace, …>` makes a new
|
|
25
|
+
* alias a compile error until it's mapped.
|
|
26
|
+
*/
|
|
27
|
+
export const WC_NAMESPACE_TO_CAIP: Record<WalletConnectNamespace, string> = {
|
|
28
|
+
evm: NAMESPACES.ETHEREUM,
|
|
29
|
+
utxo: NAMESPACES.BITCOIN,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const CHAIN_ID_STORAGE = 'wc@2:client//namespaces';
|
|
33
|
+
|
|
34
|
+
// Refrence: https://docs.walletconnect.com/2.0/advanced/rpc-reference/ethereum-rpc
|
|
35
|
+
export enum EthereumRPCMethods {
|
|
36
|
+
PERSONAL_SIGN = 'personal_sign',
|
|
37
|
+
SIGN = 'eth_sign',
|
|
38
|
+
SIGN_TYPED_DATA = 'eth_signTypedData',
|
|
39
|
+
SIGN_TRANSACTION = 'eth_signTransaction',
|
|
40
|
+
SEND_TRANSACTION = 'eth_sendTransaction',
|
|
41
|
+
SEND_RAW_TRANSACTION = 'eth_sendRawTransaction',
|
|
42
|
+
SWITCH_CHAIN = 'wallet_switchEthereumChain',
|
|
43
|
+
ADD_CHAIN = 'wallet_addEthereumChain',
|
|
44
|
+
GET_CHAIN = 'eth_chainId',
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export enum EthereumEvents {
|
|
48
|
+
CHAIN_CHANGED = 'chainChanged',
|
|
49
|
+
ACCOUNTS_CHANGED = 'accountsChanged',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const DEFAULT_ETHEREUM_EVENTS: EthereumEvents[] = [
|
|
53
|
+
EthereumEvents.CHAIN_CHANGED,
|
|
54
|
+
EthereumEvents.ACCOUNTS_CHANGED,
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
export const DEFAULT_ETHEREUM_METHODS = [
|
|
58
|
+
EthereumRPCMethods.PERSONAL_SIGN,
|
|
59
|
+
EthereumRPCMethods.SEND_TRANSACTION,
|
|
60
|
+
EthereumRPCMethods.SIGN_TRANSACTION,
|
|
61
|
+
EthereumRPCMethods.SWITCH_CHAIN,
|
|
62
|
+
EthereumRPCMethods.ADD_CHAIN,
|
|
63
|
+
EthereumRPCMethods.GET_CHAIN,
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Reference: https://docs.reown.com/advanced/multichain/rpc-reference/bitcoin-rpc
|
|
67
|
+
export enum BitcoinRPCMethods {
|
|
68
|
+
SIGN_PSBT = 'signPsbt',
|
|
69
|
+
GET_ACCOUNT_ADDRESSES = 'getAccountAddresses',
|
|
70
|
+
SIGN_MESSAGE = 'signMessage',
|
|
71
|
+
SEND_TRANSFER = 'sendTransfer',
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export enum BitcoinEvents {
|
|
75
|
+
ADDRESSES_CHANGED = 'bip122_addressesChanged',
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const DEFAULT_BITCOIN_EVENTS: BitcoinEvents[] = [
|
|
79
|
+
BitcoinEvents.ADDRESSES_CHANGED,
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
export const DEFAULT_BITCOIN_METHODS = [
|
|
83
|
+
BitcoinRPCMethods.SIGN_PSBT,
|
|
84
|
+
BitcoinRPCMethods.GET_ACCOUNT_ADDRESSES,
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
export const DEFAULT_APP_METADATA = {
|
|
88
|
+
name: 'Rango Exchange',
|
|
89
|
+
description: 'The Ultimate Cross-Chain Solution',
|
|
90
|
+
url: 'https://app.rango.exchange/',
|
|
91
|
+
icons: ['https://app.rango.exchange/logo-rounded.png'],
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const RELAY_URL = 'wss://relay.walletconnect.com';
|
package/dist/chunk-6V3WUFOU.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{Networks as n}from"@rango-dev/wallets-shared";var T=n.ETHEREUM,A=1e4;var e="wc@2:client//namespaces";var t=["chainChanged","accountsChanged"],N=["personal_sign","eth_sendTransaction","eth_signTransaction","wallet_switchEthereumChain","wallet_addEthereumChain","eth_chainId"];var a="4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ",o={name:"Rango Exchange",description:"The Ultimate Cross-Chain Solution",url:"https://app.rango.exchange/",icons:["https://app.rango.exchange/logo-rounded.png"]},s="wss://relay.walletconnect.com";export{T as a,A as b,e as c,t as d,N as e,a as f,o as g,s as h};
|
|
2
|
-
//# sourceMappingURL=chunk-6V3WUFOU.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/constants.ts"],
|
|
4
|
-
"sourcesContent": ["import { Networks } from '@rango-dev/wallets-shared';\n\nexport const DEFAULT_NETWORK = Networks.ETHEREUM;\nexport const PING_TIMEOUT = 10_000;\n\nexport enum NAMESPACES {\n ETHEREUM = 'eip155',\n SOLANA = 'solana',\n POLKADOT = 'polkadot',\n CARDANO = 'cip34',\n ERLOND = 'elrond',\n MULTIVERSX = 'multiversx',\n}\n\nexport const CHAIN_ID_STORAGE = 'wc@2:client//namespaces';\n\n// Refrence: https://docs.walletconnect.com/2.0/advanced/rpc-reference/solana-rpc\nexport enum SolanaRPCMethods {\n GET_ACCOUNTS = 'solana_getAccounts',\n REQUEST_ACCOUNTS = 'solana_requestAccounts',\n SIGN_TRANSACTION = 'solana_signTransaction',\n SIGN_MESSAGE = 'solana_signMessage',\n}\n\n// Refrence: https://docs.walletconnect.com/2.0/advanced/rpc-reference/ethereum-rpc\nexport enum EthereumRPCMethods {\n PERSONAL_SIGN = 'personal_sign',\n SIGN = 'eth_sign',\n SIGN_TYPED_DATA = 'eth_signTypedData',\n SIGN_TRANSACTION = 'eth_signTransaction',\n SEND_TRANSACTION = 'eth_sendTransaction',\n SEND_RAW_TRANSACTION = 'eth_sendRawTransaction',\n SWITCH_CHAIN = 'wallet_switchEthereumChain',\n ADD_CHAIN = 'wallet_addEthereumChain',\n GET_CHAIN = 'eth_chainId',\n}\n\nexport enum StarknetRPCMethods {\n REQUEST_ADD_INVOKE_TRANSACTION = 'starknet_requestAddInvokeTransaction',\n SIGN_TYPED_DATA = 'starknet_signTypedData',\n}\n\nexport enum EthereumEvents {\n CHAIN_CHANGED = 'chainChanged',\n ACCOUNTS_CHANGED = 'accountsChanged',\n}\n\nexport const DEFAULT_ETHEREUM_EVENTS: EthereumEvents[] = [\n EthereumEvents.CHAIN_CHANGED,\n EthereumEvents.ACCOUNTS_CHANGED,\n];\n\nexport const DEFAULT_ETHEREUM_METHODS = [\n EthereumRPCMethods.PERSONAL_SIGN,\n EthereumRPCMethods.SEND_TRANSACTION,\n EthereumRPCMethods.SIGN_TRANSACTION,\n EthereumRPCMethods.SWITCH_CHAIN,\n EthereumRPCMethods.ADD_CHAIN,\n EthereumRPCMethods.GET_CHAIN,\n];\n\nexport const DEFAULT_SOLANA_METHODS = [\n SolanaRPCMethods.SIGN_TRANSACTION,\n SolanaRPCMethods.SIGN_MESSAGE,\n];\n\n// refrence: https://github.com/ChainAgnostic/namespaces/blob/main/solana/caip2.md\nexport const DEFAULT_SOLANA_CHAIN_ID = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ';\n\nexport const DEFAULT_APP_METADATA = {\n name: 'Rango Exchange',\n description: 'The Ultimate Cross-Chain Solution',\n url: 'https://app.rango.exchange/',\n icons: ['https://app.rango.exchange/logo-rounded.png'],\n};\n\nexport const RELAY_URL = 'wss://relay.walletconnect.com';\n"],
|
|
5
|
-
"mappings": "AAAA,OAAS,YAAAA,MAAgB,4BAElB,IAAMC,EAAkBD,EAAS,SAC3BE,EAAe,IAWrB,IAAMC,EAAmB,0BAiCzB,IAAMC,EAA4C,CACvD,eACA,iBACF,EAEaC,EAA2B,CACtC,gBACA,sBACA,sBACA,6BACA,0BACA,aACF,EAQO,IAAMC,EAA0B,mCAE1BC,EAAuB,CAClC,KAAM,iBACN,YAAa,oCACb,IAAK,8BACL,MAAO,CAAC,6CAA6C,CACvD,EAEaC,EAAY",
|
|
6
|
-
"names": ["Networks", "DEFAULT_NETWORK", "PING_TIMEOUT", "CHAIN_ID_STORAGE", "DEFAULT_ETHEREUM_EVENTS", "DEFAULT_ETHEREUM_METHODS", "DEFAULT_SOLANA_CHAIN_ID", "DEFAULT_APP_METADATA", "RELAY_URL"]
|
|
7
|
-
}
|