@rango-dev/wallets-react 0.0.0-experimental-936229e8-20251208

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/dist/helpers/index.d.ts +2 -0
  3. package/dist/helpers/index.d.ts.map +1 -0
  4. package/dist/helpers/index.js +2 -0
  5. package/dist/helpers/index.js.map +7 -0
  6. package/dist/hub/autoConnect.d.ts +11 -0
  7. package/dist/hub/autoConnect.d.ts.map +1 -0
  8. package/dist/hub/constants.d.ts +3 -0
  9. package/dist/hub/constants.d.ts.map +1 -0
  10. package/dist/hub/helpers.d.ts +33 -0
  11. package/dist/hub/helpers.d.ts.map +1 -0
  12. package/dist/hub/lastConnectedWallets.d.ts +22 -0
  13. package/dist/hub/lastConnectedWallets.d.ts.map +1 -0
  14. package/dist/hub/mod.d.ts +3 -0
  15. package/dist/hub/mod.d.ts.map +1 -0
  16. package/dist/hub/types.d.ts +4 -0
  17. package/dist/hub/types.d.ts.map +1 -0
  18. package/dist/hub/useHubAdapter.d.ts +11 -0
  19. package/dist/hub/useHubAdapter.d.ts.map +1 -0
  20. package/dist/hub/useHubRefs.d.ts +7 -0
  21. package/dist/hub/useHubRefs.d.ts.map +1 -0
  22. package/dist/hub/utils.d.ts +52 -0
  23. package/dist/hub/utils.d.ts.map +1 -0
  24. package/dist/index.d.ts +5 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +7 -0
  28. package/dist/legacy/autoConnect.d.ts +8 -0
  29. package/dist/legacy/autoConnect.d.ts.map +1 -0
  30. package/dist/legacy/context.d.ts +3 -0
  31. package/dist/legacy/context.d.ts.map +1 -0
  32. package/dist/legacy/helpers.d.ts +23 -0
  33. package/dist/legacy/helpers.d.ts.map +1 -0
  34. package/dist/legacy/hooks.d.ts +10 -0
  35. package/dist/legacy/hooks.d.ts.map +1 -0
  36. package/dist/legacy/mod.d.ts +5 -0
  37. package/dist/legacy/mod.d.ts.map +1 -0
  38. package/dist/legacy/types.d.ts +143 -0
  39. package/dist/legacy/types.d.ts.map +1 -0
  40. package/dist/legacy/useAutoConnect.d.ts +8 -0
  41. package/dist/legacy/useAutoConnect.d.ts.map +1 -0
  42. package/dist/legacy/useLegacyProviders.d.ts +7 -0
  43. package/dist/legacy/useLegacyProviders.d.ts.map +1 -0
  44. package/dist/legacy/utils.d.ts +3 -0
  45. package/dist/legacy/utils.d.ts.map +1 -0
  46. package/dist/provider.d.ts +5 -0
  47. package/dist/provider.d.ts.map +1 -0
  48. package/dist/test-utils/env.d.ts +7 -0
  49. package/dist/test-utils/env.d.ts.map +1 -0
  50. package/dist/test-utils/fixtures.d.ts +14 -0
  51. package/dist/test-utils/fixtures.d.ts.map +1 -0
  52. package/dist/useProviders.d.ts +4 -0
  53. package/dist/useProviders.d.ts.map +1 -0
  54. package/dist/wallets-react.build.json +1 -0
  55. package/helpers/package.json +8 -0
  56. package/package.json +50 -0
  57. package/readme.md +3 -0
  58. package/src/helpers/index.ts +1 -0
  59. package/src/hub/autoConnect.ts +276 -0
  60. package/src/hub/constants.ts +2 -0
  61. package/src/hub/helpers.ts +179 -0
  62. package/src/hub/lastConnectedWallets.ts +166 -0
  63. package/src/hub/mod.ts +6 -0
  64. package/src/hub/types.ts +12 -0
  65. package/src/hub/useHubAdapter.ts +516 -0
  66. package/src/hub/useHubRefs.ts +50 -0
  67. package/src/hub/utils.ts +393 -0
  68. package/src/index.ts +4 -0
  69. package/src/legacy/autoConnect.ts +66 -0
  70. package/src/legacy/context.ts +39 -0
  71. package/src/legacy/helpers.ts +183 -0
  72. package/src/legacy/hooks.ts +54 -0
  73. package/src/legacy/mod.ts +13 -0
  74. package/src/legacy/types.ts +195 -0
  75. package/src/legacy/useAutoConnect.ts +23 -0
  76. package/src/legacy/useLegacyProviders.ts +241 -0
  77. package/src/legacy/utils.ts +7 -0
  78. package/src/provider.tsx +18 -0
  79. package/src/test-utils/env.ts +10 -0
  80. package/src/test-utils/fixtures.ts +238 -0
  81. package/src/useProviders.ts +120 -0
