@solana/connector 0.1.6 → 0.1.7

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 (38) hide show
  1. package/README.md +45 -45
  2. package/dist/{chunk-VMSZJPR5.mjs → chunk-APQGEW7S.mjs} +82 -11
  3. package/dist/chunk-APQGEW7S.mjs.map +1 -0
  4. package/dist/{chunk-3STZXVXD.mjs → chunk-JK47EFJT.mjs} +940 -381
  5. package/dist/chunk-JK47EFJT.mjs.map +1 -0
  6. package/dist/{chunk-QKVL45F6.mjs → chunk-TQRJYZNK.mjs} +5 -3
  7. package/dist/chunk-TQRJYZNK.mjs.map +1 -0
  8. package/dist/{chunk-JUZVCBAI.js → chunk-VA6LKXCQ.js} +85 -10
  9. package/dist/chunk-VA6LKXCQ.js.map +1 -0
  10. package/dist/{chunk-NQXK7PGX.js → chunk-VZ5Y6DIM.js} +19 -17
  11. package/dist/chunk-VZ5Y6DIM.js.map +1 -0
  12. package/dist/{chunk-ULUYX23Q.js → chunk-Z22V3D4E.js} +949 -388
  13. package/dist/chunk-Z22V3D4E.js.map +1 -0
  14. package/dist/compat.d.mts +1 -1
  15. package/dist/compat.d.ts +1 -1
  16. package/dist/headless.d.mts +99 -7
  17. package/dist/headless.d.ts +99 -7
  18. package/dist/headless.js +128 -112
  19. package/dist/headless.mjs +2 -2
  20. package/dist/index.d.mts +5 -4
  21. package/dist/index.d.ts +5 -4
  22. package/dist/index.js +163 -139
  23. package/dist/index.mjs +3 -3
  24. package/dist/react.d.mts +179 -13
  25. package/dist/react.d.ts +179 -13
  26. package/dist/react.js +36 -28
  27. package/dist/react.mjs +2 -2
  28. package/dist/{transaction-signer-D9d8nxwb.d.mts → transaction-signer-CpGEvp7S.d.mts} +1 -1
  29. package/dist/{transaction-signer-D9d8nxwb.d.ts → transaction-signer-CpGEvp7S.d.ts} +1 -1
  30. package/dist/{wallet-standard-shim--YcrQNRt.d.ts → wallet-standard-shim-D4CYG5sU.d.mts} +35 -6
  31. package/dist/{wallet-standard-shim-Dx7H8Ctf.d.mts → wallet-standard-shim-DiMvGjOk.d.ts} +35 -6
  32. package/package.json +1 -1
  33. package/dist/chunk-3STZXVXD.mjs.map +0 -1
  34. package/dist/chunk-JUZVCBAI.js.map +0 -1
  35. package/dist/chunk-NQXK7PGX.js.map +0 -1
  36. package/dist/chunk-QKVL45F6.mjs.map +0 -1
  37. package/dist/chunk-ULUYX23Q.js.map +0 -1
  38. package/dist/chunk-VMSZJPR5.mjs.map +0 -1
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: @solana/connector
2
+ title: '@solana/connector'
3
3
  description: Production-ready wallet connector for Solana applications
4
4
  ---
5
5
 
@@ -30,7 +30,7 @@ npm install @solana/connector
30
30
  pnpm add @solana/connector
31
31
  # or
32
32
  yarn add @solana/connector
33
- # or
33
+ # or
34
34
  bun add @solana/connector
35
35
  ```
36
36
 
@@ -671,6 +671,7 @@ const config = getDefaultConfig({
671
671
  ```
672
672
 
673
673
  Your `.env` file (no `NEXT_PUBLIC_` prefix):
674
+
674
675
  ```
675
676
  SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=your-key
676
677
  ```
@@ -708,12 +709,12 @@ https://raw.githubusercontent.com/.../token-logo.png
708
709
 
709
710
  ### Common Proxy Options
710
711
 
