@tuwaio/orbit-solana 0.3.0 → 0.3.1
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/README.md +43 -38
- package/dist/index.d.mts +48 -10
- package/dist/index.d.ts +48 -10
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
# @tuwaio/orbit-solana
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@tuwaio/orbit-solana)
|
|
4
|
-
[](
|
|
4
|
+
[](https://github.com/TuwaIO/orbit/blob/main/packages/orbit-solana/LICENSE)
|
|
5
5
|
|
|
6
|
-
`@tuwaio/orbit-solana`
|
|
6
|
+
`@tuwaio/orbit-solana` is the Solana Layer 2 (L2) package of **Orbit Utils**, the Stage 1 primitives layer of the TUWA ecosystem. It is built on **`@solana/kit`** and the **Wallet Standard** (`@wallet-standard/*`), and provides cached RPC clients, wallet discovery, cluster and explorer helpers, and SNS name and avatar lookups. It does not use the legacy `@solana/web3.js` or `gill`.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
## 🏛️ Core Capabilities
|
|
11
11
|
|
|
12
|
-
- **
|
|
13
|
-
- **Wallet Standard
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
|
|
12
|
+
- **RPC clients:** `createSolanaClientWithCache` returns a cached `{ rpc, rpcSubscriptions }` pair (the WebSocket URL is derived from the HTTP URL); `createSolanaRPC` returns a cached `rpc` only. Both accept a full URL or a cluster moniker (`mainnet`, `devnet`, `testnet`, `localnet`).
|
|
13
|
+
- **Wallet Standard discovery:** `getAvailableSolanaConnectors` lists installed wallets that support every feature Orbit relies on (`standard:connect`, `standard:disconnect`, `standard:events`, `solana:signAndSendTransaction`, `solana:signTransaction`, `solana:signMessage`) and only Solana chains. `getConnectedSolanaConnector` finds the wallet that holds the last connected address stored by `@tuwaio/orbit-core`.
|
|
14
|
+
- **Clusters and explorer links:** `getCluster`, `getRpcUrlForCluster`, `getSolanaClusters`, `getAvailableSolanaClusters`, `isValidSolanaCluster`, `isSolanaChainList`, and `getSolanaExplorerLink` for [Solana Explorer](https://explorer.solana.com) URLs.
|
|
15
|
+
- **Names and avatars:** `getSolanaAddressName` resolves an address to its favorite SNS (`.sol`) domain; `getSolanaAddressAvatar` returns the SNS profile image or a generated identicon. Both cache results in memory (`clear…Cache`, `get…CacheSize`, `preloadSolanaAvatar`).
|
|
16
|
+
|
|
17
|
+
Transactions are built and sent with `@solana/kit` itself, so any kit-compatible instruction builder works with the `rpc` returned here, including program clients generated by [Codama](https://github.com/codama-idl/codama).
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
@@ -24,65 +25,69 @@ pnpm add @tuwaio/orbit-solana @tuwaio/orbit-core @solana/kit @wallet-standard/ap
|
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
> [!IMPORTANT]
|
|
27
|
-
> `@tuwaio/orbit-core` (>=0.2), `@solana/kit` (>=8.2)
|
|
28
|
+
> `@tuwaio/orbit-core` (>=0.2), `@solana/kit` (>=8.2) and the `@wallet-standard` packages (1.x) are peer dependencies and must be installed alongside `@tuwaio/orbit-solana`.
|
|
28
29
|
|
|
29
30
|
---
|
|
30
31
|
|
|
31
|
-
## 🚀
|
|
32
|
-
|
|
33
|
-
### Cached RPC Connection
|
|
32
|
+
## 🚀 Usage
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
### Cached RPC client
|
|
36
35
|
|
|
37
36
|
```typescript
|
|
37
|
+
import { address } from '@solana/kit';
|
|
38
38
|
import { createSolanaClientWithCache } from '@tuwaio/orbit-solana';
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const { rpc } = createSolanaClientWithCache({
|
|
41
|
+
rpcUrlOrMoniker: 'devnet',
|
|
42
|
+
rpcUrls: { devnet: 'https://devnet.my-rpc-provider.example' }, // optional; falls back to the public endpoint
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const { value: lamports } = await rpc.getBalance(address('So11111111111111111111111111111111111111112')).send();
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
Clients are cached by the `rpcUrlOrMoniker` string. `localnet` has no default URL, so pass it in `rpcUrls`. The public `api.*.solana.com` endpoints are rate-limited; use your own RPC provider in production.
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
### Wallet discovery
|
|
47
51
|
|
|
48
52
|
```typescript
|
|
49
53
|
import { getAvailableSolanaConnectors } from '@tuwaio/orbit-solana';
|
|
50
54
|
|
|
51
|
-
const
|
|
52
|
-
console.log(
|
|
53
|
-
'Available Standard Adapters:',
|
|
54
|
-
connectors.map((c) => c.name),
|
|
55
|
-
);
|
|
55
|
+
const wallets = getAvailableSolanaConnectors(); // UiWallet[] from @wallet-standard/ui-registry
|
|
56
|
+
console.log(wallets.map((wallet) => wallet.name));
|
|
56
57
|
```
|
|
57
58
|
|
|
58
|
-
###
|
|
59
|
-
|
|
60
|
-
Use Codama (`@codama/renderers-js`) to generate type-safe instruction builders, then dispatch them using `@solana/kit` and `@tuwaio/orbit-solana`:
|
|
59
|
+
### Names, avatars and explorer links
|
|
61
60
|
|
|
62
61
|
```typescript
|
|
63
|
-
import {
|
|
64
|
-
import { pipe } from '@solana/kit';
|
|
65
|
-
// Instruction generated via Codama
|
|
66
|
-
// import { getIncrementInstruction } from './generated';
|
|
62
|
+
import { getSolanaAddressAvatar, getSolanaAddressName, getSolanaExplorerLink } from '@tuwaio/orbit-solana';
|
|
67
63
|
|
|
68
|
-
const
|
|
69
|
-
|
|
64
|
+
const owner = 'So11111111111111111111111111111111111111112';
|
|
65
|
+
|
|
66
|
+
const name = await getSolanaAddressName(owner); // "name.sol", or the address itself if no SNS domain is set
|
|
67
|
+
const avatarUrl = await getSolanaAddressAvatar(name);
|
|
68
|
+
|
|
69
|
+
getSolanaExplorerLink(`/address/${owner}`, 'solana:devnet'); // "https://explorer.solana.com/address/…?cluster=devnet"
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
74
|
-
##
|
|
74
|
+
## 🌐 External Services
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Some helpers call public third-party HTTP services. The address or domain being looked up is sent to these hosts:
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
78
|
+
| Helper | Host | Purpose |
|
|
79
|
+
| -------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
80
|
+
| RPC clients (default URLs) | `api.mainnet-beta.solana.com`, `api.devnet.solana.com`, `api.testnet.solana.com` | Public Solana RPC, used when no custom URL is configured |
|
|
81
|
+
| `getSolanaAddressName` | `sns-api.bonfida.com` | Favorite SNS domain of an address |
|
|
82
|
+
| `getSolanaAddressAvatar` | `image-api.bonfida.com` | SNS profile image of a `.sol` domain |
|
|
83
|
+
| `getSolanaAddressAvatar` | `api.dicebear.com` | Fallback identicon URL (loaded by the browser when rendered) |
|
|
83
84
|
|
|
84
85
|
---
|
|
85
86
|
|
|
87
|
+
## 📚 API Reference
|
|
88
|
+
|
|
89
|
+
Every export, with signatures and types generated from the source, is documented at **[orbit.docs.tuwa.io/packages/orbit-solana](https://orbit.docs.tuwa.io/packages/orbit-solana)**.
|
|
90
|
+
|
|
86
91
|
## 📄 License
|
|
87
92
|
|
|
88
|
-
Licensed under the **Apache-2.0 License**. See the [LICENSE](
|
|
93
|
+
Licensed under the **Apache-2.0 License**. See the [LICENSE](https://github.com/TuwaIO/orbit/blob/main/packages/orbit-solana/LICENSE) file for details.
|
package/dist/index.d.mts
CHANGED
|
@@ -25,28 +25,43 @@ interface SolanaClient {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Resolves the Solana clusters an app can use.
|
|
29
|
+
*
|
|
30
|
+
* @param solanaRPCUrls - Optional mapping of cluster monikers to RPC URLs. When provided, only these clusters are allowed.
|
|
31
|
+
* @param chains - Optional chain identifiers (e.g. `'solana:devnet'`, `'solana:mainnet-beta'`); when provided, only
|
|
32
|
+
* clusters present in this list (and allowed by `solanaRPCUrls`) are returned.
|
|
33
|
+
* @returns Cluster monikers, e.g. `['mainnet', 'devnet']`. Defaults to every cluster with a default RPC URL.
|
|
29
34
|
*/
|
|
30
35
|
declare function getSolanaClusters(solanaRPCUrls?: Partial<Record<SolanaClusterMoniker, string>>, chains?: ChainIdentifierArray): string[];
|
|
31
36
|
/**
|
|
32
|
-
* Type guard to check if a chain list contains Solana cluster names
|
|
37
|
+
* Type guard to check if a chain list contains Solana cluster names.
|
|
38
|
+
*
|
|
39
|
+
* @param chains - Mixed list of chain identifiers.
|
|
40
|
+
* @returns `true` if the list is non-empty and contains only strings.
|
|
33
41
|
*/
|
|
34
42
|
declare function isSolanaChainList(chains: (string | number)[]): chains is string[];
|
|
35
43
|
/**
|
|
36
|
-
* Gets
|
|
44
|
+
* Gets the Solana clusters that have a default public RPC URL.
|
|
45
|
+
*
|
|
46
|
+
* @returns `['mainnet', 'devnet', 'testnet']`.
|
|
37
47
|
*/
|
|
38
48
|
declare function getAvailableSolanaClusters(): SolanaClusterMoniker[];
|
|
39
49
|
/**
|
|
40
|
-
* Validates if a string is a
|
|
50
|
+
* Validates if a string is a Solana cluster moniker with a default RPC URL.
|
|
51
|
+
*
|
|
52
|
+
* @param cluster - Value to check.
|
|
53
|
+
* @returns `true` for `'mainnet'`, `'devnet'` and `'testnet'`.
|
|
41
54
|
*/
|
|
42
55
|
declare function isValidSolanaCluster(cluster: string): boolean;
|
|
43
56
|
|
|
44
57
|
/**
|
|
45
58
|
* Safely extracts the cluster moniker from a chain identifier.
|
|
46
59
|
* Handles both full chain IDs ('solana:mainnet-beta') and simple monikers ('mainnet-beta').
|
|
47
|
-
*
|
|
48
|
-
* @param
|
|
49
|
-
* @param cluster
|
|
60
|
+
*
|
|
61
|
+
* @param params - Cluster sources.
|
|
62
|
+
* @param params.cluster - Chain identifier or cluster moniker. Takes precedence when provided.
|
|
63
|
+
* @param params.walletCluster - Cluster of the connected wallet, used when `cluster` is omitted.
|
|
64
|
+
* @returns The extracted cluster moniker, falling back to `walletCluster` and then to `'mainnet'`.
|
|
50
65
|
*/
|
|
51
66
|
declare const getCluster: ({ cluster, walletCluster }: {
|
|
52
67
|
cluster?: string;
|
|
@@ -54,8 +69,12 @@ declare const getCluster: ({ cluster, walletCluster }: {
|
|
|
54
69
|
}) => string;
|
|
55
70
|
/**
|
|
56
71
|
* Retrieves the configured RPC URL for a given cluster moniker.
|
|
57
|
-
*
|
|
58
|
-
* @
|
|
72
|
+
*
|
|
73
|
+
* @param params - Cluster selection and the configured RPC URLs.
|
|
74
|
+
* @param params.cluster - The target cluster, used when `walletCluster` is not provided.
|
|
75
|
+
* @param params.walletCluster - The cluster of the connected wallet. Takes precedence over `cluster`.
|
|
76
|
+
* @param params.rpcUrls - Mapping of cluster monikers to RPC URLs.
|
|
77
|
+
* @returns The configured RPC URL, or the public mainnet-beta endpoint if the cluster has no URL configured.
|
|
59
78
|
*/
|
|
60
79
|
declare const getRpcUrlForCluster: ({ cluster, walletCluster, rpcUrls, }: {
|
|
61
80
|
cluster: SolanaClusterMoniker;
|
|
@@ -121,8 +140,26 @@ declare const clearSolanaRpcCache: () => void;
|
|
|
121
140
|
*/
|
|
122
141
|
declare const defaultRpcUrlsByMoniker: Partial<Record<SolanaClusterMoniker, string>>;
|
|
123
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Lists the Solana wallets registered through the Wallet Standard that Orbit can work with.
|
|
145
|
+
*
|
|
146
|
+
* A wallet is included only if it supports `standard:connect`, `standard:disconnect`, `standard:events`,
|
|
147
|
+
* `solana:signAndSendTransaction`, `solana:signTransaction` and `solana:signMessage`, and every chain it
|
|
148
|
+
* declares is a `solana:*` chain. Wallets registered more than once are deduplicated by name.
|
|
149
|
+
*
|
|
150
|
+
* @returns The matching wallets as `UiWallet` objects from `@wallet-standard/ui-registry`
|
|
151
|
+
* (empty on the server, where no wallets are registered).
|
|
152
|
+
*/
|
|
124
153
|
declare function getAvailableSolanaConnectors(): _wallet_standard_ui_core.UiWallet[];
|
|
125
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Finds the Wallet Standard wallet that holds the last connected address.
|
|
157
|
+
* The address is read from `lastConnectedConnectorHelpers` in `@tuwaio/orbit-core` (localStorage) and matched
|
|
158
|
+
* case-insensitively against the accounts of {@link getAvailableSolanaConnectors}.
|
|
159
|
+
*
|
|
160
|
+
* @returns The connected wallet as a `UiWallet`.
|
|
161
|
+
* @throws {Error} "Connector not provided. Cannot perform chain check." if no available wallet holds that address.
|
|
162
|
+
*/
|
|
126
163
|
declare function getConnectedSolanaConnector(): _wallet_standard_ui_core.UiWallet;
|
|
127
164
|
|
|
128
165
|
/**
|
|
@@ -178,7 +215,8 @@ declare const getSolanaNameCacheSize: () => number;
|
|
|
178
215
|
* Generates a full URL to an account, transaction, or block on the Solana explorer.
|
|
179
216
|
*
|
|
180
217
|
* @param url - The path after baseUrl (e.g. '/tx/...' or '/address/...').
|
|
181
|
-
* @param chainId - Chain ID or cluster name.
|
|
218
|
+
* @param chainId - Chain ID or cluster name (e.g. 'devnet' or 'solana:devnet').
|
|
219
|
+
* Mainnet ('mainnet', 'mainnet-beta') or an omitted value produces a link without a `cluster` query parameter.
|
|
182
220
|
* @returns The full URL on the Solana explorer.
|
|
183
221
|
*/
|
|
184
222
|
declare const getSolanaExplorerLink: (url?: string, chainId?: string | number | undefined) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -25,28 +25,43 @@ interface SolanaClient {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Resolves the Solana clusters an app can use.
|
|
29
|
+
*
|
|
30
|
+
* @param solanaRPCUrls - Optional mapping of cluster monikers to RPC URLs. When provided, only these clusters are allowed.
|
|
31
|
+
* @param chains - Optional chain identifiers (e.g. `'solana:devnet'`, `'solana:mainnet-beta'`); when provided, only
|
|
32
|
+
* clusters present in this list (and allowed by `solanaRPCUrls`) are returned.
|
|
33
|
+
* @returns Cluster monikers, e.g. `['mainnet', 'devnet']`. Defaults to every cluster with a default RPC URL.
|
|
29
34
|
*/
|
|
30
35
|
declare function getSolanaClusters(solanaRPCUrls?: Partial<Record<SolanaClusterMoniker, string>>, chains?: ChainIdentifierArray): string[];
|
|
31
36
|
/**
|
|
32
|
-
* Type guard to check if a chain list contains Solana cluster names
|
|
37
|
+
* Type guard to check if a chain list contains Solana cluster names.
|
|
38
|
+
*
|
|
39
|
+
* @param chains - Mixed list of chain identifiers.
|
|
40
|
+
* @returns `true` if the list is non-empty and contains only strings.
|
|
33
41
|
*/
|
|
34
42
|
declare function isSolanaChainList(chains: (string | number)[]): chains is string[];
|
|
35
43
|
/**
|
|
36
|
-
* Gets
|
|
44
|
+
* Gets the Solana clusters that have a default public RPC URL.
|
|
45
|
+
*
|
|
46
|
+
* @returns `['mainnet', 'devnet', 'testnet']`.
|
|
37
47
|
*/
|
|
38
48
|
declare function getAvailableSolanaClusters(): SolanaClusterMoniker[];
|
|
39
49
|
/**
|
|
40
|
-
* Validates if a string is a
|
|
50
|
+
* Validates if a string is a Solana cluster moniker with a default RPC URL.
|
|
51
|
+
*
|
|
52
|
+
* @param cluster - Value to check.
|
|
53
|
+
* @returns `true` for `'mainnet'`, `'devnet'` and `'testnet'`.
|
|
41
54
|
*/
|
|
42
55
|
declare function isValidSolanaCluster(cluster: string): boolean;
|
|
43
56
|
|
|
44
57
|
/**
|
|
45
58
|
* Safely extracts the cluster moniker from a chain identifier.
|
|
46
59
|
* Handles both full chain IDs ('solana:mainnet-beta') and simple monikers ('mainnet-beta').
|
|
47
|
-
*
|
|
48
|
-
* @param
|
|
49
|
-
* @param cluster
|
|
60
|
+
*
|
|
61
|
+
* @param params - Cluster sources.
|
|
62
|
+
* @param params.cluster - Chain identifier or cluster moniker. Takes precedence when provided.
|
|
63
|
+
* @param params.walletCluster - Cluster of the connected wallet, used when `cluster` is omitted.
|
|
64
|
+
* @returns The extracted cluster moniker, falling back to `walletCluster` and then to `'mainnet'`.
|
|
50
65
|
*/
|
|
51
66
|
declare const getCluster: ({ cluster, walletCluster }: {
|
|
52
67
|
cluster?: string;
|
|
@@ -54,8 +69,12 @@ declare const getCluster: ({ cluster, walletCluster }: {
|
|
|
54
69
|
}) => string;
|
|
55
70
|
/**
|
|
56
71
|
* Retrieves the configured RPC URL for a given cluster moniker.
|
|
57
|
-
*
|
|
58
|
-
* @
|
|
72
|
+
*
|
|
73
|
+
* @param params - Cluster selection and the configured RPC URLs.
|
|
74
|
+
* @param params.cluster - The target cluster, used when `walletCluster` is not provided.
|
|
75
|
+
* @param params.walletCluster - The cluster of the connected wallet. Takes precedence over `cluster`.
|
|
76
|
+
* @param params.rpcUrls - Mapping of cluster monikers to RPC URLs.
|
|
77
|
+
* @returns The configured RPC URL, or the public mainnet-beta endpoint if the cluster has no URL configured.
|
|
59
78
|
*/
|
|
60
79
|
declare const getRpcUrlForCluster: ({ cluster, walletCluster, rpcUrls, }: {
|
|
61
80
|
cluster: SolanaClusterMoniker;
|
|
@@ -121,8 +140,26 @@ declare const clearSolanaRpcCache: () => void;
|
|
|
121
140
|
*/
|
|
122
141
|
declare const defaultRpcUrlsByMoniker: Partial<Record<SolanaClusterMoniker, string>>;
|
|
123
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Lists the Solana wallets registered through the Wallet Standard that Orbit can work with.
|
|
145
|
+
*
|
|
146
|
+
* A wallet is included only if it supports `standard:connect`, `standard:disconnect`, `standard:events`,
|
|
147
|
+
* `solana:signAndSendTransaction`, `solana:signTransaction` and `solana:signMessage`, and every chain it
|
|
148
|
+
* declares is a `solana:*` chain. Wallets registered more than once are deduplicated by name.
|
|
149
|
+
*
|
|
150
|
+
* @returns The matching wallets as `UiWallet` objects from `@wallet-standard/ui-registry`
|
|
151
|
+
* (empty on the server, where no wallets are registered).
|
|
152
|
+
*/
|
|
124
153
|
declare function getAvailableSolanaConnectors(): _wallet_standard_ui_core.UiWallet[];
|
|
125
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Finds the Wallet Standard wallet that holds the last connected address.
|
|
157
|
+
* The address is read from `lastConnectedConnectorHelpers` in `@tuwaio/orbit-core` (localStorage) and matched
|
|
158
|
+
* case-insensitively against the accounts of {@link getAvailableSolanaConnectors}.
|
|
159
|
+
*
|
|
160
|
+
* @returns The connected wallet as a `UiWallet`.
|
|
161
|
+
* @throws {Error} "Connector not provided. Cannot perform chain check." if no available wallet holds that address.
|
|
162
|
+
*/
|
|
126
163
|
declare function getConnectedSolanaConnector(): _wallet_standard_ui_core.UiWallet;
|
|
127
164
|
|
|
128
165
|
/**
|
|
@@ -178,7 +215,8 @@ declare const getSolanaNameCacheSize: () => number;
|
|
|
178
215
|
* Generates a full URL to an account, transaction, or block on the Solana explorer.
|
|
179
216
|
*
|
|
180
217
|
* @param url - The path after baseUrl (e.g. '/tx/...' or '/address/...').
|
|
181
|
-
* @param chainId - Chain ID or cluster name.
|
|
218
|
+
* @param chainId - Chain ID or cluster name (e.g. 'devnet' or 'solana:devnet').
|
|
219
|
+
* Mainnet ('mainnet', 'mainnet-beta') or an omitted value produces a link without a `cluster` query parameter.
|
|
182
220
|
* @returns The full URL on the Solana explorer.
|
|
183
221
|
*/
|
|
184
222
|
declare const getSolanaExplorerLink: (url?: string, chainId?: string | number | undefined) => string;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var kit=require('@solana/kit'),orbitCore=require('@tuwaio/orbit-core'),app=require('@wallet-standard/app'),uiRegistry=require('@wallet-standard/ui-registry');var s={mainnet:"https://api.mainnet-beta.solana.com",devnet:"https://api.devnet.solana.com",testnet:"https://api.testnet.solana.com"};function d(t){let e=t.split(":");if(e.length<2)return null;let r=e[1];r==="mainnet-beta"&&(r="mainnet");let a=r;return a in s?a:null}function S(t,e){let r={},a=Object.keys(e||s);for(let n of t){if(typeof n!="string")continue;let o=d(n);if(!o||!a.includes(o))continue;let f=e?.[o]??s[o];f&&(r[o]=f);}return r}function
|
|
2
|
-
exports.clearSolanaAvatarCache=
|
|
1
|
+
'use strict';var kit=require('@solana/kit'),orbitCore=require('@tuwaio/orbit-core'),app=require('@wallet-standard/app'),uiRegistry=require('@wallet-standard/ui-registry');var s={mainnet:"https://api.mainnet-beta.solana.com",devnet:"https://api.devnet.solana.com",testnet:"https://api.testnet.solana.com"};function d(t){let e=t.split(":");if(e.length<2)return null;let r=e[1];r==="mainnet-beta"&&(r="mainnet");let a=r;return a in s?a:null}function S(t,e){let r={},a=Object.keys(e||s);for(let n of t){if(typeof n!="string")continue;let o=d(n);if(!o||!a.includes(o))continue;let f=e?.[o]??s[o];f&&(r[o]=f);}return r}function z(t,e){if(e&&e.length>0){let r=S(e,t);return Object.keys(r)}return Object.keys(t||s)}function T(t){return t.length>0&&t.every(e=>typeof e=="string")}function W(){return Object.keys(s)}function D(t){return t in s}var m=({cluster:t,walletCluster:e})=>{let r="mainnet";return t?t.includes(":")?t.split(":")[1]:t:e??r},q=({cluster:t,walletCluster:e,rpcUrls:r})=>r[e??t]??"https://api.mainnet-beta.solana.com/";function h(t){try{return new URL(t),!0}catch{return false}}function R(t){return t.replace(/^http/,"ws")}var l=new Map,G=({rpcUrlOrMoniker:t,rpcUrls:e})=>{if(l.has(t))return l.get(t);let r=h(t)?t:e?e[t]??s[t]:s[t];if(!r)throw new Error(`Unable to resolve RPC URL for input: "${t}". Ensure it's a valid URL or known moniker.`);let a=kit.createSolanaRpc(r),n;try{n=kit.createSolanaRpcSubscriptions(R(r));}catch{}let o={rpc:a,...n?{rpcSubscriptions:n}:{}};return l.set(t,o),o},J=()=>{l.clear();};function v(t){try{return new URL(t),!0}catch{return false}}var c=new Map,O=({rpcUrlOrMoniker:t,rpcUrls:e})=>{if(c.has(t))return c.get(t);let r=v(t)?t:e?e[t]??s[t]:s[t];if(!r)throw new Error(`Unable to resolve RPC URL for input: "${t}". Ensure it's a valid URL or known moniker.`);let a=kit.createSolanaRpc(r);return c.set(t,a),a},tt=()=>{c.clear();};function g(){return orbitCore.filterUniqueByKey(app.getWallets().get().map(uiRegistry.getOrCreateUiWalletForStandardWallet),"name").filter(t=>{try{return !t||!Array.isArray(t.chains)||!t.features||!Array.isArray(t.features)||!["standard:connect","standard:disconnect","standard:events","solana:signAndSendTransaction","solana:signTransaction","solana:signMessage"].every(a=>t.features.includes(a))?!1:t.chains.every(a=>{try{if(typeof a!="string")return !1;let n=a.split(":");return n.length>=1&&n[0]==="solana"}catch(n){return console.warn("Error parsing chain:",a,n),!1}})}catch(e){return console.warn("Error filtering wallet:",e),false}})}function lt(){let t=orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector(),r=g().find(a=>a.accounts.find(n=>n.address.toLowerCase()===t?.address?.toLowerCase()));if(!r)throw new Error("Connector not provided. Cannot perform chain check.");return r}var u=new Map,L="https://image-api.bonfida.com",P=t=>/^[a-z0-9-]+\.sol$/.test(t.toLowerCase()),N=async t=>{try{let e=await fetch(`${L}/image?domain=${encodeURIComponent(t)}`);if(!e.ok)return null;let r=await e.json();return r.result&&Array.isArray(r.result)&&r.result.length>0?r.result.find(n=>n.domain===t)?.image??r.result[0]?.image??null:null}catch(e){return console.warn("Failed to fetch SNS avatar:",e),null}},i=t=>`https://api.dicebear.com/7.x/identicon/svg?seed=${encodeURIComponent(t)}`,E=async t=>{if(!t)return i("default");let e=t.trim();if(!e)return i("default");let r=e.toLowerCase(),a=u.get(r);if(a!==void 0)return a;let n;try{if(P(e)){let o=await N(e);o?n=o:n=i(e);}else kit.isAddress(e),n=i(e);}catch(o){console.warn("Error resolving avatar:",o),n=i(e);}return u.set(r,n),n},pt=()=>{u.clear();},ft=()=>u.size,mt=async t=>{try{await E(t);}catch(e){console.warn("Failed to preload avatar:",e);}};var p=new Map,$="https://sns-api.bonfida.com",I=async t=>{try{let e=await fetch(`${$}/v2/user/fav-domains/${t}`);if(!e.ok)return null;let r=await e.json();return r.result&&typeof r.result=="object"&&t in r.result?r.result[t]:null}catch(e){return console.warn("Failed to fetch SNS name:",e),null}},St=async t=>{if(!t)return t||"";let e=t.trim();if(!kit.isAddress(e))return t;let r=e.toLowerCase(),a=p.get(r);if(a!==void 0)return a;let n=t;try{let o=await I(e);o&&(n=o);}catch(o){console.warn("Error resolving address name:",o);}return p.set(r,n),n},Ct=()=>{p.clear();},yt=()=>p.size;var _="https://explorer.solana.com",F=new Set(["mainnet","mainnet-beta"]),At=(t,e)=>{let r=m({cluster:e===void 0?void 0:String(e)}),a=_,n=F.has(r)?"":`?cluster=${r}`,o=t?t.startsWith("/")?t:`/${t}`:"/";return `${a}${o}${n}`};
|
|
2
|
+
exports.clearSolanaAvatarCache=pt;exports.clearSolanaClientCache=J;exports.clearSolanaNameCache=Ct;exports.clearSolanaRpcCache=tt;exports.createSolanaClientWithCache=G;exports.createSolanaRPC=O;exports.defaultRpcUrlsByMoniker=s;exports.getAvailableSolanaClusters=W;exports.getAvailableSolanaConnectors=g;exports.getCluster=m;exports.getConnectedSolanaConnector=lt;exports.getRpcUrlForCluster=q;exports.getSolanaAddressAvatar=E;exports.getSolanaAddressName=St;exports.getSolanaAvatarCacheSize=ft;exports.getSolanaClusters=z;exports.getSolanaExplorerLink=At;exports.getSolanaNameCacheSize=yt;exports.isSolanaChainList=T;exports.isValidSolanaCluster=D;exports.preloadSolanaAvatar=mt;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {createSolanaRpc,createSolanaRpcSubscriptions,isAddress}from'@solana/kit';import {filterUniqueByKey,lastConnectedConnectorHelpers}from'@tuwaio/orbit-core';import {getWallets}from'@wallet-standard/app';import {getOrCreateUiWalletForStandardWallet}from'@wallet-standard/ui-registry';var s={mainnet:"https://api.mainnet-beta.solana.com",devnet:"https://api.devnet.solana.com",testnet:"https://api.testnet.solana.com"};function d(t){let e=t.split(":");if(e.length<2)return null;let r=e[1];r==="mainnet-beta"&&(r="mainnet");let a=r;return a in s?a:null}function S(t,e){let r={},a=Object.keys(e||s);for(let n of t){if(typeof n!="string")continue;let o=d(n);if(!o||!a.includes(o))continue;let f=e?.[o]??s[o];f&&(r[o]=f);}return r}function
|
|
2
|
-
export{
|
|
1
|
+
import {createSolanaRpc,createSolanaRpcSubscriptions,isAddress}from'@solana/kit';import {filterUniqueByKey,lastConnectedConnectorHelpers}from'@tuwaio/orbit-core';import {getWallets}from'@wallet-standard/app';import {getOrCreateUiWalletForStandardWallet}from'@wallet-standard/ui-registry';var s={mainnet:"https://api.mainnet-beta.solana.com",devnet:"https://api.devnet.solana.com",testnet:"https://api.testnet.solana.com"};function d(t){let e=t.split(":");if(e.length<2)return null;let r=e[1];r==="mainnet-beta"&&(r="mainnet");let a=r;return a in s?a:null}function S(t,e){let r={},a=Object.keys(e||s);for(let n of t){if(typeof n!="string")continue;let o=d(n);if(!o||!a.includes(o))continue;let f=e?.[o]??s[o];f&&(r[o]=f);}return r}function z(t,e){if(e&&e.length>0){let r=S(e,t);return Object.keys(r)}return Object.keys(t||s)}function T(t){return t.length>0&&t.every(e=>typeof e=="string")}function W(){return Object.keys(s)}function D(t){return t in s}var m=({cluster:t,walletCluster:e})=>{let r="mainnet";return t?t.includes(":")?t.split(":")[1]:t:e??r},q=({cluster:t,walletCluster:e,rpcUrls:r})=>r[e??t]??"https://api.mainnet-beta.solana.com/";function h(t){try{return new URL(t),!0}catch{return false}}function R(t){return t.replace(/^http/,"ws")}var l=new Map,G=({rpcUrlOrMoniker:t,rpcUrls:e})=>{if(l.has(t))return l.get(t);let r=h(t)?t:e?e[t]??s[t]:s[t];if(!r)throw new Error(`Unable to resolve RPC URL for input: "${t}". Ensure it's a valid URL or known moniker.`);let a=createSolanaRpc(r),n;try{n=createSolanaRpcSubscriptions(R(r));}catch{}let o={rpc:a,...n?{rpcSubscriptions:n}:{}};return l.set(t,o),o},J=()=>{l.clear();};function v(t){try{return new URL(t),!0}catch{return false}}var c=new Map,O=({rpcUrlOrMoniker:t,rpcUrls:e})=>{if(c.has(t))return c.get(t);let r=v(t)?t:e?e[t]??s[t]:s[t];if(!r)throw new Error(`Unable to resolve RPC URL for input: "${t}". Ensure it's a valid URL or known moniker.`);let a=createSolanaRpc(r);return c.set(t,a),a},tt=()=>{c.clear();};function g(){return filterUniqueByKey(getWallets().get().map(getOrCreateUiWalletForStandardWallet),"name").filter(t=>{try{return !t||!Array.isArray(t.chains)||!t.features||!Array.isArray(t.features)||!["standard:connect","standard:disconnect","standard:events","solana:signAndSendTransaction","solana:signTransaction","solana:signMessage"].every(a=>t.features.includes(a))?!1:t.chains.every(a=>{try{if(typeof a!="string")return !1;let n=a.split(":");return n.length>=1&&n[0]==="solana"}catch(n){return console.warn("Error parsing chain:",a,n),!1}})}catch(e){return console.warn("Error filtering wallet:",e),false}})}function lt(){let t=lastConnectedConnectorHelpers.getLastConnectedConnector(),r=g().find(a=>a.accounts.find(n=>n.address.toLowerCase()===t?.address?.toLowerCase()));if(!r)throw new Error("Connector not provided. Cannot perform chain check.");return r}var u=new Map,L="https://image-api.bonfida.com",P=t=>/^[a-z0-9-]+\.sol$/.test(t.toLowerCase()),N=async t=>{try{let e=await fetch(`${L}/image?domain=${encodeURIComponent(t)}`);if(!e.ok)return null;let r=await e.json();return r.result&&Array.isArray(r.result)&&r.result.length>0?r.result.find(n=>n.domain===t)?.image??r.result[0]?.image??null:null}catch(e){return console.warn("Failed to fetch SNS avatar:",e),null}},i=t=>`https://api.dicebear.com/7.x/identicon/svg?seed=${encodeURIComponent(t)}`,E=async t=>{if(!t)return i("default");let e=t.trim();if(!e)return i("default");let r=e.toLowerCase(),a=u.get(r);if(a!==void 0)return a;let n;try{if(P(e)){let o=await N(e);o?n=o:n=i(e);}else isAddress(e),n=i(e);}catch(o){console.warn("Error resolving avatar:",o),n=i(e);}return u.set(r,n),n},pt=()=>{u.clear();},ft=()=>u.size,mt=async t=>{try{await E(t);}catch(e){console.warn("Failed to preload avatar:",e);}};var p=new Map,$="https://sns-api.bonfida.com",I=async t=>{try{let e=await fetch(`${$}/v2/user/fav-domains/${t}`);if(!e.ok)return null;let r=await e.json();return r.result&&typeof r.result=="object"&&t in r.result?r.result[t]:null}catch(e){return console.warn("Failed to fetch SNS name:",e),null}},St=async t=>{if(!t)return t||"";let e=t.trim();if(!isAddress(e))return t;let r=e.toLowerCase(),a=p.get(r);if(a!==void 0)return a;let n=t;try{let o=await I(e);o&&(n=o);}catch(o){console.warn("Error resolving address name:",o);}return p.set(r,n),n},Ct=()=>{p.clear();},yt=()=>p.size;var _="https://explorer.solana.com",F=new Set(["mainnet","mainnet-beta"]),At=(t,e)=>{let r=m({cluster:e===void 0?void 0:String(e)}),a=_,n=F.has(r)?"":`?cluster=${r}`,o=t?t.startsWith("/")?t:`/${t}`:"/";return `${a}${o}${n}`};
|
|
2
|
+
export{pt as clearSolanaAvatarCache,J as clearSolanaClientCache,Ct as clearSolanaNameCache,tt as clearSolanaRpcCache,G as createSolanaClientWithCache,O as createSolanaRPC,s as defaultRpcUrlsByMoniker,W as getAvailableSolanaClusters,g as getAvailableSolanaConnectors,m as getCluster,lt as getConnectedSolanaConnector,q as getRpcUrlForCluster,E as getSolanaAddressAvatar,St as getSolanaAddressName,ft as getSolanaAvatarCacheSize,z as getSolanaClusters,At as getSolanaExplorerLink,yt as getSolanaNameCacheSize,T as isSolanaChainList,D as isValidSolanaCluster,mt as preloadSolanaAvatar};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuwaio/orbit-solana",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Oleksandr Tkach",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "L2 Solana package of Orbit Utils (TUWA): cached @solana/kit RPC clients, Wallet Standard discovery, cluster and explorer helpers, and SNS name/avatar lookups.",
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"module": "./dist/index.mjs",
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
@@ -16,9 +16,14 @@
|
|
|
16
16
|
"socket.json"
|
|
17
17
|
],
|
|
18
18
|
"keywords": [
|
|
19
|
+
"tuwa",
|
|
20
|
+
"orbit",
|
|
19
21
|
"web3",
|
|
20
|
-
"typescript",
|
|
21
22
|
"solana",
|
|
23
|
+
"@solana/kit",
|
|
24
|
+
"wallet-standard",
|
|
25
|
+
"sns",
|
|
26
|
+
"typescript",
|
|
22
27
|
"headless"
|
|
23
28
|
],
|
|
24
29
|
"repository": {
|
|
@@ -44,10 +49,10 @@
|
|
|
44
49
|
"@wallet-standard/ui-registry": "1.x.x"
|
|
45
50
|
},
|
|
46
51
|
"devDependencies": {
|
|
47
|
-
"@tuwaio/orbit-core": "^0.3.
|
|
52
|
+
"@tuwaio/orbit-core": "^0.3.1",
|
|
48
53
|
"tsup": "^8.5.1",
|
|
49
|
-
"typescript": "
|
|
50
|
-
"@solana/kit": "^8.
|
|
54
|
+
"typescript": "6.0.3",
|
|
55
|
+
"@solana/kit": "^8.3.0",
|
|
51
56
|
"@wallet-standard/app": "^1.1.1",
|
|
52
57
|
"@wallet-standard/ui-core": "^1.0.1",
|
|
53
58
|
"@wallet-standard/ui-registry": "^1.1.1"
|