@solana/connector 0.1.9 → 0.2.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/README.md +403 -50
- package/dist/chunk-4KD6HQQG.js +69 -0
- package/dist/chunk-4KD6HQQG.js.map +1 -0
- package/dist/chunk-BJAVJQLK.js +230 -0
- package/dist/chunk-BJAVJQLK.js.map +1 -0
- package/dist/{chunk-5HRJKCIL.js → chunk-BZ2VBJCZ.js} +1061 -424
- package/dist/chunk-BZ2VBJCZ.js.map +1 -0
- package/dist/{chunk-WDXEP4AJ.js → chunk-EM4KNOKG.js} +658 -190
- package/dist/chunk-EM4KNOKG.js.map +1 -0
- package/dist/chunk-HN5AJF7F.js +507 -0
- package/dist/chunk-HN5AJF7F.js.map +1 -0
- package/dist/chunk-HO6QNKFM.mjs +61 -0
- package/dist/chunk-HO6QNKFM.mjs.map +1 -0
- package/dist/chunk-HPQ5T32K.mjs +178 -0
- package/dist/chunk-HPQ5T32K.mjs.map +1 -0
- package/dist/{chunk-MAXA3HEP.mjs → chunk-IDTUFDNB.mjs} +962 -344
- package/dist/chunk-IDTUFDNB.mjs.map +1 -0
- package/dist/{chunk-P5LXUDP6.mjs → chunk-RTXUS5KG.mjs} +579 -119
- package/dist/chunk-RTXUS5KG.mjs.map +1 -0
- package/dist/{chunk-DSUCH44G.js → chunk-SITQ4JWM.js} +23 -67
- package/dist/chunk-SITQ4JWM.js.map +1 -0
- package/dist/chunk-UCISIAOG.mjs +501 -0
- package/dist/chunk-UCISIAOG.mjs.map +1 -0
- package/dist/{chunk-J7DHGLW6.mjs → chunk-ZZTY3O4N.mjs} +21 -61
- package/dist/chunk-ZZTY3O4N.mjs.map +1 -0
- package/dist/compat.d.mts +1 -1
- package/dist/compat.d.ts +1 -1
- package/dist/compat.js +10 -9
- package/dist/compat.js.map +1 -1
- package/dist/compat.mjs +2 -1
- package/dist/compat.mjs.map +1 -1
- package/dist/headless.d.mts +239 -104
- package/dist/headless.d.ts +239 -104
- package/dist/headless.js +255 -169
- package/dist/headless.mjs +5 -3
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +316 -206
- package/dist/index.mjs +6 -4
- package/dist/react.d.mts +299 -9
- package/dist/react.d.ts +299 -9
- package/dist/react.js +90 -38
- package/dist/react.mjs +2 -2
- package/dist/{standard-shim-CT49DM5l.d.mts → standard-shim-CGB88PPO.d.mts} +673 -52
- package/dist/{standard-shim-D9guL5fz.d.ts → standard-shim-tmnQelaJ.d.ts} +673 -52
- package/dist/{transaction-signer-T-KVQFi8.d.mts → transaction-signer-7NaYmP5w.d.mts} +1 -0
- package/dist/{transaction-signer-T-KVQFi8.d.ts → transaction-signer-7NaYmP5w.d.ts} +1 -0
- package/dist/walletconnect-447EY3OJ.js +28 -0
- package/dist/walletconnect-447EY3OJ.js.map +1 -0
- package/dist/walletconnect-U455PO4I.mjs +3 -0
- package/dist/walletconnect-U455PO4I.mjs.map +1 -0
- package/package.json +6 -2
- package/dist/chunk-5HRJKCIL.js.map +0 -1
- package/dist/chunk-DSUCH44G.js.map +0 -1
- package/dist/chunk-I6TJLYNA.js +0 -535
- package/dist/chunk-I6TJLYNA.js.map +0 -1
- package/dist/chunk-J7DHGLW6.mjs.map +0 -1
- package/dist/chunk-JOBLG62A.mjs +0 -476
- package/dist/chunk-JOBLG62A.mjs.map +0 -1
- package/dist/chunk-MAXA3HEP.mjs.map +0 -1
- package/dist/chunk-P5LXUDP6.mjs.map +0 -1
- package/dist/chunk-WDXEP4AJ.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/core/try-catch.ts","../src/utils/transaction-format.ts"],"names":[],"mappings":";;;AAoEA,eAAsB,SAAuB,OAAA,EAA4C;AACrF,EAAA,IAAI;AAEA,IAAA,OAAO,EAAE,IAAA,EADI,MAAM,OAAA,EACJ,OAAO,IAAA,EAAK;AAAA,EAC/B,SAAS,KAAA,EAAO;AACZ,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAkB;AAAA,EAC3C;AACJ;AAkBO,SAAS,aAA2B,EAAA,EAA2B;AAClE,EAAA,IAAI;AAEA,IAAA,OAAO,EAAE,IAAA,EADI,EAAA,EAAG,EACD,OAAO,IAAA,EAAK;AAAA,EAC/B,SAAS,KAAA,EAAO;AACZ,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAkB;AAAA,EAC3C;AACJ;AAKO,SAAS,UAAgB,MAAA,EAA4C;AACxE,EAAA,OAAO,OAAO,KAAA,KAAU,IAAA;AAC5B;AAKO,SAAS,UAAgB,MAAA,EAA4C;AACxE,EAAA,OAAO,OAAO,KAAA,KAAU,IAAA;AAC5B;;;AC7FO,SAAS,oBAAoB,EAAA,EAAuD;AAEvF,EAAA,OAAO,EAAA,KAAO,QAAQ,OAAO,EAAA,IAAO,YAAY,WAAA,IAAe,EAAA,IAAM,OAAO,EAAA,CAAG,SAAA,IAAc,UAAA;AACjG;AASO,SAAS,qBAAqB,EAAA,EAAmC;AAEpE,EAAA,IAAI,oBAAoB,EAAE,CAAA;AACtB,IAAA,OAAO,GAAG,SAAA,CAAU;AAAA,MAChB,oBAAA,EAAsB,KAAA;AAAA,MACtB,gBAAA,EAAkB;AAAA,KACrB,CAAA;AAIL,EAAA,IAAI,EAAA,YAAc,UAAA;AACd,IAAA,OAAO,EAAA;AAIX,EAAA,IAAI,WAAA,CAAY,OAAO,EAAE,CAAA;AACrB,IAAA,OAAO,IAAI,UAAA,CAAW,EAAA,CAAG,QAAQ,EAAA,CAAG,UAAA,EAAY,GAAG,UAAU,CAAA;AAGjE,EAAA,MAAM,IAAI,MAAM,2FAA2F,CAAA;AAC/G;AASA,SAAS,oBAAoB,KAAA,EAA4B;AACrD,EAAA,OAAI,MAAM,MAAA,KAAW,CAAA,GAAU,SAEvB,KAAA,CAAM,CAAC,IAAI,GAAA,MAAU,CAAA;AACjC;AAUA,eAAsB,+BAA+B,KAAA,EAAgE;AACjH,EAAA,IAAI,mBAAA,CAAoB,KAAK,CAAA,EAAG;AAE5B,IAAA,IAAM,EAAE,WAAA,EAAY,GAAI,MAAM,OAAO,iBAAiB,CAAA;AACtD,IAAA,OAAO,WAAA,CAAY,KAAK,KAAK,CAAA;AAAA,EACjC,CAAA,MAAO;AAEH,IAAA,IAAM,EAAE,oBAAA,EAAqB,GAAI,MAAM,OAAO,iBAAiB,CAAA;AAC/D,IAAA,OAAO,oBAAA,CAAqB,YAAY,KAAK,CAAA;AAAA,EACjD;AACJ;AASO,SAAS,4BAA4B,EAAA,EAAuE;AAC/G,EAAA,IAAM,SAAA,GAAY,oBAAoB,EAAE,CAAA;AAExC,EAAA,OAAO,EAAE,UAAA,EADU,oBAAA,CAAqB,EAAE,GACrB,SAAA,EAAU;AACnC;AAUA,eAAsB,wBAAA,CAClB,aACA,SAAA,EACwD;AACxD,EAAA,OAAI,SAAA,GACO,MAAM,8BAAA,CAA+B,WAAW,CAAA,GAEpD,WAAA;AACX","file":"chunk-4KD6HQQG.js","sourcesContent":["/**\n * @solana/connector - Try-Catch Utility\n *\n * Provides a consistent pattern for async error handling,\n * returning a Result type instead of throwing errors.\n */\n\n/**\n * Represents a failed operation\n */\nexport interface Failure<E> {\n data: null;\n error: E;\n}\n\n/**\n * Represents a successful operation\n */\nexport interface Success<T> {\n data: T;\n error: null;\n}\n\n/**\n * Result type that is either a Success or Failure\n */\nexport type Result<T, E = Error> = Success<T> | Failure<E>;\n\n/**\n * Wraps an async operation and returns a Result instead of throwing.\n * This enables consistent error handling without nested try/catch blocks.\n *\n * @param promise - The promise to wrap\n * @returns A Result containing either the data or an error\n *\n * @example Basic usage\n * ```typescript\n * const { data, error } = await tryCatch(fetchData());\n * if (error) {\n * console.error('Failed:', error.message);\n * return;\n * }\n * console.log('Success:', data);\n * ```\n *\n * @example With typed errors\n * ```typescript\n * const { data, error } = await tryCatch<User, ApiError>(api.getUser(id));\n * if (error) {\n * // error is typed as ApiError\n * handleApiError(error);\n * return;\n * }\n * // data is typed as User\n * displayUser(data);\n * ```\n *\n * @example Chaining operations\n * ```typescript\n * const { data: user, error: userError } = await tryCatch(getUser(id));\n * if (userError) return handleError(userError);\n *\n * const { data: posts, error: postsError } = await tryCatch(getPosts(user.id));\n * if (postsError) return handleError(postsError);\n *\n * return { user, posts };\n * ```\n */\nexport async function tryCatch<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>> {\n try {\n const data = await promise;\n return { data, error: null };\n } catch (error) {\n return { data: null, error: error as E };\n }\n}\n\n/**\n * Synchronous version of tryCatch for non-async operations\n *\n * @param fn - The function to execute\n * @returns A Result containing either the return value or an error\n *\n * @example\n * ```typescript\n * const { data, error } = tryCatchSync(() => JSON.parse(jsonString));\n * if (error) {\n * console.error('Invalid JSON:', error.message);\n * return defaultValue;\n * }\n * return data;\n * ```\n */\nexport function tryCatchSync<T, E = Error>(fn: () => T): Result<T, E> {\n try {\n const data = fn();\n return { data, error: null };\n } catch (error) {\n return { data: null, error: error as E };\n }\n}\n\n/**\n * Type guard to check if a Result is a Success\n */\nexport function isSuccess<T, E>(result: Result<T, E>): result is Success<T> {\n return result.error === null;\n}\n\n/**\n * Type guard to check if a Result is a Failure\n */\nexport function isFailure<T, E>(result: Result<T, E>): result is Failure<E> {\n return result.error !== null;\n}\n","/**\n * Transaction Format Utilities\n *\n * Utilities for detecting and converting between different transaction formats:\n * - web3.js Transaction/VersionedTransaction objects\n * - Serialized Uint8Array (Wallet Standard format)\n * - Other TypedArray formats\n *\n * Note: Uses dynamic imports for @solana/web3.js to avoid bundling it\n * since it's only needed for the compat layer.\n */\n\nimport type { Transaction, VersionedTransaction } from '@solana/web3.js';\nimport type { SolanaTransaction } from '../types/transactions';\n\n/**\n * Check if a value is a web3.js Transaction or VersionedTransaction object\n *\n * @param tx - Value to check\n * @returns True if it's a web3.js transaction object\n */\nexport function isWeb3jsTransaction(tx: unknown): tx is Transaction | VersionedTransaction {\n // Duck-typing: if it has a serialize method, it's likely a web3.js transaction\n return tx !== null && typeof tx === 'object' && 'serialize' in tx && typeof tx.serialize === 'function';\n}\n\n/**\n * Serialize a transaction to Uint8Array format (required for Wallet Standard)\n *\n * @param tx - Transaction to serialize (web3.js object, Uint8Array, or TypedArray)\n * @returns Serialized transaction bytes\n * @throws Error if transaction format is unsupported\n */\nexport function serializeTransaction(tx: SolanaTransaction): Uint8Array {\n // web3.js Transaction/VersionedTransaction object\n if (isWeb3jsTransaction(tx)) {\n return tx.serialize({\n requireAllSignatures: false,\n verifySignatures: false,\n });\n }\n\n // Already serialized as Uint8Array\n if (tx instanceof Uint8Array) {\n return tx;\n }\n\n // Other TypedArray format\n if (ArrayBuffer.isView(tx)) {\n return new Uint8Array(tx.buffer, tx.byteOffset, tx.byteLength);\n }\n\n throw new Error('Unsupported transaction format - must be Transaction, VersionedTransaction, or Uint8Array');\n}\n\n/**\n * Check if transaction bytes represent a legacy transaction\n * Legacy transactions have high bit = 0, versioned have high bit = 1\n *\n * @param bytes - Serialized transaction bytes\n * @returns True if legacy transaction\n */\nfunction isLegacyTransaction(bytes: Uint8Array): boolean {\n if (bytes.length === 0) return false;\n // High bit of first byte: 0 = legacy, 1 = versioned\n return (bytes[0] & 0x80) === 0;\n}\n\n/**\n * Deserialize bytes to a web3.js Transaction or VersionedTransaction object\n * Uses dynamic import to avoid bundling @solana/web3.js\n * Automatically detects legacy vs versioned format\n *\n * @param bytes - Serialized transaction bytes\n * @returns Transaction or VersionedTransaction object\n */\nexport async function deserializeToWeb3jsTransaction(bytes: Uint8Array): Promise<Transaction | VersionedTransaction> {\n if (isLegacyTransaction(bytes)) {\n // Legacy transaction - use Transaction.deserialize to preserve legacy-only fields\n const { Transaction } = await import('@solana/web3.js');\n return Transaction.from(bytes);\n } else {\n // Versioned transaction\n const { VersionedTransaction } = await import('@solana/web3.js');\n return VersionedTransaction.deserialize(bytes);\n }\n}\n\n/**\n * Smart converter that preserves the original format\n * Converts to Wallet Standard format (Uint8Array) and tracks original type\n *\n * @param tx - Transaction in any supported format\n * @returns Object with serialized bytes and format flag\n */\nexport function prepareTransactionForWallet(tx: SolanaTransaction): { serialized: Uint8Array; wasWeb3js: boolean } {\n const wasWeb3js = isWeb3jsTransaction(tx);\n const serialized = serializeTransaction(tx);\n return { serialized, wasWeb3js };\n}\n\n/**\n * Convert signed transaction bytes back to original format if needed\n *\n * @param signedBytes - Signed transaction as Uint8Array\n * @param wasWeb3js - Whether the original was a web3.js object\n * @returns Transaction in appropriate format (async if conversion needed)\n * Returns Transaction for legacy, VersionedTransaction for versioned, or Uint8Array if not web3js\n */\nexport async function convertSignedTransaction(\n signedBytes: Uint8Array,\n wasWeb3js: boolean,\n): Promise<Transaction | VersionedTransaction | Uint8Array> {\n if (wasWeb3js) {\n return await deserializeToWeb3jsTransaction(signedBytes);\n }\n return signedBytes;\n}\n"]}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkBZ2VBJCZ_js = require('./chunk-BZ2VBJCZ.js');
|
|
4
|
+
var chunkSITQ4JWM_js = require('./chunk-SITQ4JWM.js');
|
|
5
|
+
var core = require('@wallet-ui/core');
|
|
6
|
+
var signers = require('@solana/signers');
|
|
7
|
+
var addresses = require('@solana/addresses');
|
|
8
|
+
|
|
9
|
+
// src/types/wallets.ts
|
|
10
|
+
function isWalletName(value) {
|
|
11
|
+
return typeof value == "string" && value.length > 0;
|
|
12
|
+
}
|
|
13
|
+
function isAccountAddress(value) {
|
|
14
|
+
return typeof value == "string" && value.length >= 32 && value.length <= 44;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/lib/connection/types.ts
|
|
18
|
+
function isLegacyConnection(conn) {
|
|
19
|
+
return "rpcEndpoint" in conn && typeof conn.rpcEndpoint == "string";
|
|
20
|
+
}
|
|
21
|
+
function isKitConnection(conn) {
|
|
22
|
+
if ("rpcEndpoint" in conn)
|
|
23
|
+
return false;
|
|
24
|
+
let asKitRpc = conn;
|
|
25
|
+
return typeof asKitRpc.getLatestBlockhash == "function" && typeof asKitRpc.sendTransaction == "function";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/lib/connection/helpers.ts
|
|
29
|
+
async function getLatestBlockhash(connection, commitment = "confirmed") {
|
|
30
|
+
if (isLegacyConnection(connection))
|
|
31
|
+
return await connection.getLatestBlockhash(commitment);
|
|
32
|
+
if (isKitConnection(connection))
|
|
33
|
+
return (await connection.getLatestBlockhash({ commitment }).send()).value;
|
|
34
|
+
throw new Error("Unsupported connection type");
|
|
35
|
+
}
|
|
36
|
+
async function sendRawTransaction(connection, bytes, options) {
|
|
37
|
+
if (isLegacyConnection(connection))
|
|
38
|
+
return await connection.sendRawTransaction(bytes, options);
|
|
39
|
+
if (isKitConnection(connection)) {
|
|
40
|
+
let rpc = connection, base64String = Buffer.from(bytes).toString("base64");
|
|
41
|
+
return await rpc.sendTransaction(base64String, {
|
|
42
|
+
...options?.commitment ? { commitment: options.commitment } : {},
|
|
43
|
+
...options?.skipPreflight !== void 0 ? { skipPreflight: options.skipPreflight } : {},
|
|
44
|
+
...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
|
|
45
|
+
}).send();
|
|
46
|
+
}
|
|
47
|
+
throw new Error("Unsupported connection type");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/utils/chain.ts
|
|
51
|
+
var SOLANA_CHAIN_IDS = {
|
|
52
|
+
mainnet: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
53
|
+
devnet: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
|
|
54
|
+
testnet: "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"
|
|
55
|
+
}, CHAIN_ID_TO_CLUSTER_TYPE = {
|
|
56
|
+
[SOLANA_CHAIN_IDS.mainnet]: "mainnet",
|
|
57
|
+
[SOLANA_CHAIN_IDS.devnet]: "devnet",
|
|
58
|
+
[SOLANA_CHAIN_IDS.testnet]: "testnet"
|
|
59
|
+
}, CLUSTER_ID_TO_CHAIN_ID = {
|
|
60
|
+
"solana:mainnet": SOLANA_CHAIN_IDS.mainnet,
|
|
61
|
+
"solana:mainnet-beta": SOLANA_CHAIN_IDS.mainnet,
|
|
62
|
+
"solana:devnet": SOLANA_CHAIN_IDS.devnet,
|
|
63
|
+
"solana:testnet": SOLANA_CHAIN_IDS.testnet
|
|
64
|
+
};
|
|
65
|
+
function getChainIdFromCluster(cluster) {
|
|
66
|
+
let clusterType = chunkBZ2VBJCZ_js.getClusterType(cluster);
|
|
67
|
+
return clusterType === "localnet" || clusterType === "custom" ? null : getChainIdFromClusterType(clusterType);
|
|
68
|
+
}
|
|
69
|
+
function getChainIdFromClusterId(clusterId) {
|
|
70
|
+
return CLUSTER_ID_TO_CHAIN_ID[clusterId] || null;
|
|
71
|
+
}
|
|
72
|
+
function getChainIdFromClusterType(type) {
|
|
73
|
+
switch (type) {
|
|
74
|
+
case "mainnet":
|
|
75
|
+
return SOLANA_CHAIN_IDS.mainnet;
|
|
76
|
+
case "devnet":
|
|
77
|
+
return SOLANA_CHAIN_IDS.devnet;
|
|
78
|
+
case "testnet":
|
|
79
|
+
return SOLANA_CHAIN_IDS.testnet;
|
|
80
|
+
case "localnet":
|
|
81
|
+
case "custom":
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function getClusterTypeFromChainId(chainId) {
|
|
86
|
+
return CHAIN_ID_TO_CLUSTER_TYPE[chainId] || null;
|
|
87
|
+
}
|
|
88
|
+
function getClusterIdFromChainId(chainId) {
|
|
89
|
+
let clusterType = getClusterTypeFromChainId(chainId);
|
|
90
|
+
if (!clusterType)
|
|
91
|
+
return null;
|
|
92
|
+
switch (clusterType) {
|
|
93
|
+
case "mainnet":
|
|
94
|
+
return "solana:mainnet";
|
|
95
|
+
case "devnet":
|
|
96
|
+
return "solana:devnet";
|
|
97
|
+
case "testnet":
|
|
98
|
+
return "solana:testnet";
|
|
99
|
+
default:
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function isSolanaChain(chain) {
|
|
104
|
+
return chain.startsWith("solana:");
|
|
105
|
+
}
|
|
106
|
+
function isKnownSolanaChain(chain) {
|
|
107
|
+
return chain === SOLANA_CHAIN_IDS.mainnet || chain === SOLANA_CHAIN_IDS.devnet || chain === SOLANA_CHAIN_IDS.testnet;
|
|
108
|
+
}
|
|
109
|
+
function validateKnownSolanaChain(chain) {
|
|
110
|
+
if (!isSolanaChain(chain))
|
|
111
|
+
throw new Error(`Invalid chain format: expected 'solana:...', got '${chain}'`);
|
|
112
|
+
if (!isKnownSolanaChain(chain))
|
|
113
|
+
throw new Error(`Unknown Solana chain: ${chain}. Known chains: ${Object.values(SOLANA_CHAIN_IDS).join(", ")}`);
|
|
114
|
+
}
|
|
115
|
+
function getClusterTypeFromConnection(connection) {
|
|
116
|
+
if (!connection)
|
|
117
|
+
return null;
|
|
118
|
+
let rpcUrl = connection.rpcEndpoint || "";
|
|
119
|
+
return rpcUrl.includes("mainnet") || rpcUrl.includes("api.mainnet-beta") ? "mainnet" : rpcUrl.includes("testnet") ? "testnet" : rpcUrl.includes("devnet") ? "devnet" : rpcUrl.includes("localhost") || rpcUrl.includes("127.0.0.1") ? "localnet" : "custom";
|
|
120
|
+
}
|
|
121
|
+
function getChainIdFromConnection(connection, network) {
|
|
122
|
+
if (network)
|
|
123
|
+
return getChainIdFromClusterType(network);
|
|
124
|
+
let clusterType = getClusterTypeFromConnection(connection);
|
|
125
|
+
return clusterType ? getChainIdFromClusterType(clusterType) : null;
|
|
126
|
+
}
|
|
127
|
+
function clusterToChainId(cluster) {
|
|
128
|
+
return getChainIdFromCluster(cluster);
|
|
129
|
+
}
|
|
130
|
+
function chainIdToClusterType(chainId) {
|
|
131
|
+
return getClusterTypeFromChainId(chainId);
|
|
132
|
+
}
|
|
133
|
+
function chainIdToClusterId(chainId) {
|
|
134
|
+
return getClusterIdFromChainId(chainId);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/lib/utils/explorer-urls.ts
|
|
138
|
+
function getSolanaExplorerUrl(signature, options = {}) {
|
|
139
|
+
let { cluster = "mainnet", customUrl } = options, normalizedCluster = cluster === "mainnet-beta" ? "mainnet" : cluster;
|
|
140
|
+
if (normalizedCluster === "localnet")
|
|
141
|
+
return `https://explorer.solana.com/tx/${signature}?cluster=custom&customUrl=${encodeURIComponent(customUrl || "http://localhost:8899")}`;
|
|
142
|
+
let explorerCluster = ["mainnet", "devnet", "testnet"].includes(normalizedCluster) ? normalizedCluster : "devnet";
|
|
143
|
+
return chunkSITQ4JWM_js.getExplorerLink({
|
|
144
|
+
transaction: signature,
|
|
145
|
+
cluster: explorerCluster
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function getSolscanUrl(signature, options = {}) {
|
|
149
|
+
let { cluster = "mainnet" } = options, normalizedCluster = cluster === "mainnet-beta" ? "mainnet" : cluster;
|
|
150
|
+
return normalizedCluster === "mainnet" ? `https://solscan.io/tx/${signature}` : normalizedCluster === "localnet" ? `https://solscan.io/tx/${signature}?cluster=custom` : `https://solscan.io/tx/${signature}?cluster=${normalizedCluster}`;
|
|
151
|
+
}
|
|
152
|
+
function getXrayUrl(signature) {
|
|
153
|
+
return `https://xray.helius.xyz/tx/${signature}`;
|
|
154
|
+
}
|
|
155
|
+
function getSolanaFmUrl(signature, options = {}) {
|
|
156
|
+
let { cluster = "mainnet" } = options, normalizedCluster = cluster === "mainnet-beta" ? "mainnet" : cluster;
|
|
157
|
+
return normalizedCluster === "mainnet" ? `https://solana.fm/tx/${signature}` : `https://solana.fm/tx/${signature}?cluster=${normalizedCluster}`;
|
|
158
|
+
}
|
|
159
|
+
function getAllExplorerUrls(signature, options = {}) {
|
|
160
|
+
return {
|
|
161
|
+
"solana-explorer": getSolanaExplorerUrl(signature, options),
|
|
162
|
+
solscan: getSolscanUrl(signature, options),
|
|
163
|
+
xray: getXrayUrl(signature),
|
|
164
|
+
"solana-fm": getSolanaFmUrl(signature, options)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function formatSignature(signature, chars = 8) {
|
|
168
|
+
return signature.length <= chars * 2 ? signature : `${signature.slice(0, chars)}...${signature.slice(-chars)}`;
|
|
169
|
+
}
|
|
170
|
+
async function copySignature(signature) {
|
|
171
|
+
try {
|
|
172
|
+
return await navigator.clipboard.writeText(signature), true;
|
|
173
|
+
} catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Object.defineProperty(exports, "createSolanaDevnet", {
|
|
179
|
+
enumerable: true,
|
|
180
|
+
get: function () { return core.createSolanaDevnet; }
|
|
181
|
+
});
|
|
182
|
+
Object.defineProperty(exports, "createSolanaLocalnet", {
|
|
183
|
+
enumerable: true,
|
|
184
|
+
get: function () { return core.createSolanaLocalnet; }
|
|
185
|
+
});
|
|
186
|
+
Object.defineProperty(exports, "createSolanaMainnet", {
|
|
187
|
+
enumerable: true,
|
|
188
|
+
get: function () { return core.createSolanaMainnet; }
|
|
189
|
+
});
|
|
190
|
+
Object.defineProperty(exports, "createSolanaTestnet", {
|
|
191
|
+
enumerable: true,
|
|
192
|
+
get: function () { return core.createSolanaTestnet; }
|
|
193
|
+
});
|
|
194
|
+
Object.defineProperty(exports, "createSignableMessage", {
|
|
195
|
+
enumerable: true,
|
|
196
|
+
get: function () { return signers.createSignableMessage; }
|
|
197
|
+
});
|
|
198
|
+
Object.defineProperty(exports, "address", {
|
|
199
|
+
enumerable: true,
|
|
200
|
+
get: function () { return addresses.address; }
|
|
201
|
+
});
|
|
202
|
+
exports.SOLANA_CHAIN_IDS = SOLANA_CHAIN_IDS;
|
|
203
|
+
exports.chainIdToClusterId = chainIdToClusterId;
|
|
204
|
+
exports.chainIdToClusterType = chainIdToClusterType;
|
|
205
|
+
exports.clusterToChainId = clusterToChainId;
|
|
206
|
+
exports.copySignature = copySignature;
|
|
207
|
+
exports.formatSignature = formatSignature;
|
|
208
|
+
exports.getAllExplorerUrls = getAllExplorerUrls;
|
|
209
|
+
exports.getChainIdFromCluster = getChainIdFromCluster;
|
|
210
|
+
exports.getChainIdFromClusterId = getChainIdFromClusterId;
|
|
211
|
+
exports.getChainIdFromClusterType = getChainIdFromClusterType;
|
|
212
|
+
exports.getChainIdFromConnection = getChainIdFromConnection;
|
|
213
|
+
exports.getClusterIdFromChainId = getClusterIdFromChainId;
|
|
214
|
+
exports.getClusterTypeFromChainId = getClusterTypeFromChainId;
|
|
215
|
+
exports.getClusterTypeFromConnection = getClusterTypeFromConnection;
|
|
216
|
+
exports.getLatestBlockhash = getLatestBlockhash;
|
|
217
|
+
exports.getSolanaExplorerUrl = getSolanaExplorerUrl;
|
|
218
|
+
exports.getSolanaFmUrl = getSolanaFmUrl;
|
|
219
|
+
exports.getSolscanUrl = getSolscanUrl;
|
|
220
|
+
exports.getXrayUrl = getXrayUrl;
|
|
221
|
+
exports.isAccountAddress = isAccountAddress;
|
|
222
|
+
exports.isKitConnection = isKitConnection;
|
|
223
|
+
exports.isKnownSolanaChain = isKnownSolanaChain;
|
|
224
|
+
exports.isLegacyConnection = isLegacyConnection;
|
|
225
|
+
exports.isSolanaChain = isSolanaChain;
|
|
226
|
+
exports.isWalletName = isWalletName;
|
|
227
|
+
exports.sendRawTransaction = sendRawTransaction;
|
|
228
|
+
exports.validateKnownSolanaChain = validateKnownSolanaChain;
|
|
229
|
+
//# sourceMappingURL=chunk-BJAVJQLK.js.map
|
|
230
|
+
//# sourceMappingURL=chunk-BJAVJQLK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/wallets.ts","../src/lib/connection/types.ts","../src/lib/connection/helpers.ts","../src/utils/chain.ts","../src/lib/utils/explorer-urls.ts"],"names":["getClusterType","getExplorerLink"],"mappings":"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","file":"chunk-BJAVJQLK.js","sourcesContent":["/**\n * Wallet-related types\n * Re-exports from @wallet-standard/base and custom wallet types\n */\n\nimport type { Wallet, WalletAccount } from '@wallet-standard/base';\n\n// Re-export standard types\nexport type { Wallet, WalletAccount };\n\n/**\n * Wallet name as a branded string for type safety\n * Represents the unique identifier for a wallet (e.g., \"Phantom\", \"Solflare\")\n */\nexport type WalletName = string & { readonly __brand: 'WalletName' };\n\n/**\n * Account address as a branded string for type safety\n * Represents a Solana address (base58-encoded public key)\n *\n * @deprecated Use `Address` from '@solana/addresses' instead for consistent address typing\n */\nexport type AccountAddress = string & { readonly __brand: 'AccountAddress' };\n\n/**\n * Type guard to check if a string is a valid wallet name\n */\nexport function isWalletName(value: string): value is WalletName {\n return typeof value === 'string' && value.length > 0;\n}\n\n/**\n * Type guard to check if a string is a valid account address\n *\n * @deprecated Use `isAddress` from '@solana/addresses' instead for proper address validation\n */\nexport function isAccountAddress(value: string): value is AccountAddress {\n // Basic validation: Solana addresses are typically 32-44 characters\n return typeof value === 'string' && value.length >= 32 && value.length <= 44;\n}\n\n/**\n * Extended wallet information with capability metadata\n */\nexport interface WalletInfo {\n /** The Wallet Standard wallet object */\n wallet: Wallet;\n /** Whether the wallet extension is installed */\n installed: boolean;\n /** Precomputed capability flag for UI convenience */\n connectable?: boolean;\n}\n","import type { Connection } from '@solana/web3.js';\n\nexport type Commitment = 'processed' | 'confirmed' | 'finalized';\n\nexport interface KitSendTransactionOptions {\n commitment?: Commitment;\n skipPreflight?: boolean;\n maxRetries?: number;\n}\n\nexport type KitRpc = {\n getLatestBlockhash(options?: { commitment?: Commitment }): {\n send(): Promise<{ value: { blockhash: string; lastValidBlockHeight: number } }>;\n };\n sendTransaction(\n bytes: Uint8Array | string,\n options?: KitSendTransactionOptions,\n ): {\n send(): Promise<string>;\n };\n send?: () => unknown;\n};\n\nexport type DualConnection = Connection | KitRpc;\n\nexport function isLegacyConnection(conn: DualConnection): conn is Connection {\n return 'rpcEndpoint' in conn && typeof (conn as Connection).rpcEndpoint === 'string';\n}\n\nexport function isKitConnection(conn: DualConnection): conn is KitRpc {\n if ('rpcEndpoint' in conn) {\n return false;\n }\n\n const asKitRpc = conn as KitRpc;\n return typeof asKitRpc.getLatestBlockhash === 'function' && typeof asKitRpc.sendTransaction === 'function';\n}\n","/**\n * @solana/connector - Connection Helpers\n *\n * Abstraction layer for working with both legacy @solana/web3.js Connection\n * and modern Kit/gill Rpc objects.\n */\n\nimport type { SendOptions } from '@solana/web3.js';\nimport type { DualConnection, Commitment, KitRpc } from './types';\nimport { isLegacyConnection, isKitConnection } from './types';\n\n/**\n * Get latest blockhash from either legacy Connection or Kit Rpc\n *\n * Abstracts the differences between web3.js 1.x and Kit/gill APIs.\n *\n * @param connection - Legacy Connection or Kit Rpc\n * @param commitment - Optional commitment level (default: 'confirmed')\n * @returns Latest blockhash and last valid block height\n *\n * @example\n * ```typescript\n * // Works with both Connection and Rpc\n * const { blockhash, lastValidBlockHeight } = await getLatestBlockhash(connection);\n * ```\n */\nexport async function getLatestBlockhash(\n connection: DualConnection,\n commitment: Commitment = 'confirmed',\n): Promise<{ blockhash: string; lastValidBlockHeight: number }> {\n if (isLegacyConnection(connection)) {\n // Legacy Connection API\n return await connection.getLatestBlockhash(commitment);\n }\n\n if (isKitConnection(connection)) {\n // Kit/gill Rpc API - returns { value: { blockhash, lastValidBlockHeight } }\n const rpc = connection as KitRpc;\n const result = await rpc.getLatestBlockhash({ commitment }).send();\n return result.value;\n }\n\n throw new Error('Unsupported connection type');\n}\n\n/**\n * Send raw transaction bytes to either legacy Connection or Kit Rpc\n *\n * Abstracts the differences between web3.js 1.x and Kit/gill APIs.\n *\n * @param connection - Legacy Connection or Kit Rpc\n * @param bytes - Raw transaction bytes\n * @param options - Optional send options (skipPreflight, maxRetries, etc.)\n * @returns Transaction signature string\n *\n * @example\n * ```typescript\n * // Works with both Connection and Rpc\n * const signature = await sendRawTransaction(connection, transactionBytes, {\n * skipPreflight: false,\n * maxRetries: 3\n * });\n * ```\n */\nexport async function sendRawTransaction(\n connection: DualConnection,\n bytes: Uint8Array,\n options?: SendOptions & { commitment?: Commitment },\n): Promise<string> {\n if (isLegacyConnection(connection)) {\n // Legacy Connection API\n return await connection.sendRawTransaction(bytes, options);\n }\n\n if (isKitConnection(connection)) {\n // Kit/gill Rpc API\n // Note: gill's sendTransaction expects different options format\n const rpc = connection as KitRpc;\n // Convert Uint8Array to base64 string\n const base64String = Buffer.from(bytes).toString('base64');\n const result = await rpc\n .sendTransaction(base64String as Uint8Array | string, {\n ...(options?.commitment ? { commitment: options.commitment } : {}),\n ...(options?.skipPreflight !== undefined ? { skipPreflight: options.skipPreflight } : {}),\n ...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),\n })\n .send();\n\n // Kit Rpc returns signature string directly\n return result;\n }\n\n throw new Error('Unsupported connection type');\n}\n","import type { SolanaCluster, SolanaClusterId } from '@wallet-ui/core';\nimport type { Connection } from '@solana/web3.js';\nimport type { ClusterType } from './cluster';\nimport { getClusterType, isMainnetCluster, isDevnetCluster, isTestnetCluster } from './cluster';\n\nexport const SOLANA_CHAIN_IDS = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n} as const;\n\nconst CHAIN_ID_TO_CLUSTER_TYPE: Record<string, ClusterType> = {\n [SOLANA_CHAIN_IDS.mainnet]: 'mainnet',\n [SOLANA_CHAIN_IDS.devnet]: 'devnet',\n [SOLANA_CHAIN_IDS.testnet]: 'testnet',\n};\n\nconst CLUSTER_ID_TO_CHAIN_ID: Partial<Record<SolanaClusterId, string>> = {\n 'solana:mainnet': SOLANA_CHAIN_IDS.mainnet,\n 'solana:mainnet-beta': SOLANA_CHAIN_IDS.mainnet,\n 'solana:devnet': SOLANA_CHAIN_IDS.devnet,\n 'solana:testnet': SOLANA_CHAIN_IDS.testnet,\n};\n\nexport function getChainIdFromCluster(cluster: SolanaCluster): `solana:${string}` | null {\n const clusterType = getClusterType(cluster);\n\n if (clusterType === 'localnet' || clusterType === 'custom') {\n return null;\n }\n\n return getChainIdFromClusterType(clusterType);\n}\n\nexport function getChainIdFromClusterId(clusterId: SolanaClusterId): `solana:${string}` | null {\n return (CLUSTER_ID_TO_CHAIN_ID[clusterId] as `solana:${string}` | undefined) || null;\n}\n\nexport function getChainIdFromClusterType(type: ClusterType): `solana:${string}` | null {\n switch (type) {\n case 'mainnet':\n return SOLANA_CHAIN_IDS.mainnet;\n case 'devnet':\n return SOLANA_CHAIN_IDS.devnet;\n case 'testnet':\n return SOLANA_CHAIN_IDS.testnet;\n case 'localnet':\n case 'custom':\n return null;\n }\n}\n\nexport function getClusterTypeFromChainId(chainId: string): ClusterType | null {\n return CHAIN_ID_TO_CLUSTER_TYPE[chainId] || null;\n}\n\nexport function getClusterIdFromChainId(chainId: string): SolanaClusterId | null {\n const clusterType = getClusterTypeFromChainId(chainId);\n if (!clusterType) {\n return null;\n }\n\n switch (clusterType) {\n case 'mainnet':\n return 'solana:mainnet';\n case 'devnet':\n return 'solana:devnet';\n case 'testnet':\n return 'solana:testnet';\n default:\n return null;\n }\n}\n\nexport function isSolanaChain(chain: string): chain is `solana:${string}` {\n return chain.startsWith('solana:');\n}\n\nexport function isKnownSolanaChain(chain: string): boolean {\n return (\n chain === SOLANA_CHAIN_IDS.mainnet || chain === SOLANA_CHAIN_IDS.devnet || chain === SOLANA_CHAIN_IDS.testnet\n );\n}\n\nexport function validateKnownSolanaChain(chain: string): asserts chain is `solana:${string}` {\n if (!isSolanaChain(chain)) {\n throw new Error(`Invalid chain format: expected 'solana:...', got '${chain}'`);\n }\n\n if (!isKnownSolanaChain(chain)) {\n throw new Error(`Unknown Solana chain: ${chain}. Known chains: ${Object.values(SOLANA_CHAIN_IDS).join(', ')}`);\n }\n}\n\nexport function getClusterTypeFromConnection(connection: Connection | null): ClusterType | null {\n if (!connection) {\n return null;\n }\n\n const rpcUrl = connection.rpcEndpoint || '';\n\n if (rpcUrl.includes('mainnet') || rpcUrl.includes('api.mainnet-beta')) {\n return 'mainnet';\n }\n\n if (rpcUrl.includes('testnet')) {\n return 'testnet';\n }\n\n if (rpcUrl.includes('devnet')) {\n return 'devnet';\n }\n\n if (rpcUrl.includes('localhost') || rpcUrl.includes('127.0.0.1')) {\n return 'localnet';\n }\n\n return 'custom';\n}\n\nexport function getChainIdFromConnection(\n connection: Connection | null,\n network?: 'mainnet' | 'devnet' | 'testnet',\n): `solana:${string}` | null {\n if (network) {\n return getChainIdFromClusterType(network);\n }\n\n const clusterType = getClusterTypeFromConnection(connection);\n if (!clusterType) {\n return null;\n }\n\n return getChainIdFromClusterType(clusterType);\n}\n\nexport function clusterToChainId(cluster: SolanaCluster): `solana:${string}` | null {\n return getChainIdFromCluster(cluster);\n}\n\nexport function chainIdToClusterType(chainId: string): ClusterType | null {\n return getClusterTypeFromChainId(chainId);\n}\n\nexport function chainIdToClusterId(chainId: string): SolanaClusterId | null {\n return getClusterIdFromChainId(chainId);\n}\n","/**\n * @solana/connector - Explorer URL Utilities\n *\n * Generate URLs for various Solana block explorers to view transactions,\n * accounts, and other on-chain data.\n */\n\nimport { getExplorerLink } from '../kit';\n\nexport type ExplorerType = 'solana-explorer' | 'solscan' | 'xray' | 'solana-fm';\n\nexport interface ExplorerOptions {\n /** Cluster to use for the explorer link */\n cluster?: string;\n /** Custom RPC URL for localnet */\n customUrl?: string;\n}\n\n/**\n * Generate Solana Explorer URL for a transaction signature\n */\nexport function getSolanaExplorerUrl(signature: string, options: ExplorerOptions = {}): string {\n const { cluster = 'mainnet', customUrl } = options;\n const normalizedCluster = cluster === 'mainnet-beta' ? 'mainnet' : cluster;\n\n // Handle localnet with custom URL - gill doesn't support this specific case\n if (normalizedCluster === 'localnet') {\n const url = customUrl || 'http://localhost:8899';\n return `https://explorer.solana.com/tx/${signature}?cluster=custom&customUrl=${encodeURIComponent(url)}`;\n }\n\n // Map to valid gill cluster types (custom clusters default to devnet)\n const validClusters = ['mainnet', 'devnet', 'testnet'] as const;\n const explorerCluster = validClusters.includes(normalizedCluster as 'mainnet' | 'devnet' | 'testnet')\n ? (normalizedCluster as 'mainnet' | 'devnet' | 'testnet')\n : 'devnet';\n\n // Use gill's getExplorerLink for standard clusters\n return getExplorerLink({\n transaction: signature,\n cluster: explorerCluster,\n });\n}\n\n/**\n * Generate Solscan URL for a transaction signature\n */\nexport function getSolscanUrl(signature: string, options: ExplorerOptions = {}): string {\n const { cluster = 'mainnet' } = options;\n const normalizedCluster = cluster === 'mainnet-beta' ? 'mainnet' : cluster;\n\n if (normalizedCluster === 'mainnet') {\n return `https://solscan.io/tx/${signature}`;\n }\n\n if (normalizedCluster === 'localnet') {\n return `https://solscan.io/tx/${signature}?cluster=custom`;\n }\n\n return `https://solscan.io/tx/${signature}?cluster=${normalizedCluster}`;\n}\n\n/**\n * Generate XRAY (Helius) URL for a transaction signature\n * Note: XRAY works best with mainnet transactions\n */\nexport function getXrayUrl(signature: string): string {\n return `https://xray.helius.xyz/tx/${signature}`;\n}\n\n/**\n * Generate SolanaFM URL for a transaction signature\n */\nexport function getSolanaFmUrl(signature: string, options: ExplorerOptions = {}): string {\n const { cluster = 'mainnet' } = options;\n const normalizedCluster = cluster === 'mainnet-beta' ? 'mainnet' : cluster;\n\n if (normalizedCluster === 'mainnet') {\n return `https://solana.fm/tx/${signature}`;\n }\n\n return `https://solana.fm/tx/${signature}?cluster=${normalizedCluster}`;\n}\n\n/**\n * Get all explorer URLs for a transaction\n */\nexport function getAllExplorerUrls(signature: string, options: ExplorerOptions = {}): Record<ExplorerType, string> {\n return {\n 'solana-explorer': getSolanaExplorerUrl(signature, options),\n solscan: getSolscanUrl(signature, options),\n xray: getXrayUrl(signature),\n 'solana-fm': getSolanaFmUrl(signature, options),\n };\n}\n\n/**\n * Format a transaction signature for display (truncated)\n */\nexport function formatSignature(signature: string, chars = 8): string {\n if (signature.length <= chars * 2) return signature;\n return `${signature.slice(0, chars)}...${signature.slice(-chars)}`;\n}\n\n/**\n * Copy signature to clipboard with enhanced error handling\n *\n * @deprecated Use copySignatureToClipboard from utils/clipboard instead\n * This is maintained for backwards compatibility but will be removed in a future version\n */\nexport async function copySignature(signature: string): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(signature);\n return true;\n } catch {\n return false;\n }\n}\n"]}
|