711
- | Service | Configuration |
712
- |---------|---------------|
713
- | **Next.js Image** | `imageProxy: '/_next/image?w=64&q=75&url='` |
714
- | **Cloudflare** | `imageProxy: '/cdn-cgi/image/width=64,quality=75/'` |
715
- | **imgproxy** | `imageProxy: 'https://imgproxy.example.com/insecure/fill/64/64/'` |
716
- | **Custom API** | `imageProxy: '/api/image-proxy?url='` |
712
+ | Service | Configuration |
713
+ | ----------------- | ----------------------------------------------------------------- |
714
+ | **Next.js Image** | `imageProxy: '/_next/image?w=64&q=75&url='` |
715
+ | **Cloudflare** | `imageProxy: '/cdn-cgi/image/width=64,quality=75/'` |
716
+ | **imgproxy** | `imageProxy: 'https://imgproxy.example.com/insecure/fill/64/64/'` |
717
+ | **Custom API** | `imageProxy: '/api/image-proxy?url='` |
717
718
 
718
719
  ### Custom Proxy API Route (Next.js Example)
719
720
 
@@ -790,14 +791,12 @@ function validateUrl(urlString: string): URL | null {
790
791
 
791
792
  // Check if hostname is in the allowlist
792
793
  function isAllowedDomain(hostname: string): boolean {
793
- return ALLOWED_DOMAINS.some(
794
- (domain) => hostname === domain || hostname.endsWith(`.${domain}`)
795
- );
794
+ return ALLOWED_DOMAINS.some(domain => hostname === domain || hostname.endsWith(`.${domain}`));
796
795
  }
797
796
 
798
797
  export async function GET(request: NextRequest) {
799
798
  const urlParam = request.nextUrl.searchParams.get('url');
800
-
799
+
801
800
  // (1) Ensure URL exists and parses correctly with http/https
802
801
  if (!urlParam) {
803
802
  return new NextResponse('Missing URL parameter', { status: 400 });
@@ -829,7 +828,7 @@ export async function GET(request: NextRequest) {
829
828
  try {
830
829
  const response = await fetch(parsedUrl.toString());
831
830
  const buffer = await response.arrayBuffer();
832
-
831
+
833
832
  return new NextResponse(buffer, {
834
833
  headers: {
835
834
  'Content-Type': response.headers.get('Content-Type') || 'image/png',
@@ -850,16 +849,17 @@ The `useTokens()` hook fetches token prices from CoinGecko. CoinGecko has rate l
850
849
 
851
850
  ### Rate Limits (as of 2024)
852
851
 
853
- | Tier | Rate Limit | API Key Required |
854
- |------|------------|------------------|
855
- | **Free (Public)** | 10-30 requests/minute | No |
856
- | **Demo** | 30 requests/minute | Yes (free) |
857
- | **Analyst** | 500 requests/minute | Yes (paid) |
858
- | **Pro** | 1000+ requests/minute | Yes (paid) |
852
+ | Tier | Rate Limit | API Key Required |
853
+ | ----------------- | --------------------- | ---------------- |
854
+ | **Free (Public)** | 10-30 requests/minute | No |
855
+ | **Demo** | 30 requests/minute | Yes (free) |
856
+ | **Analyst** | 500 requests/minute | Yes (paid) |
857
+ | **Pro** | 1000+ requests/minute | Yes (paid) |
859
858
 
860
859
  ### Handling Rate Limits
861
860
 
862
861
  ConnectorKit automatically handles rate limits with:
862
+
863
863
  - **Exponential backoff**: Retries with increasing delays
864
864
  - **Jitter**: Random delay added to prevent thundering herd
865
865
  - **Retry-After header**: Honors server-specified wait times
@@ -887,16 +887,16 @@ const config = getDefaultConfig({
887
887
  coingecko: {
888
888
  // API key for higher rate limits (optional)
889
889
  apiKey: process.env.COINGECKO_API_KEY,
890
-
890
+
891
891
  // Set to true if using a Pro API key (default: false for Demo keys)
892
892
  isPro: false,
893
-
893
+
894
894
  // Maximum retry attempts on 429 (default: 3)
895
895
  maxRetries: 3,
896
-
896
+
897
897
  // Base delay for exponential backoff in ms (default: 1000)
898
898
  baseDelay: 1000,
899
-
899
+
900
900
  // Maximum total timeout in ms (default: 30000)
901
901
  maxTimeout: 30000,
902
902
  },
@@ -1007,35 +1007,35 @@ import { useConnector, useAccount } from '@solana/connector/react';
1007
1007
 
1008
1008
  ### Hooks
1009
1009
 
1010
- | Hook | Description | Returns |
1011
- |------|-------------|---------|
1012
- | `useConnector()` | Main wallet connection hook | `{ wallets, selectedWallet, accounts, connected, connecting, select, disconnect }` |
1013
- | `useAccount()` | Account management hook | `{ address, formatted, copy, copied, accounts, selectAccount }` |
1014
- | `useCluster()` | Network/cluster management hook | `{ cluster, clusters, setCluster, isMainnet, isDevnet, rpcUrl }` |
1015
- | `useWalletInfo()` | Wallet metadata hook | `{ name, icon, wallet, connecting }` |
1016
- | `useTransactionSigner()` | Legacy transaction signer (web3.js) | `{ signer, ready, address, capabilities }` |
1017
- | `useKitTransactionSigner()` | Modern transaction signer (@solana/kit) | `{ signer, ready, address }` |
1018
- | `useBalance()` | SOL balance hook | `{ solBalance, isLoading, refetch }` |
1019
- | `useTokens()` | SPL tokens hook | `{ tokens, isLoading, refetch }` |
1020
- | `useTransactions()` | Transaction history hook | `{ transactions, isLoading, refetch }` |
1010
+ | Hook | Description | Returns |
1011
+ | --------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------- |
1012
+ | `useConnector()` | Main wallet connection hook | `{ wallets, selectedWallet, accounts, connected, connecting, select, disconnect }` |
1013
+ | `useAccount()` | Account management hook | `{ address, formatted, copy, copied, accounts, selectAccount }` |
1014
+ | `useCluster()` | Network/cluster management hook | `{ cluster, clusters, setCluster, isMainnet, isDevnet, rpcUrl }` |
1015
+ | `useWalletInfo()` | Wallet metadata hook | `{ name, icon, wallet, connecting }` |
1016
+ | `useTransactionSigner()` | Legacy transaction signer (web3.js) | `{ signer, ready, address, capabilities }` |
1017
+ | `useKitTransactionSigner()` | Modern transaction signer (@solana/kit) | `{ signer, ready, address }` |
1018
+ | `useBalance()` | SOL balance hook | `{ solBalance, isLoading, refetch }` |
1019
+ | `useTokens()` | SPL tokens hook | `{ tokens, isLoading, refetch }` |
1020
+ | `useTransactions()` | Transaction history hook | `{ transactions, isLoading, refetch }` |
1021
1021
 
1022
1022
  ### Configuration Functions
1023
1023
 
1024
- | Function | Description |
1025
- |----------|-------------|
1026
- | `getDefaultConfig(options)` | Create default connector configuration |
1027
- | `getDefaultMobileConfig(options)` | Create mobile wallet adapter configuration |
1028
- | `createConfig(options)` | Create unified config for ConnectorKit + Armadura |
1024
+ | Function | Description |
1025
+ | --------------------------------- | ------------------------------------------------- |
1026
+ | `getDefaultConfig(options)` | Create default connector configuration |
1027
+ | `getDefaultMobileConfig(options)` | Create mobile wallet adapter configuration |
1028
+ | `createConfig(options)` | Create unified config for ConnectorKit + Armadura |
1029
1029
 
1030
1030
  ### Utility Functions
1031
1031
 
1032
- | Function | Description |
1033
- |----------|-------------|
1034
- | `formatAddress(address, options?)` | Format Solana address |
1035
- | `formatSOL(lamports, options?)` | Format SOL amount |
1036
- | `copyAddressToClipboard(address)` | Copy address to clipboard |
1032
+ | Function | Description |
1033
+ | --------------------------------------- | ----------------------------------- |
1034
+ | `formatAddress(address, options?)` | Format Solana address |
1035
+ | `formatSOL(lamports, options?)` | Format SOL amount |
1036
+ | `copyAddressToClipboard(address)` | Copy address to clipboard |
1037
1037
  | `getTransactionUrl(cluster, signature)` | Get Solana Explorer transaction URL |
1038
- | `getAddressUrl(cluster, address)` | Get Solana Explorer address URL |
1038
+ | `getAddressUrl(cluster, address)` | Get Solana Explorer address URL |
1039
1039
 
1040
1040
  ---
1041
1041
 
@@ -228,6 +228,11 @@ function getNetworkDisplayName(network) {
228
228
  }
229
229
 
230
230
  // src/utils/cluster.ts
231
+ function getMaybeStringProp(value, prop) {
232
+ if (typeof value != "object" || value === null) return;
233
+ let v = value[prop];
234
+ return typeof v == "string" ? v : void 0;
235
+ }
231
236
  function getClusterRpcUrl(cluster) {
232
237
  if (typeof cluster == "string") {
233
238
  let presets2 = {
@@ -238,7 +243,7 @@ function getClusterRpcUrl(cluster) {
238
243
  return presets2[cluster];
239
244
  throw new Error(`Unknown cluster: ${cluster}`);
240
245
  }
241
- let url = cluster.url || cluster.rpcUrl;
246
+ let url = cluster.url ?? getMaybeStringProp(cluster, "rpcUrl");
242
247
  if (!url)
243
248
  throw new Error("Cluster URL is required");
244
249
  if (url.startsWith("http://") || url.startsWith("https://"))
@@ -283,16 +288,17 @@ function isTestnetCluster(cluster) {
283
288
  return cluster.id === "solana:testnet";
284
289
  }
285
290
  function isLocalCluster(cluster) {
286
- let url = cluster.url || cluster.rpcUrl;
291
+ let url = cluster.url ?? getMaybeStringProp(cluster, "rpcUrl");
287
292
  return url ? cluster.id === "solana:localnet" || url.includes("localhost") || url.includes("127.0.0.1") : cluster.id === "solana:localnet";
288
293
  }
289
294
  function getClusterName(cluster) {
290
295
  if (cluster.label) return cluster.label;
291
- if (cluster.name) return cluster.name;
296
+ let name = getMaybeStringProp(cluster, "name");
297
+ if (name) return name;
292
298
  let parts = cluster.id.split(":");
293
299
  if (parts.length >= 2 && parts[1]) {
294
- let name = parts.slice(1).join(":");
295
- return name.charAt(0).toUpperCase() + name.slice(1).replace(/-/g, " ");
300
+ let name2 = parts.slice(1).join(":");
301
+ return name2.charAt(0).toUpperCase() + name2.slice(1).replace(/-/g, " ");
296
302
  }
297
303
  return "Unknown";
298
304
  }
@@ -1284,7 +1290,7 @@ var TransactionTracker = class extends BaseCollaborator {
1284
1290
  * Track a transaction for debugging and monitoring
1285
1291
  */
1286
1292
  trackTransaction(activity) {
1287
- let clusterId = this.getState().cluster?.id || "solana:devnet", fullActivity = {
1293
+ let clusterId = this.getState().cluster?.id ?? "solana:devnet", fullActivity = {
1288
1294
  ...activity,
1289
1295
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1290
1296
  cluster: clusterId
@@ -1300,10 +1306,10 @@ var TransactionTracker = class extends BaseCollaborator {
1300
1306
  * Update transaction status (e.g., from pending to confirmed/failed)
1301
1307
  */
1302
1308
  updateStatus(signature, status, error) {
1303
- let tx = this.transactions.find((t) => t.signature === signature);
1309
+ let tx = this.transactions.find((t) => String(t.signature) === signature);
1304
1310
  tx && (tx.status = status, error && (tx.error = error), this.eventEmitter.emit({
1305
1311
  type: "transaction:updated",
1306
- signature,
1312
+ signature: tx.signature,
1307
1313
  status,
1308
1314
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1309
1315
  }), this.log("[Connector] Transaction updated:", { signature, status, error }));
@@ -1886,6 +1892,71 @@ function formatTokenAmount(amount, decimals, options = {}) {
1886
1892
  maximumFractionDigits: maxDecimals
1887
1893
  });
1888
1894
  }
1895
+ var MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
1896
+ function isSafeInteger(value) {
1897
+ return value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
1898
+ }
1899
+ function splitBigIntDecimals(amount, decimals) {
1900
+ if (decimals <= 0)
1901
+ return { whole: amount.toString(), fraction: "" };
1902
+ let str = amount.toString(), isNegative = str.startsWith("-"), absStr = isNegative ? str.slice(1) : str;
1903
+ if (absStr.length <= decimals) {
1904
+ let padded = absStr.padStart(decimals, "0");
1905
+ return {
1906
+ whole: isNegative ? "-0" : "0",
1907
+ fraction: padded
1908
+ };
1909
+ }
1910
+ let splitPoint = absStr.length - decimals;
1911
+ return {
1912
+ whole: (isNegative ? "-" : "") + absStr.slice(0, splitPoint),
1913
+ fraction: absStr.slice(splitPoint)
1914
+ };
1915
+ }
1916
+ function formatBigIntBalance(amount, decimals, options = {}) {
1917
+ let { maxDecimals = Math.min(decimals, 6), minDecimals = 0, locale, useGrouping = true } = options;
1918
+ if (isSafeInteger(amount))
1919
+ return (Number(amount) / Math.pow(10, decimals)).toLocaleString(locale, {
1920
+ minimumFractionDigits: minDecimals,
1921
+ maximumFractionDigits: maxDecimals,
1922
+ useGrouping
1923
+ });
1924
+ let { whole, fraction } = splitBigIntDecimals(amount, decimals), truncatedFraction = fraction.slice(0, maxDecimals);
1925
+ for (; truncatedFraction.length > minDecimals && truncatedFraction.endsWith("0"); )
1926
+ truncatedFraction = truncatedFraction.slice(0, -1);
1927
+ truncatedFraction = truncatedFraction.padEnd(minDecimals, "0");
1928
+ let formattedWhole = whole;
1929
+ if (useGrouping) {
1930
+ let isNegative = whole.startsWith("-"), absWhole = isNegative ? whole.slice(1) : whole, parts = [];
1931
+ for (let i = absWhole.length; i > 0; i -= 3)
1932
+ parts.unshift(absWhole.slice(Math.max(0, i - 3), i));
1933
+ formattedWhole = (isNegative ? "-" : "") + parts.join(",");
1934
+ }
1935
+ return truncatedFraction.length === 0 ? formattedWhole : `${formattedWhole}.${truncatedFraction}`;
1936
+ }
1937
+ function formatLamportsToSolSafe(lamports, options = {}) {
1938
+ let { maxDecimals = 4, minDecimals = 0, suffix = false, locale } = options, formatted = formatBigIntBalance(lamports, 9, {
1939
+ maxDecimals,
1940
+ minDecimals,
1941
+ locale
1942
+ });
1943
+ return suffix ? `${formatted} SOL` : formatted;
1944
+ }
1945
+ function formatBigIntUsd(amount, decimals, usdPrice, options = {}) {
1946
+ let { locale, currency = "USD" } = options, { whole, fraction } = splitBigIntDecimals(amount, decimals), wholeNum = parseFloat(whole), fractionNum = fraction ? parseFloat("0." + fraction) : 0;
1947
+ return ((wholeNum + fractionNum) * usdPrice).toLocaleString(locale, {
1948
+ style: "currency",
1949
+ currency,
1950
+ minimumFractionDigits: 2,
1951
+ maximumFractionDigits: 2
1952
+ });
1953
+ }
1954
+ function formatTokenBalanceSafe(amount, decimals, options = {}) {
1955
+ return formatBigIntBalance(amount, decimals, {
1956
+ maxDecimals: options.maxDecimals ?? Math.min(decimals, 6),
1957
+ locale: options.locale
1958
+ });
1959
+ }
1889
1960
  var ClipboardErrorType = /* @__PURE__ */ ((ClipboardErrorType2) => (ClipboardErrorType2.NOT_SUPPORTED = "not_supported", ClipboardErrorType2.PERMISSION_DENIED = "permission_denied", ClipboardErrorType2.SSR = "ssr", ClipboardErrorType2.EMPTY_VALUE = "empty_value", ClipboardErrorType2.INVALID_VALUE = "invalid_value", ClipboardErrorType2.UNKNOWN = "unknown", ClipboardErrorType2))(ClipboardErrorType || {});
1890
1961
  function isClipboardAvailable() {
1891
1962
  if (typeof window > "u" || typeof document > "u")
@@ -2447,6 +2518,6 @@ function createKitTransactionSigner(connectorSigner) {
2447
2518
  }
2448
2519
  var createGillTransactionSigner = createKitTransactionSigner;
2449
2520
 
2450
- export { ClipboardErrorType, ConfigurationError, ConnectionError, ConnectorClient, ConnectorError, ConnectorErrorBoundary, DEFAULT_MAX_RETRIES, Errors, NetworkError, PUBLIC_RPC_ENDPOINTS, TransactionError, TransactionSignerError, ValidationError, WalletErrorType, copyAddressToClipboard, copySignatureToClipboard, copyToClipboard, createGillTransactionSigner, createKitTransactionSigner, createTransactionSigner, formatAddress, formatNumber, formatSOL, formatTokenAmount, getAddressUrl, getBlockUrl, getChainIdForWalletStandard, getClusterChainId, getClusterExplorerUrl, getClusterName, getClusterRpcUrl, getClusterType, getDefaultRpcUrl, getNetworkDisplayName, getPolyfillStatus, getTokenUrl, getTransactionUrl, getUserFriendlyMessage, getWalletsRegistry, installPolyfills, isClipboardAvailable, isConfigurationError, isConnectionError, isConnectorError, isCryptoAvailable, isDevnet, isDevnetCluster, isLocalCluster, isLocalnet, isMainnet, isMainnetCluster, isNetworkError, isPolyfillInstalled, isTestnet, isTestnetCluster, isTransactionError, isTransactionSignerError, isValidationError, normalizeNetwork, toClusterId, toConnectorError, truncate, withErrorBoundary };
2451
- //# sourceMappingURL=chunk-VMSZJPR5.mjs.map
2452
- //# sourceMappingURL=chunk-VMSZJPR5.mjs.map
2521
+ export { ClipboardErrorType, ConfigurationError, ConnectionError, ConnectorClient, ConnectorError, ConnectorErrorBoundary, DEFAULT_MAX_RETRIES, Errors, NetworkError, PUBLIC_RPC_ENDPOINTS, TransactionError, TransactionSignerError, ValidationError, WalletErrorType, copyAddressToClipboard, copySignatureToClipboard, copyToClipboard, createGillTransactionSigner, createKitTransactionSigner, createTransactionSigner, formatAddress, formatBigIntBalance, formatBigIntUsd, formatLamportsToSolSafe, formatNumber, formatSOL, formatTokenAmount, formatTokenBalanceSafe, getAddressUrl, getBlockUrl, getChainIdForWalletStandard, getClusterChainId, getClusterExplorerUrl, getClusterName, getClusterRpcUrl, getClusterType, getDefaultRpcUrl, getNetworkDisplayName, getPolyfillStatus, getTokenUrl, getTransactionUrl, getUserFriendlyMessage, getWalletsRegistry, installPolyfills, isClipboardAvailable, isConfigurationError, isConnectionError, isConnectorError, isCryptoAvailable, isDevnet, isDevnetCluster, isLocalCluster, isLocalnet, isMainnet, isMainnetCluster, isNetworkError, isPolyfillInstalled, isTestnet, isTestnetCluster, isTransactionError, isTransactionSignerError, isValidationError, normalizeNetwork, toClusterId, toConnectorError, truncate, withErrorBoundary };
2522
+ //# sourceMappingURL=chunk-APQGEW7S.mjs.map
2523
+ //# sourceMappingURL=chunk-APQGEW7S.mjs.map