@k256/sdk 0.1.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/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/index.cjs +949 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +938 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.cjs +14 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +202 -0
- package/dist/types/index.d.ts +202 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +70 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +48 -0
- package/dist/utils/index.d.ts +48 -0
- package/dist/utils/index.js +66 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/ws/index.cjs +896 -0
- package/dist/ws/index.cjs.map +1 -0
- package/dist/ws/index.d.cts +516 -0
- package/dist/ws/index.d.ts +516 -0
- package/dist/ws/index.js +889 -0
- package/dist/ws/index.js.map +1 -0
- package/package.json +92 -0
- package/src/index.ts +34 -0
- package/src/types/index.ts +212 -0
- package/src/utils/base58.ts +123 -0
- package/src/utils/index.ts +7 -0
- package/src/ws/client.ts +786 -0
- package/src/ws/decoder.ts +490 -0
- package/src/ws/index.ts +55 -0
- package/src/ws/types.ts +227 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/types/index.ts"],"names":["NetworkState"],"mappings":";AAsIO,IAAK,YAAA,qBAAAA,aAAAA,KAAL;AACL,EAAAA,aAAAA,CAAAA,aAAAA,CAAA,SAAM,CAAA,CAAA,GAAN,KAAA;AACA,EAAAA,aAAAA,CAAAA,aAAAA,CAAA,YAAS,CAAA,CAAA,GAAT,QAAA;AACA,EAAAA,aAAAA,CAAAA,aAAAA,CAAA,UAAO,CAAA,CAAA,GAAP,MAAA;AACA,EAAAA,aAAAA,CAAAA,aAAAA,CAAA,eAAY,CAAA,CAAA,GAAZ,WAAA;AAJU,EAAA,OAAAA,aAAAA;AAAA,CAAA,EAAA,YAAA,IAAA,EAAA","file":"index.js","sourcesContent":["/**\n * Shared type definitions for K256 SDK\n * \n * These types are used across WebSocket and REST API modules.\n * \n * @module @k256/sdk/types\n */\n\n/**\n * Pool state from DEX\n */\nexport interface Pool {\n /** Pool address (Base58) */\n address: string;\n /** Protocol/DEX name */\n protocol: string;\n /** Token mints in the pool (Base58) */\n tokenMints: string[];\n /** Token balances (as strings for precision) */\n tokenBalances: string[];\n /** Token decimals */\n tokenDecimals: number[];\n /** Whether pool is valid for trading */\n isValid: boolean;\n}\n\n/**\n * Real-time pool state update\n */\nexport interface PoolUpdate extends Pool {\n /** Global sequence number (monotonically increasing) */\n sequence: number;\n /** Solana slot when updated */\n slot: number;\n /** Write version within slot */\n writeVersion: number;\n /** Best bid price/size (orderbook pools only) */\n bestBid?: OrderLevel;\n /** Best ask price/size (orderbook pools only) */\n bestAsk?: OrderLevel;\n}\n\n/**\n * Order book level (bid or ask)\n */\nexport interface OrderLevel {\n /** Price in base units (as string for precision) */\n price: string;\n /** Size in base units (as string for precision) */\n size: string;\n}\n\n/**\n * Token metadata\n */\nexport interface Token {\n /** Token mint address (Base58) */\n mint: string;\n /** Token symbol (e.g., \"SOL\", \"USDC\") */\n symbol: string;\n /** Token name */\n name: string;\n /** Decimal places */\n decimals: number;\n /** Logo URL (optional) */\n logoUri?: string;\n /** Coingecko ID (optional) */\n coingeckoId?: string;\n}\n\n/**\n * Swap quote from aggregator\n */\nexport interface Quote {\n /** Input token mint (Base58) */\n inputMint: string;\n /** Output token mint (Base58) */\n outputMint: string;\n /** Input amount (as string for precision) */\n inAmount: string;\n /** Output amount (as string for precision) */\n outAmount: string;\n /** Price impact in basis points */\n priceImpactBps: number;\n /** Slippage in basis points */\n slippageBps: number;\n /** Route plan (DEXes used) */\n routePlan: RoutePlanStep[];\n /** Context slot */\n contextSlot: number;\n /** Algorithm used for routing */\n algorithm: string;\n}\n\n/**\n * Step in a swap route\n */\nexport interface RoutePlanStep {\n /** DEX/protocol name */\n protocol: string;\n /** Pool address (Base58) */\n poolAddress: string;\n /** Input mint for this step */\n inputMint: string;\n /** Output mint for this step */\n outputMint: string;\n /** Percentage of input for this step (0-100) */\n percent: number;\n}\n\n/**\n * Priority fee estimates\n */\nexport interface PriorityFees {\n /** Current slot */\n slot: number;\n /** Timestamp in milliseconds */\n timestampMs: number;\n /** Recommended fee in microlamports */\n recommended: number;\n /** Network state (0=low, 1=normal, 2=high, 3=congested) */\n state: NetworkState;\n /** Whether data is stale */\n isStale: boolean;\n /** Swap fee percentiles */\n swapP50: number;\n swapP75: number;\n swapP90: number;\n swapP99: number;\n}\n\n/**\n * Network congestion state\n */\nexport enum NetworkState {\n Low = 0,\n Normal = 1,\n High = 2,\n Congested = 3,\n}\n\n/**\n * Recent blockhash for transactions\n */\nexport interface Blockhash {\n /** Slot of blockhash */\n slot: number;\n /** Timestamp in milliseconds */\n timestampMs: number;\n /** Recent blockhash (Base58) */\n blockhash: string;\n /** Block height */\n blockHeight: number;\n /** Last valid block height for transactions */\n lastValidBlockHeight: number;\n /** Whether data is stale */\n isStale: boolean;\n}\n\n/**\n * WebSocket connection heartbeat\n */\nexport interface Heartbeat {\n /** Server timestamp in milliseconds */\n timestampMs: number;\n /** Connection uptime in seconds */\n uptimeSecs: number;\n /** Total messages sent */\n messagesSent: number;\n /** Pool updates sent */\n poolUpdatesSent: number;\n /** Messages dropped (slow client) */\n messagesDropped: number;\n /** Whether pool updates are enabled */\n poolUpdatesEnabled: boolean;\n /** Subscribed channels */\n subscribedChannels: string[];\n /** Server sequence number */\n serverSequence: number;\n}\n\n/**\n * Subscribe request for WebSocket\n */\nexport interface SubscribeRequest {\n /** Channels to subscribe to */\n channels: ('pools' | 'priority_fees' | 'blockhash')[];\n /** Response format (default: binary) */\n format?: 'binary' | 'json';\n /** Filter by protocol names */\n protocols?: string[];\n /** Filter by pool addresses (Base58) */\n pools?: string[];\n /** Filter by token pairs [[mintA, mintB], ...] */\n tokenPairs?: [string, string][];\n}\n\n/**\n * Quote subscription request\n */\nexport interface SubscribeQuoteRequest {\n /** Input token mint (Base58) */\n inputMint: string;\n /** Output token mint (Base58) */\n outputMint: string;\n /** Amount in base units */\n amount: number;\n /** Slippage tolerance in basis points */\n slippageBps?: number;\n /** Refresh interval in milliseconds */\n refreshIntervalMs?: number;\n}\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/utils/base58.ts
|
|
4
|
+
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
5
|
+
function base58Encode(bytes) {
|
|
6
|
+
const digits = [0];
|
|
7
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
8
|
+
let carry = bytes[i];
|
|
9
|
+
for (let j = 0; j < digits.length; j++) {
|
|
10
|
+
carry += digits[j] << 8;
|
|
11
|
+
digits[j] = carry % 58;
|
|
12
|
+
carry = carry / 58 | 0;
|
|
13
|
+
}
|
|
14
|
+
while (carry > 0) {
|
|
15
|
+
digits.push(carry % 58);
|
|
16
|
+
carry = carry / 58 | 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
let leadingZeros = "";
|
|
20
|
+
for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
|
|
21
|
+
leadingZeros += "1";
|
|
22
|
+
}
|
|
23
|
+
return leadingZeros + digits.reverse().map((d) => BASE58_ALPHABET[d]).join("");
|
|
24
|
+
}
|
|
25
|
+
function base58Decode(str) {
|
|
26
|
+
const bytes = [0];
|
|
27
|
+
for (let i = 0; i < str.length; i++) {
|
|
28
|
+
const char = str[i];
|
|
29
|
+
const value = BASE58_ALPHABET.indexOf(char);
|
|
30
|
+
if (value === -1) {
|
|
31
|
+
throw new Error(`Invalid Base58 character: ${char}`);
|
|
32
|
+
}
|
|
33
|
+
let carry = value;
|
|
34
|
+
for (let j = 0; j < bytes.length; j++) {
|
|
35
|
+
carry += bytes[j] * 58;
|
|
36
|
+
bytes[j] = carry & 255;
|
|
37
|
+
carry >>= 8;
|
|
38
|
+
}
|
|
39
|
+
while (carry > 0) {
|
|
40
|
+
bytes.push(carry & 255);
|
|
41
|
+
carry >>= 8;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
for (let i = 0; i < str.length && str[i] === "1"; i++) {
|
|
45
|
+
bytes.push(0);
|
|
46
|
+
}
|
|
47
|
+
return new Uint8Array(bytes.reverse());
|
|
48
|
+
}
|
|
49
|
+
function isValidPubkey(address) {
|
|
50
|
+
if (address.length < 32 || address.length > 44) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
for (const char of address) {
|
|
54
|
+
if (!BASE58_ALPHABET.includes(char)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const bytes = base58Decode(address);
|
|
60
|
+
return bytes.length === 32;
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
exports.base58Decode = base58Decode;
|
|
67
|
+
exports.base58Encode = base58Encode;
|
|
68
|
+
exports.isValidPubkey = isValidPubkey;
|
|
69
|
+
//# sourceMappingURL=index.cjs.map
|
|
70
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/base58.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base58 encoding utilities for Solana addresses\n * \n * Solana uses Base58 encoding (Bitcoin-style) for public keys and signatures.\n */\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n\n/**\n * Encode bytes to Base58 string (Solana address format)\n * \n * @param bytes - Uint8Array to encode\n * @returns Base58 encoded string\n * \n * @example\n * ```typescript\n * const pubkey = new Uint8Array([1, 2, 3, ...]);\n * const address = base58Encode(pubkey);\n * // \"EPjFWdd5...\"\n * ```\n */\nexport function base58Encode(bytes: Uint8Array): string {\n const digits = [0];\n \n for (let i = 0; i < bytes.length; i++) {\n let carry = bytes[i];\n for (let j = 0; j < digits.length; j++) {\n carry += digits[j] << 8;\n digits[j] = carry % 58;\n carry = (carry / 58) | 0;\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = (carry / 58) | 0;\n }\n }\n\n // Leading zeros\n let leadingZeros = '';\n for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {\n leadingZeros += '1';\n }\n\n return leadingZeros + digits.reverse().map(d => BASE58_ALPHABET[d]).join('');\n}\n\n/**\n * Decode Base58 string to bytes\n * \n * @param str - Base58 encoded string\n * @returns Uint8Array of decoded bytes\n * @throws Error if string contains invalid characters\n * \n * @example\n * ```typescript\n * const bytes = base58Decode(\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\");\n * // Uint8Array(32) [...]\n * ```\n */\nexport function base58Decode(str: string): Uint8Array {\n const bytes = [0];\n \n for (let i = 0; i < str.length; i++) {\n const char = str[i];\n const value = BASE58_ALPHABET.indexOf(char);\n \n if (value === -1) {\n throw new Error(`Invalid Base58 character: ${char}`);\n }\n \n let carry = value;\n for (let j = 0; j < bytes.length; j++) {\n carry += bytes[j] * 58;\n bytes[j] = carry & 0xff;\n carry >>= 8;\n }\n while (carry > 0) {\n bytes.push(carry & 0xff);\n carry >>= 8;\n }\n }\n\n // Leading '1's are leading zeros\n for (let i = 0; i < str.length && str[i] === '1'; i++) {\n bytes.push(0);\n }\n\n return new Uint8Array(bytes.reverse());\n}\n\n/**\n * Check if a string is a valid Solana public key (Base58, 32-44 chars)\n * \n * @param address - String to validate\n * @returns true if valid Solana pubkey format\n * \n * @example\n * ```typescript\n * isValidPubkey(\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\") // true\n * isValidPubkey(\"invalid\") // false\n * ```\n */\nexport function isValidPubkey(address: string): boolean {\n // Solana pubkeys are 32-44 characters in Base58\n if (address.length < 32 || address.length > 44) {\n return false;\n }\n\n // Check all characters are valid Base58\n for (const char of address) {\n if (!BASE58_ALPHABET.includes(char)) {\n return false;\n }\n }\n\n // Try to decode and verify length\n try {\n const bytes = base58Decode(address);\n return bytes.length === 32;\n } catch {\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base58 encoding utilities for Solana addresses
|
|
3
|
+
*
|
|
4
|
+
* Solana uses Base58 encoding (Bitcoin-style) for public keys and signatures.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Encode bytes to Base58 string (Solana address format)
|
|
8
|
+
*
|
|
9
|
+
* @param bytes - Uint8Array to encode
|
|
10
|
+
* @returns Base58 encoded string
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const pubkey = new Uint8Array([1, 2, 3, ...]);
|
|
15
|
+
* const address = base58Encode(pubkey);
|
|
16
|
+
* // "EPjFWdd5..."
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function base58Encode(bytes: Uint8Array): string;
|
|
20
|
+
/**
|
|
21
|
+
* Decode Base58 string to bytes
|
|
22
|
+
*
|
|
23
|
+
* @param str - Base58 encoded string
|
|
24
|
+
* @returns Uint8Array of decoded bytes
|
|
25
|
+
* @throws Error if string contains invalid characters
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const bytes = base58Decode("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
30
|
+
* // Uint8Array(32) [...]
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function base58Decode(str: string): Uint8Array;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a string is a valid Solana public key (Base58, 32-44 chars)
|
|
36
|
+
*
|
|
37
|
+
* @param address - String to validate
|
|
38
|
+
* @returns true if valid Solana pubkey format
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* isValidPubkey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") // true
|
|
43
|
+
* isValidPubkey("invalid") // false
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare function isValidPubkey(address: string): boolean;
|
|
47
|
+
|
|
48
|
+
export { base58Decode, base58Encode, isValidPubkey };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base58 encoding utilities for Solana addresses
|
|
3
|
+
*
|
|
4
|
+
* Solana uses Base58 encoding (Bitcoin-style) for public keys and signatures.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Encode bytes to Base58 string (Solana address format)
|
|
8
|
+
*
|
|
9
|
+
* @param bytes - Uint8Array to encode
|
|
10
|
+
* @returns Base58 encoded string
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const pubkey = new Uint8Array([1, 2, 3, ...]);
|
|
15
|
+
* const address = base58Encode(pubkey);
|
|
16
|
+
* // "EPjFWdd5..."
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function base58Encode(bytes: Uint8Array): string;
|
|
20
|
+
/**
|
|
21
|
+
* Decode Base58 string to bytes
|
|
22
|
+
*
|
|
23
|
+
* @param str - Base58 encoded string
|
|
24
|
+
* @returns Uint8Array of decoded bytes
|
|
25
|
+
* @throws Error if string contains invalid characters
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const bytes = base58Decode("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
30
|
+
* // Uint8Array(32) [...]
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function base58Decode(str: string): Uint8Array;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a string is a valid Solana public key (Base58, 32-44 chars)
|
|
36
|
+
*
|
|
37
|
+
* @param address - String to validate
|
|
38
|
+
* @returns true if valid Solana pubkey format
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* isValidPubkey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") // true
|
|
43
|
+
* isValidPubkey("invalid") // false
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare function isValidPubkey(address: string): boolean;
|
|
47
|
+
|
|
48
|
+
export { base58Decode, base58Encode, isValidPubkey };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// src/utils/base58.ts
|
|
2
|
+
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
3
|
+
function base58Encode(bytes) {
|
|
4
|
+
const digits = [0];
|
|
5
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
6
|
+
let carry = bytes[i];
|
|
7
|
+
for (let j = 0; j < digits.length; j++) {
|
|
8
|
+
carry += digits[j] << 8;
|
|
9
|
+
digits[j] = carry % 58;
|
|
10
|
+
carry = carry / 58 | 0;
|
|
11
|
+
}
|
|
12
|
+
while (carry > 0) {
|
|
13
|
+
digits.push(carry % 58);
|
|
14
|
+
carry = carry / 58 | 0;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
let leadingZeros = "";
|
|
18
|
+
for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
|
|
19
|
+
leadingZeros += "1";
|
|
20
|
+
}
|
|
21
|
+
return leadingZeros + digits.reverse().map((d) => BASE58_ALPHABET[d]).join("");
|
|
22
|
+
}
|
|
23
|
+
function base58Decode(str) {
|
|
24
|
+
const bytes = [0];
|
|
25
|
+
for (let i = 0; i < str.length; i++) {
|
|
26
|
+
const char = str[i];
|
|
27
|
+
const value = BASE58_ALPHABET.indexOf(char);
|
|
28
|
+
if (value === -1) {
|
|
29
|
+
throw new Error(`Invalid Base58 character: ${char}`);
|
|
30
|
+
}
|
|
31
|
+
let carry = value;
|
|
32
|
+
for (let j = 0; j < bytes.length; j++) {
|
|
33
|
+
carry += bytes[j] * 58;
|
|
34
|
+
bytes[j] = carry & 255;
|
|
35
|
+
carry >>= 8;
|
|
36
|
+
}
|
|
37
|
+
while (carry > 0) {
|
|
38
|
+
bytes.push(carry & 255);
|
|
39
|
+
carry >>= 8;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (let i = 0; i < str.length && str[i] === "1"; i++) {
|
|
43
|
+
bytes.push(0);
|
|
44
|
+
}
|
|
45
|
+
return new Uint8Array(bytes.reverse());
|
|
46
|
+
}
|
|
47
|
+
function isValidPubkey(address) {
|
|
48
|
+
if (address.length < 32 || address.length > 44) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
for (const char of address) {
|
|
52
|
+
if (!BASE58_ALPHABET.includes(char)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const bytes = base58Decode(address);
|
|
58
|
+
return bytes.length === 32;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { base58Decode, base58Encode, isValidPubkey };
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/base58.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base58 encoding utilities for Solana addresses\n * \n * Solana uses Base58 encoding (Bitcoin-style) for public keys and signatures.\n */\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n\n/**\n * Encode bytes to Base58 string (Solana address format)\n * \n * @param bytes - Uint8Array to encode\n * @returns Base58 encoded string\n * \n * @example\n * ```typescript\n * const pubkey = new Uint8Array([1, 2, 3, ...]);\n * const address = base58Encode(pubkey);\n * // \"EPjFWdd5...\"\n * ```\n */\nexport function base58Encode(bytes: Uint8Array): string {\n const digits = [0];\n \n for (let i = 0; i < bytes.length; i++) {\n let carry = bytes[i];\n for (let j = 0; j < digits.length; j++) {\n carry += digits[j] << 8;\n digits[j] = carry % 58;\n carry = (carry / 58) | 0;\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = (carry / 58) | 0;\n }\n }\n\n // Leading zeros\n let leadingZeros = '';\n for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {\n leadingZeros += '1';\n }\n\n return leadingZeros + digits.reverse().map(d => BASE58_ALPHABET[d]).join('');\n}\n\n/**\n * Decode Base58 string to bytes\n * \n * @param str - Base58 encoded string\n * @returns Uint8Array of decoded bytes\n * @throws Error if string contains invalid characters\n * \n * @example\n * ```typescript\n * const bytes = base58Decode(\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\");\n * // Uint8Array(32) [...]\n * ```\n */\nexport function base58Decode(str: string): Uint8Array {\n const bytes = [0];\n \n for (let i = 0; i < str.length; i++) {\n const char = str[i];\n const value = BASE58_ALPHABET.indexOf(char);\n \n if (value === -1) {\n throw new Error(`Invalid Base58 character: ${char}`);\n }\n \n let carry = value;\n for (let j = 0; j < bytes.length; j++) {\n carry += bytes[j] * 58;\n bytes[j] = carry & 0xff;\n carry >>= 8;\n }\n while (carry > 0) {\n bytes.push(carry & 0xff);\n carry >>= 8;\n }\n }\n\n // Leading '1's are leading zeros\n for (let i = 0; i < str.length && str[i] === '1'; i++) {\n bytes.push(0);\n }\n\n return new Uint8Array(bytes.reverse());\n}\n\n/**\n * Check if a string is a valid Solana public key (Base58, 32-44 chars)\n * \n * @param address - String to validate\n * @returns true if valid Solana pubkey format\n * \n * @example\n * ```typescript\n * isValidPubkey(\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\") // true\n * isValidPubkey(\"invalid\") // false\n * ```\n */\nexport function isValidPubkey(address: string): boolean {\n // Solana pubkeys are 32-44 characters in Base58\n if (address.length < 32 || address.length > 44) {\n return false;\n }\n\n // Check all characters are valid Base58\n for (const char of address) {\n if (!BASE58_ALPHABET.includes(char)) {\n return false;\n }\n }\n\n // Try to decode and verify length\n try {\n const bytes = base58Decode(address);\n return bytes.length === 32;\n } catch {\n return false;\n }\n}\n"]}
|