@@ -0,0 +1,179 @@
1
+ import type { AllProxiedNamespaces } from './types.js';
2
+ import type {
3
+ Accounts,
4
+ AccountsWithActiveChain,
5
+ } from '@rango-dev/wallets-core/namespaces/common';
6
+ import type { BlockchainMeta } from 'rango-types';
7
+ import type { Result } from 'ts-results';
8
+
9
+ import { legacyFormatAddressWithNetwork as formatAddressWithNetwork } from '@rango-dev/wallets-core/legacy';
10
+ import { CAIP_NAMESPACE as CAIP_COSMOS_NAMESPACE } from '@rango-dev/wallets-core/namespaces/cosmos';
11
+ import { CAIP_TRON_CHAIN_ID } from '@rango-dev/wallets-core/namespaces/tron';
12
+ import { CAIP_BITCOIN_CHAIN_ID } from '@rango-dev/wallets-core/namespaces/utxo';
13
+ import { CAIP } from '@rango-dev/wallets-core/utils';
14
+ import { getBlockChainNameFromId } from '@rango-dev/wallets-shared';
15
+ import { Err, Ok } from 'ts-results';
16
+
17
+ export function mapCaipNamespaceToLegacyNetworkName(
18
+ chainId: CAIP.ChainIdParams | string,
19
+ allBlockChains: BlockchainMeta[]
20
+ ): string {
21
+ if (typeof chainId === 'string') {
22
+ return chainId;
23
+ }
24
+ const useNamespaceAsNetworkFor = ['solana'];
25
+
26
+ if (useNamespaceAsNetworkFor.includes(chainId.namespace.toLowerCase())) {
27
+ return chainId.namespace.toUpperCase();
28
+ }
29
+
30
+ if (chainId.namespace.toLowerCase() === 'eip155') {
31
+ return 'ETH';
32
+ } else if (chainId.reference === CAIP_BITCOIN_CHAIN_ID) {
33
+ return 'BTC';
34
+ }
35
+
36
+ if (chainId.namespace.toLowerCase() === CAIP_COSMOS_NAMESPACE) {
37
+ const network = getBlockChainNameFromId(chainId.reference, allBlockChains);
38
+ if (!network) {
39
+ throw new Error(
40
+ `Network didn't found for given chainId: ${chainId.reference}`
41
+ );
42
+ }
43
+ return network;
44
+ }
45
+ if (chainId.namespace === 'sui' || chainId.reference === CAIP_TRON_CHAIN_ID) {
46
+ return chainId.reference.toUpperCase();
47
+ }
48
+
49
+ return chainId.reference;
50
+ }
51
+
52
+ /**
53
+ * CAIP's accountId has a format like this: eip155:1:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb
54
+ * Legacy format is something like this: ETH:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb
55
+ * This function will try to convert this two format.
56
+ *
57
+ * @see https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md
58
+ */
59
+ export function fromAccountIdToLegacyAddressFormat(
60
+ account: string,
61
+ allBlockChains: BlockchainMeta[]
62
+ ): string {
63
+ const { chainId, address } = CAIP.AccountId.parse(account);
64
+ const network = mapCaipNamespaceToLegacyNetworkName(chainId, allBlockChains);
65
+ return formatAddressWithNetwork(address, network);
66
+ }
67
+
68
+ /**
69
+ * Getting a list of (lazy) promises and run them one after another.
70
+ */
71
+
72
+ export async function runSequentiallyWithoutFailure<R>(
73
+ promises: Array<() => Promise<R>>
74
+ ): Promise<Result<R, unknown>[]> {
75
+ return promises.reduce(async (prevPromise, task) => {
76
+ const previousResults = await prevPromise;
77
+ try {
78
+ const taskResult = await task();
79
+ return [...previousResults, new Ok(taskResult)];
80
+ } catch (error) {
81
+ return [...previousResults, new Err(error)];
82
+ }
83
+ }, Promise.resolve<Result<R, unknown>[]>([]));
84
+ }
85
+
86
+ export function isConnectResultEvm(
87
+ result: Awaited<ReturnType<AllProxiedNamespaces['connect']>>
88
+ ): result is AccountsWithActiveChain {
89
+ return typeof result === 'object' && !Array.isArray(result);
90
+ }
91
+
92
+ export function isConnectResultSolana(
93
+ result: Awaited<ReturnType<AllProxiedNamespaces['connect']>>
94
+ ): result is Accounts {
95
+ return Array.isArray(result);
96
+ }
97
+
98
+ type QueueItem<T> = {
99
+ task: () => Promise<T>;
100
+ resolve: (value: Result<T, unknown>) => void;
101
+ key: string;
102
+ };
103
+ /**
104
+ * Creates a queue manager that ensures sequential execution of tasks by key.
105
+ * When multiple tasks with the same key are queued, they are executed one at a time
106
+ * in the order they were added. This prevents race conditions and ensures
107
+ * predictable task execution order.
108
+ *
109
+ */
110
+ export function createQueue(options?: {
111
+ onError?: (
112
+ error: unknown,
113
+ actions: {
114
+ removeCurrentKeyFromQueue: () => void;
115
+ }
116
+ ) => void;
117
+ }) {
118
+ const processingKeys = new Set<string>();
119
+ let queue: QueueItem<unknown>[] = [];
120
+
121
+ const removeKeyFromQueue = (
122
+ key: string,
123
+ result: Result<unknown, unknown>
124
+ ) => {
125
+ queue = queue.filter((q) => {
126
+ if (q.key !== key) {
127
+ return true;
128
+ }
129
+ q.resolve(result);
130
+ return false;
131
+ });
132
+ };
133
+
134
+ const processQueue = async () => {
135
+ const currentItem = queue.find((item) => !processingKeys.has(item.key));
136
+ if (!currentItem) {
137
+ return;
138
+ }
139
+
140
+ const { task, resolve, key } = currentItem;
141
+ processingKeys.add(key);
142
+
143
+ try {
144
+ const result = await task();
145
+ resolve(new Ok(result));
146
+ } catch (error) {
147
+ if (options?.onError) {
148
+ options.onError(error, {
149
+ removeCurrentKeyFromQueue: () =>
150
+ removeKeyFromQueue(key, new Err(error)),
151
+ });
152
+ }
153
+
154
+ resolve(new Err(error));
155
+ } finally {
156
+ const indexOfCurrentItem = queue.findIndex((item) => item.key === key);
157
+ if (indexOfCurrentItem >= 0) {
158
+ queue.splice(indexOfCurrentItem, 1);
159
+ }
160
+ processingKeys.delete(key);
161
+ void processQueue();
162
+ }
163
+ };
164
+
165
+ const queueTask = async <T>(
166
+ task: () => Promise<T>,
167
+ key: string
168
+ ): Promise<Result<T, unknown>> =>
169
+ new Promise((resolve) => {
170
+ queue.push({
171
+ task,
172
+ resolve: resolve as (value: Result<unknown, unknown>) => void,
173
+ key,
174
+ });
175
+ void processQueue();
176
+ });
177
+
178
+ return queueTask;
179
+ }
@@ -0,0 +1,166 @@
1
+ import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';
2
+
3
+ import { Persistor } from '@rango-dev/wallets-core/legacy';
4
+
5
+ import {
6
+ HUB_LAST_CONNECTED_WALLETS,
7
+ LEGACY_LAST_CONNECTED_WALLETS,
8
+ } from './constants.js';
9
+
10
+ export interface NamespaceInput {
11
+ namespace: Namespace;
12
+ network: string | undefined;
13
+ }
14
+
15
+ export interface LastConnectedWalletsStorage {
16
+ [providerId: string]: NamespaceInput[];
17
+ }
18
+
19
+ export type LegacyLastConnectedWalletsStorage = string[];
20
+
21
+ /**
22
+ * We are doing some certain actions on storage for `last-connected-wallets` key.
23
+ * This class helps us to define them in one place and also it has support for both legacy and hub.
24
+ */
25
+ export class LastConnectedWalletsFromStorage {
26
+ #storageKey: string;
27
+
28
+ constructor(storageKey: string) {
29
+ this.#storageKey = storageKey;
30
+ }
31
+
32
+ addWallet(providerId: string, namespaces: NamespaceInput[]): void {
33
+ if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {
34
+ return this.#addWalletToHub(providerId, namespaces);
35
+ } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {
36
+ return this.#addWalletToLegacy(providerId);
37
+ }
38
+ throw new Error('Not implemented');
39
+ }
40
+ removeWallets(providerIds?: string[]): void {
41
+ if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {
42
+ return this.#removeWalletsFromHub(providerIds);
43
+ } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {
44
+ return this.#removeWalletsFromLegacy(providerIds);
45
+ }
46
+ throw new Error('Not implemented');
47
+ }
48
+ list(): LastConnectedWalletsStorage {
49
+ if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {
50
+ return this.#listFromHub();
51
+ } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {
52
+ return this.#listFromLegacy();
53
+ }
54
+ throw new Error('Not implemented');
55
+ }
56
+ removeNamespacesFromWallet(providerId: string, namespaceIds: string[]) {
57
+ if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {
58
+ return this.#removeNamespaceFromWalletHub(providerId, namespaceIds);
59
+ }
60
+ throw new Error('Not implemented');
61
+ }
62
+
63
+ #listFromLegacy(): LastConnectedWalletsStorage {
64
+ const persistor = new Persistor<LegacyLastConnectedWalletsStorage>();
65
+ const lastConnectedWallets =
66
+ persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS) || [];
67
+ const output: LastConnectedWalletsStorage = {};
68
+ lastConnectedWallets.forEach((provider) => {
69
+ // Setting empty namespaces
70
+ output[provider] = [];
71
+ });
72
+ return output;
73
+ }
74
+ #listFromHub(): LastConnectedWalletsStorage {
75
+ const persistor = new Persistor<LastConnectedWalletsStorage>();
76
+ const lastConnectedWallets =
77
+ persistor.getItem(HUB_LAST_CONNECTED_WALLETS) || {};
78
+ return lastConnectedWallets;
79
+ }
80
+ #addWalletToHub(providerId: string, namespaces: NamespaceInput[]): void {
81
+ const storage = new Persistor<LastConnectedWalletsStorage>();
82
+ const storageState = storage.getItem(this.#storageKey) || {};
83
+
84
+ let toBeAddedNamespaces = namespaces;
85
+
86
+ // If provider already exits in the storage, we should just add new namespaces to the previously added namespaces.
87
+ if (!!storageState[providerId]) {
88
+ const storedNamespaces = storageState[providerId];
89
+ toBeAddedNamespaces = storedNamespaces.concat(
90
+ namespaces.filter(
91
+ (namespace) =>
92
+ !storedNamespaces.some(
93
+ (storedNamespace) =>
94
+ storedNamespace.namespace === namespace.namespace
95
+ )
96
+ )
97
+ );
98
+ }
99
+
100
+ storage.setItem(this.#storageKey, {
101
+ ...storageState,
102
+ [providerId]: toBeAddedNamespaces,
103
+ });
104
+ }
105
+ #addWalletToLegacy(providerId: string): void {
106
+ const storage = new Persistor<LegacyLastConnectedWalletsStorage>();
107
+ const storageState = storage.getItem(this.#storageKey) || [];
108
+
109
+ storage.setItem(
110
+ LEGACY_LAST_CONNECTED_WALLETS,
111
+ storageState.concat(providerId)
112
+ );
113
+ }
114
+ #removeWalletsFromHub(providerIds?: string[]): void {
115
+ const persistor = new Persistor<LastConnectedWalletsStorage>();
116
+ const storageState = persistor.getItem(this.#storageKey) || {};
117
+
118
+ // Remove all wallets
119
+ if (!providerIds) {
120
+ persistor.setItem(this.#storageKey, {});
121
+ return;
122
+ }
123
+
124
+ // Remove some of the wallets
125
+ providerIds.forEach((providerId) => {
126
+ if (storageState[providerId]) {
127
+ delete storageState[providerId];
128
+ }
129
+ });
130
+
131
+ persistor.setItem(this.#storageKey, storageState);
132
+ }
133
+ #removeNamespaceFromWalletHub(
134
+ providerId: string,
135
+ namespaceIds: string[]
136
+ ): void {
137
+ const persistor = new Persistor<LastConnectedWalletsStorage>();
138
+ const storageState = persistor.getItem(this.#storageKey) || {};
139
+
140
+ const currentProviderNamespaces = storageState[providerId];
141
+ const newProviderNamespaces = currentProviderNamespaces?.filter(
142
+ (namespace) => !namespaceIds.includes(namespace.namespace)
143
+ );
144
+
145
+ this.#removeWalletsFromHub([providerId]);
146
+ if (newProviderNamespaces?.length > 0) {
147
+ this.#addWalletToHub(providerId, newProviderNamespaces);
148
+ }
149
+ }
150
+ #removeWalletsFromLegacy(providerIds?: string[]): void {
151
+ const persistor = new Persistor<LegacyLastConnectedWalletsStorage>();
152
+ const storageState = persistor.getItem(this.#storageKey) || [];
153
+
154
+ // Remove all wallets
155
+ if (!providerIds) {
156
+ persistor.setItem(this.#storageKey, []);
157
+ return;
158
+ }
159
+
160
+ // Remove some of the wallets
161
+ persistor.setItem(
162
+ LEGACY_LAST_CONNECTED_WALLETS,
163
+ storageState.filter((wallet) => !providerIds.includes(wallet))
164
+ );
165
+ }
166
+ }
package/src/hub/mod.ts ADDED
@@ -0,0 +1,6 @@
1
+ export {
2
+ separateLegacyAndHubProviders,
3
+ getAllLegacyProviders,
4
+ findProviderByType,
5
+ } from './utils.js';
6
+ export { useHubAdapter } from './useHubAdapter.js';
@@ -0,0 +1,12 @@
1
+ import type {
2
+ CommonNamespaces,
3
+ FindProxiedNamespace,
4
+ ProviderMetadata,
5
+ } from '@rango-dev/wallets-core';
6
+
7
+ export type AllProxiedNamespaces = FindProxiedNamespace<
8
+ keyof CommonNamespaces,
9
+ CommonNamespaces
10
+ >;
11
+
12
+ export type ExtensionLink = keyof ProviderMetadata['extensions'];