stellar-shade 0.0.2 → 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/README.md +135 -39
- package/dist/index.cjs +3069 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2234 -124
- package/dist/index.d.ts +2234 -124
- package/dist/index.js +3017 -225
- package/dist/index.js.map +1 -1
- package/package.json +23 -12
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../crypto/src/errors.ts","../../crypto/src/ed25519.ts","../../crypto/src/keys.ts","../../crypto/src/hash.ts","../../crypto/src/stellar-keys.ts","../../crypto/src/scan.ts","../../crypto/src/recover.ts","../../crypto/src/prove.ts","../../crypto/src/advanced.ts","../../crypto/src/hd.ts","../src/soroban.ts","../src/client.ts"],"names":["ed25519","bytesToNumberLE","numberToBytesLE","randomBytes","sha256","sha512","_generateMnemonic","wordlist","_validateMnemonic","mnemonicToSeedSync","viewTag","Networks","StellarSdk","TransactionBuilder","Contract","Asset","nativeToScVal","StrKey","Keypair","StellarSdk2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Custom error types for crypto operations\r\n */\r\n\r\n/**\r\n * Error thrown when a point operation results in the point at infinity\r\n */\r\nexport class PointAtInfinity extends Error {\r\n constructor(operation: string) {\r\n super(`Point at infinity encountered in ${operation}`);\r\n this.name = 'PointAtInfinity';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a public key is not on the ed25519 curve\r\n */\r\nexport class InvalidPublicKey extends Error {\r\n constructor(message = 'Invalid public key: not on curve') {\r\n super(message);\r\n this.name = 'InvalidPublicKey';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a scalar value is invalid (e.g., zero where not allowed)\r\n */\r\nexport class InvalidScalar extends Error {\r\n constructor(message = 'Invalid scalar value') {\r\n super(message);\r\n this.name = 'InvalidScalar';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when meta-address encoding/decoding fails\r\n */\r\nexport class InvalidMetaAddress extends Error {\r\n constructor(message = 'Invalid meta-address format') {\r\n super(message);\r\n this.name = 'InvalidMetaAddress';\r\n }\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { PointAtInfinity, InvalidPublicKey, InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Curve order L for ed25519\r\n */\r\nexport const L = 2n ** 252n + 27742317777372353535851937790883648493n;\r\n\r\n/**\r\n * Validate that a point is on the ed25519 curve.\r\n * @param point 32-byte compressed point\r\n * @returns true if valid\r\n * @throws InvalidPublicKey if not on curve\r\n */\r\nexport function validatePoint(point: Uint8Array): boolean {\r\n if (point.length !== 32) {\r\n throw new InvalidPublicKey('Invalid point length');\r\n }\r\n\r\n try {\r\n // This will throw if point is not on curve\r\n ed25519.ExtendedPoint.fromHex(point);\r\n return true;\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) throw e;\r\n throw new InvalidPublicKey('Point not on curve');\r\n }\r\n}\r\n\r\n/**\r\n * Add two ed25519 points.\r\n * @param p1 First point (32-byte compressed)\r\n * @param p2 Second point (32-byte compressed)\r\n * @returns Result point (32-byte compressed)\r\n * @throws PointAtInfinity if result is point at infinity\r\n * @throws InvalidPublicKey if points are not on curve\r\n */\r\nexport function pointAdd(p1: Uint8Array, p2: Uint8Array): Uint8Array {\r\n if (p1.length !== 32) throw new InvalidPublicKey('Invalid p1 length');\r\n if (p2.length !== 32) throw new InvalidPublicKey('Invalid p2 length');\r\n\r\n // Validate both points are on curve\r\n validatePoint(p1);\r\n validatePoint(p2);\r\n\r\n const point1 = ed25519.ExtendedPoint.fromHex(p1);\r\n const point2 = ed25519.ExtendedPoint.fromHex(p2);\r\n const result = point1.add(point2);\r\n\r\n // Check for point at infinity\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('pointAdd');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with generator point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n */\r\nexport function scalarMultBase(scalar: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const result = ed25519.ExtendedPoint.BASE.multiply(s);\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with arbitrary point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param point 32-byte compressed point\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n * @throws InvalidPublicKey if point is not on curve\r\n * @throws PointAtInfinity if result is point at infinity\r\n */\r\nexport function scalarMult(scalar: Uint8Array, point: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n if (point.length !== 32) throw new InvalidPublicKey('Invalid point length');\r\n\r\n // Validate point is on curve\r\n validatePoint(point);\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const p = ed25519.ExtendedPoint.fromHex(point);\r\n const result = p.multiply(s);\r\n\r\n // Check for point at infinity (should not happen with valid inputs)\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('scalarMult');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Add two scalars modulo curve order L.\r\n * @param s1 First scalar (32-byte, little-endian)\r\n * @param s2 Second scalar (32-byte, little-endian)\r\n * @returns Result scalar (32-byte, little-endian)\r\n * @throws InvalidScalar if inputs have wrong length\r\n */\r\nexport function scalarAdd(s1: Uint8Array, s2: Uint8Array): Uint8Array {\r\n if (s1.length !== 32) throw new InvalidScalar('Invalid s1 length');\r\n if (s2.length !== 32) throw new InvalidScalar('Invalid s2 length');\r\n\r\n const a = bytesToNumberLE(s1) % L;\r\n const b = bytesToNumberLE(s2) % L;\r\n const result = (a + b) % L;\r\n\r\n return numberToBytesLE(result, 32);\r\n}","import { randomBytes } from '@noble/hashes/utils';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\nimport type { StealthKeys, StealthMetaAddress } from './types.js';\r\nimport { L, scalarMultBase, validatePoint } from './ed25519.js';\r\nimport { InvalidMetaAddress, InvalidPublicKey } from './errors.js';\r\n\r\n/**\r\n * Generate a new stealth meta-address with random keys.\r\n *\r\n * Creates a complete stealth key pair using cryptographically secure\r\n * random number generation. The resulting keys can be used for:\r\n * - Receiving stealth payments (using the meta-address)\r\n * - Scanning for incoming payments (using view private key)\r\n * - Spending from stealth addresses (using spend private key)\r\n *\r\n * @returns Complete stealth keys including private keys and meta-address\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n *\r\n * // Share the meta-address publicly\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log('Share this:', encoded);\r\n *\r\n * // Keep private keys secure\r\n * saveSecurely(keys.spendPrivKey, keys.viewPrivKey);\r\n * ```\r\n */\r\nexport function generateMetaAddress(): StealthKeys {\r\n // Generate two random 32-byte scalars (reduced mod L)\r\n const spendPrivKey = generateRandomScalar();\r\n const viewPrivKey = generateRandomScalar();\r\n\r\n // Derive public keys\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: {\r\n spendPubKey,\r\n viewPubKey,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Generate a random scalar reduced modulo L.\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n */\r\nfunction generateRandomScalar(): Uint8Array {\r\n const bytes = randomBytes(32);\r\n const scalar = bytesToNumberLE(bytes) % L;\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Encode a stealth meta-address to a string format with checksum.\r\n *\r\n * Encodes the meta-address into a shareable string format that includes:\r\n * - Protocol identifier (\"st:stellar:\")\r\n * - Concatenated public keys (spend || view)\r\n * - CRC32 checksum for error detection\r\n *\r\n * @param meta - Stealth meta-address containing spend and view public keys\r\n * @returns Encoded string in format \"st:stellar:<hex(spend_pk || view_pk)><checksum>\"\r\n * @throws {InvalidMetaAddress} If public keys are invalid length or not on curve\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log(encoded); // \"st:stellar:abc123...def456\"\r\n *\r\n * // Share this encoded string with senders\r\n * publishMetaAddress(encoded);\r\n * ```\r\n */\r\nexport function encodeMetaAddress(meta: StealthMetaAddress): string {\r\n if (meta.spendPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid spend public key length');\r\n }\r\n if (meta.viewPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid view public key length');\r\n }\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(meta.spendPubKey);\r\n validatePoint(meta.viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n // Concatenate both public keys\r\n const payload = new Uint8Array(64);\r\n payload.set(meta.spendPubKey, 0);\r\n payload.set(meta.viewPubKey, 32);\r\n\r\n // Calculate checksum (last 4 bytes of SHA-256)\r\n const hash = sha256(payload);\r\n const checksum = hash.slice(28, 32);\r\n\r\n // Combine payload and checksum\r\n const combined = new Uint8Array(68);\r\n combined.set(payload, 0);\r\n combined.set(checksum, 64);\r\n\r\n // Convert to hex\r\n const hex = Array.from(combined)\r\n .map((b) => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n\r\n return `st:stellar:${hex}`;\r\n}\r\n\r\n/**\r\n * Decode a string-encoded stealth meta-address with checksum validation.\r\n *\r\n * Parses an encoded meta-address string and validates:\r\n * - Correct format and prefix\r\n * - Valid hex encoding\r\n * - Checksum integrity\r\n * - Public keys are on curve\r\n *\r\n * @param encoded - Encoded meta-address string (\"st:stellar:...\")\r\n * @returns Decoded stealth meta-address with public keys\r\n * @throws {InvalidMetaAddress} If format, checksum, or keys are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * const encoded = \"st:stellar:abc123...def456\";\r\n * const meta = decodeMetaAddress(encoded);\r\n *\r\n * // Use for deriving stealth addresses\r\n * const stealth = deriveStealthAddress(meta);\r\n * ```\r\n */\r\nexport function decodeMetaAddress(encoded: string): StealthMetaAddress {\r\n if (!encoded.startsWith('st:stellar:')) {\r\n throw new InvalidMetaAddress('Invalid meta-address prefix');\r\n }\r\n\r\n const hex = encoded.slice(11); // Remove \"st:stellar:\" prefix\r\n if (hex.length !== 136) {\r\n // 64 bytes payload + 4 bytes checksum = 68 bytes = 136 hex chars\r\n throw new InvalidMetaAddress('Invalid meta-address length');\r\n }\r\n\r\n // Parse hex to bytes\r\n const combined = new Uint8Array(68);\r\n for (let i = 0; i < 68; i++) {\r\n const byte = parseInt(hex.substr(i * 2, 2), 16);\r\n if (isNaN(byte)) {\r\n throw new InvalidMetaAddress('Invalid hex encoding');\r\n }\r\n combined[i] = byte;\r\n }\r\n\r\n // Split payload and checksum\r\n const payload = combined.slice(0, 64);\r\n const checksum = combined.slice(64, 68);\r\n\r\n // Verify checksum\r\n const hash = sha256(payload);\r\n const expectedChecksum = hash.slice(28, 32);\r\n\r\n let checksumValid = true;\r\n for (let i = 0; i < 4; i++) {\r\n if (checksum[i] !== expectedChecksum[i]) {\r\n checksumValid = false;\r\n break;\r\n }\r\n }\r\n\r\n if (!checksumValid) {\r\n throw new InvalidMetaAddress('Invalid checksum');\r\n }\r\n\r\n const spendPubKey = payload.slice(0, 32);\r\n const viewPubKey = payload.slice(32, 64);\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(spendPubKey);\r\n validatePoint(viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key in meta-address: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n return {\r\n spendPubKey,\r\n viewPubKey,\r\n };\r\n}","import { sha256 } from '@noble/hashes/sha256';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L } from './ed25519.js';\r\nimport { InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Hash data to a scalar value modulo curve order L.\r\n *\r\n * Implements the hash-to-scalar function used in DKSAP for deriving\r\n * the blinding factor from the shared secret.\r\n *\r\n * @param data - Input data to hash (typically a 32-byte shared secret)\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n * @throws {InvalidScalar} If hash produces zero scalar (extremely unlikely)\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(ephemeralPrivKey, viewPubKey);\r\n * const s = hashToScalar(sharedSecret);\r\n * // Use s as blinding factor for stealth key derivation\r\n * ```\r\n */\r\nexport function hashToScalar(data: Uint8Array): Uint8Array {\r\n const hash = sha256(data);\r\n const scalar = bytesToNumberLE(hash) % L;\r\n\r\n // In the extremely unlikely event the hash produces zero mod L\r\n if (scalar === 0n) {\r\n throw new InvalidScalar('Hash produced zero scalar');\r\n }\r\n\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Extract view tag from shared secret.\r\n *\r\n * The view tag is the first byte of SHA256(shared_secret) and enables\r\n * ~25x faster scanning by filtering announcements before expensive EC operations.\r\n *\r\n * @param sharedSecret - 32-byte shared secret from ECDH\r\n * @returns Single byte view tag (0-255)\r\n * @throws {Error} If shared secret is not 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(viewPrivKey, ephemeralPubKey);\r\n * const tag = viewTag(sharedSecret);\r\n * // Use tag for fast announcement filtering\r\n * ```\r\n */\r\nexport function viewTag(sharedSecret: Uint8Array): number {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error('Invalid shared secret length');\r\n }\r\n const hash = sha256(sharedSecret);\r\n return hash[0]!;\r\n}","/**\r\n * Stellar StrKey encoding (base32check) for ed25519 public keys.\r\n * This module provides pure TypeScript implementation without @stellar/stellar-sdk dependency.\r\n */\r\n\r\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\r\nconst VERSION_BYTE_PUBLIC_KEY = 6 << 3; // G addresses\r\n\r\n/**\r\n * CRC16-XModem checksum implementation.\r\n */\r\nfunction crc16XModem(data: Uint8Array): number {\r\n let crc = 0x0000;\r\n for (let i = 0; i < data.length; i++) {\r\n crc ^= data[i]! << 8;\r\n for (let j = 0; j < 8; j++) {\r\n if (crc & 0x8000) {\r\n crc = (crc << 1) ^ 0x1021;\r\n } else {\r\n crc = crc << 1;\r\n }\r\n }\r\n }\r\n return crc & 0xffff;\r\n}\r\n\r\n/**\r\n * Base32 encode (RFC 4648) without padding.\r\n */\r\nfunction base32Encode(data: Uint8Array): string {\r\n let bits = 0;\r\n let value = 0;\r\n let output = '';\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n value = (value << 8) | data[i]!;\r\n bits += 8;\r\n\r\n while (bits >= 5) {\r\n output += ALPHABET[(value >>> (bits - 5)) & 31];\r\n bits -= 5;\r\n }\r\n }\r\n\r\n if (bits > 0) {\r\n output += ALPHABET[(value << (5 - bits)) & 31];\r\n }\r\n\r\n return output;\r\n}\r\n\r\n/**\r\n * Base32 decode (RFC 4648).\r\n */\r\nfunction base32Decode(str: string): Uint8Array {\r\n const output: number[] = [];\r\n let bits = 0;\r\n let value = 0;\r\n\r\n for (let i = 0; i < str.length; i++) {\r\n const idx = ALPHABET.indexOf(str[i]!);\r\n if (idx === -1) {\r\n throw new Error(`Invalid base32 character: ${str[i]}`);\r\n }\r\n\r\n value = (value << 5) | idx;\r\n bits += 5;\r\n\r\n while (bits >= 8) {\r\n output.push((value >>> (bits - 8)) & 255);\r\n bits -= 8;\r\n }\r\n }\r\n\r\n return new Uint8Array(output);\r\n}\r\n\r\n/**\r\n * Encode ed25519 public key to Stellar address format (G...).\r\n *\r\n * Implements Stellar's StrKey encoding (SEP-23) using base32check format.\r\n *\r\n * @param pubKey - 32-byte ed25519 public key\r\n * @returns Stellar address in StrKey format (G...)\r\n * @throws {Error} If public key is not exactly 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const pubKey = new Uint8Array(32); // Your public key\r\n * const address = encodePublicKey(pubKey);\r\n * console.log(address); // \"GABC...XYZ\"\r\n * ```\r\n */\r\nexport function encodePublicKey(pubKey: Uint8Array): string {\r\n if (pubKey.length !== 32) {\r\n throw new Error('Public key must be 32 bytes');\r\n }\r\n\r\n const versionedPayload = new Uint8Array(33);\r\n versionedPayload[0] = VERSION_BYTE_PUBLIC_KEY;\r\n versionedPayload.set(pubKey, 1);\r\n\r\n const checksum = crc16XModem(versionedPayload);\r\n const checksumBytes = new Uint8Array(2);\r\n checksumBytes[0] = checksum & 0xff;\r\n checksumBytes[1] = (checksum >>> 8) & 0xff;\r\n\r\n const fullPayload = new Uint8Array(35);\r\n fullPayload.set(versionedPayload, 0);\r\n fullPayload.set(checksumBytes, 33);\r\n\r\n return base32Encode(fullPayload);\r\n}\r\n\r\n/**\r\n * Decode Stellar address to ed25519 public key.\r\n *\r\n * Implements Stellar's StrKey decoding (SEP-23) with checksum validation.\r\n *\r\n * @param address - Stellar address in StrKey format (G...)\r\n * @returns 32-byte ed25519 public key\r\n * @throws {Error} If address format is invalid or checksum fails\r\n *\r\n * @example\r\n * ```typescript\r\n * const address = \"GABC...XYZ\";\r\n * const pubKey = decodePublicKey(address);\r\n * console.log(pubKey.length); // 32\r\n * ```\r\n */\r\nexport function decodePublicKey(address: string): Uint8Array {\r\n if (!address.startsWith('G')) {\r\n throw new Error('Invalid Stellar address: must start with G');\r\n }\r\n\r\n const decoded = base32Decode(address);\r\n if (decoded.length !== 35) {\r\n throw new Error('Invalid Stellar address: incorrect length');\r\n }\r\n\r\n const versionByte = decoded[0]!;\r\n if (versionByte !== VERSION_BYTE_PUBLIC_KEY) {\r\n throw new Error('Invalid Stellar address: wrong version byte');\r\n }\r\n\r\n const versionedPayload = decoded.slice(0, 33);\r\n const providedChecksum = (decoded[34]! << 8) | decoded[33]!;\r\n const calculatedChecksum = crc16XModem(versionedPayload);\r\n\r\n if (providedChecksum !== calculatedChecksum) {\r\n throw new Error('Invalid Stellar address: checksum mismatch');\r\n }\r\n\r\n return decoded.slice(1, 33);\r\n}","import type { Announcement, StealthAddress } from './types.js';\r\nimport { scalarMult, pointAdd, scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\n\r\n/**\r\n * Check if a view tag matches for a given ephemeral public key.\r\n *\r\n * This is a fast pre-filter before doing the expensive EC operations.\r\n * Only computes the shared secret and extracts the first byte for comparison.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param expectedTag - Expected view tag from announcement (0-255)\r\n * @returns Object with match result and shared secret if matched\r\n * @throws {Error} If key lengths are invalid or tag is out of range\r\n *\r\n * @example\r\n * ```typescript\r\n * // Fast filtering before full verification\r\n * const result = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n * if (result.matches) {\r\n * // Use the shared secret for further verification\r\n * const s = hashToScalar(result.sharedSecret);\r\n * }\r\n * ```\r\n */\r\nexport function checkViewTag(\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n expectedTag: number\r\n): { matches: boolean; sharedSecret?: Uint8Array } {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n if (expectedTag < 0 || expectedTag > 255) {\r\n throw new Error('Invalid view tag');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Extract and compare view tag (first byte of SHA256(S))\r\n const computedTag = viewTag(S);\r\n\r\n if (computedTag === expectedTag) {\r\n return { matches: true, sharedSecret: S };\r\n }\r\n return { matches: false };\r\n}\r\n\r\n/**\r\n * Scan announcements to find stealth addresses belonging to the receiver.\r\n *\r\n * This implements an optimized two-pass scanning algorithm:\r\n * - Pass 1: Filter by view tag (cheap byte comparison)\r\n * - Pass 2: Full EC math (scalarMult + pointAdd) only on tag matches\r\n *\r\n * This optimization provides ~25x speedup for large announcement sets\r\n * by avoiding expensive EC operations on non-matching announcements.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param announcements - List of announcements to scan\r\n * @returns Array of stealth addresses belonging to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Scan blockchain announcements\r\n * const announcements = await fetchAnnouncements();\r\n * const myAddresses = scanAnnouncements(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcements\r\n * );\r\n *\r\n * // Check balances of discovered addresses\r\n * for (const addr of myAddresses) {\r\n * const balance = await getBalance(addr.address);\r\n * console.log(`${addr.address}: ${balance} XLM`);\r\n * }\r\n * ```\r\n */\r\nexport function scanAnnouncements(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n announcements: Announcement[]\r\n): StealthAddress[] {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n\r\n const results: StealthAddress[] = [];\r\n\r\n // Two-pass scanning for optimization\r\n // Pass 1: Quick view tag filtering with shared secret caching\r\n const tagMatches: Array<{ announcement: Announcement; sharedSecret: Uint8Array }> = [];\r\n for (const announcement of announcements) {\r\n const tagResult = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n if (tagResult.matches && tagResult.sharedSecret) {\r\n tagMatches.push({ announcement, sharedSecret: tagResult.sharedSecret });\r\n }\r\n }\r\n\r\n // Pass 2: Full verification only on tag matches (reusing shared secrets)\r\n for (const { announcement, sharedSecret } of tagMatches) {\r\n // Hash to scalar s = SHA256(S) mod L (using cached shared secret)\r\n const s = hashToScalar(sharedSecret);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n if (computedAddress === announcement.stealthAddress) {\r\n results.push({\r\n publicKey: P,\r\n address: computedAddress,\r\n });\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Check if a specific stealth address belongs to the receiver.\r\n *\r\n * Performs full DKSAP verification to determine ownership of a stealth address.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param stealthAddress - Stellar address to check (G... format)\r\n * @returns True if the stealth address belongs to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Check if a payment is for you\r\n * const isMine = isMyStealthAddress(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcement.ephemeralPubKey,\r\n * announcement.stealthAddress\r\n * );\r\n *\r\n * if (isMine) {\r\n * console.log('Found payment to:', announcement.stealthAddress);\r\n * }\r\n * ```\r\n */\r\nexport function isMyStealthAddress(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n stealthAddress: string\r\n): boolean {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Hash to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n return computedAddress === stealthAddress;\r\n}","import { scalarMult, scalarAdd } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\n/**\r\n * Recover the stealth private key for a stealth address.\r\n *\r\n * This implements the receiver's private key recovery:\r\n * 1. Compute shared secret S = k_view * R\r\n * 2. Hash to scalar s = SHA256(S) mod L\r\n * 3. Compute stealth private key p = k_spend + s mod L\r\n *\r\n * The recovered private key can be used to:\r\n * - Sign transactions from the stealth address\r\n * - Derive the corresponding public key for verification\r\n *\r\n * @param spendPrivKey - Receiver's 32-byte spend private key\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @returns 32-byte stealth private key for signing transactions\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Recover private key to withdraw funds\r\n * const stealthPrivKey = recoverStealthPrivateKey(\r\n * keys.spendPrivKey,\r\n * keys.viewPrivKey,\r\n * announcement.ephemeralPubKey\r\n * );\r\n *\r\n * // Use with Stellar SDK to sign transaction\r\n * const keypair = Keypair.fromRawEd25519Seed(stealthPrivKey);\r\n * transaction.sign(keypair);\r\n *\r\n * // IMPORTANT: Clear private key from memory after use\r\n * stealthPrivKey.fill(0);\r\n * ```\r\n */\r\nexport function recoverStealthPrivateKey(\r\n spendPrivKey: Uint8Array,\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array\r\n): Uint8Array {\r\n if (spendPrivKey.length !== 32) {\r\n throw new Error('Invalid spend private key length');\r\n }\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Step 1: Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Step 2: Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Step 3: Compute stealth private key p = k_spend + s mod L\r\n const stealthPrivKey = scalarAdd(spendPrivKey, s);\r\n\r\n return stealthPrivKey;\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { sha512 } from '@noble/hashes/sha512';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L, scalarMultBase } from './ed25519.js';\r\n\r\n/**\r\n * Sign a message using a raw ed25519 scalar (stealth private key).\r\n *\r\n * Standard ed25519.sign() hashes the seed to derive the signing scalar,\r\n * but stealth private keys are already raw scalars from modular addition\r\n * (k_spend + s mod L). This function constructs a valid ed25519 signature\r\n * directly from the raw scalar, producing signatures that verify with\r\n * standard ed25519.verify() against the corresponding public key (scalar * G).\r\n *\r\n * @param message - The message to sign\r\n * @param privateScalar - 32-byte raw scalar (stealth private key)\r\n * @returns 64-byte ed25519 signature (R || S)\r\n */\r\nexport function signWithStealthKey(message: Uint8Array, privateScalar: Uint8Array): Uint8Array {\r\n if (privateScalar.length !== 32) {\r\n throw new Error('Invalid stealth private key length');\r\n }\r\n if (message.length === 0) {\r\n throw new Error('Message cannot be empty');\r\n }\r\n\r\n const a = bytesToNumberLE(privateScalar) % L;\r\n const pubKeyBytes = scalarMultBase(privateScalar);\r\n\r\n // Deterministic nonce: r = SHA-512(privateScalar || message) mod L\r\n const nonceInput = new Uint8Array(32 + message.length);\r\n nonceInput.set(privateScalar, 0);\r\n nonceInput.set(message, 32);\r\n const r = bytesToNumberLE(sha512(nonceInput)) % L;\r\n\r\n const R = ed25519.ExtendedPoint.BASE.multiply(r);\r\n const Rbytes = R.toRawBytes();\r\n\r\n // Challenge: k = SHA-512(R || pubKey || message) mod L\r\n const challengeInput = new Uint8Array(32 + 32 + message.length);\r\n challengeInput.set(Rbytes, 0);\r\n challengeInput.set(pubKeyBytes, 32);\r\n challengeInput.set(message, 64);\r\n const k = bytesToNumberLE(sha512(challengeInput)) % L;\r\n\r\n // Response: S = (r + k * a) mod L\r\n const S = (r + k * a) % L;\r\n\r\n const sig = new Uint8Array(64);\r\n sig.set(Rbytes, 0);\r\n sig.set(numberToBytesLE(S, 32), 32);\r\n return sig;\r\n}\r\n\r\n/**\r\n * Prove ownership of a stealth address by signing a challenge.\r\n *\r\n * Uses raw-scalar ed25519 signing so the signature verifies against\r\n * the stealth public key (privateScalar * G), not the hashed-seed public key.\r\n *\r\n * @param stealthPrivKey - The 32-byte stealth private key (raw scalar)\r\n * @param challenge - The challenge to sign (typically a nonce or timestamp)\r\n * @returns The 64-byte ed25519 signature\r\n * @throws {Error} If private key is not 32 bytes or challenge is empty\r\n */\r\nexport function proveOwnership(\r\n stealthPrivKey: Uint8Array,\r\n challenge: Uint8Array\r\n): Uint8Array {\r\n return signWithStealthKey(challenge, stealthPrivKey);\r\n}\r\n\r\n/**\r\n * Verify ownership proof of a stealth address.\r\n *\r\n * Verifies a standard ed25519 signature against the stealth public key.\r\n * Works with signatures produced by signWithStealthKey/proveOwnership.\r\n *\r\n * @param stealthPubKey - The 32-byte stealth public key (scalar * G)\r\n * @param challenge - The challenge that was signed\r\n * @param signature - The 64-byte signature to verify\r\n * @returns True if the signature is valid, false otherwise\r\n */\r\nexport function verifyOwnership(\r\n stealthPubKey: Uint8Array,\r\n challenge: Uint8Array,\r\n signature: Uint8Array,\r\n): boolean {\r\n if (stealthPubKey.length !== 32) {\r\n throw new Error('Invalid stealth public key length');\r\n }\r\n if (challenge.length === 0) {\r\n throw new Error('Challenge cannot be empty');\r\n }\r\n if (signature.length !== 64) {\r\n throw new Error('Invalid signature length');\r\n }\r\n\r\n try {\r\n return ed25519.verify(signature, challenge, stealthPubKey);\r\n } catch {\r\n return false;\r\n }\r\n}","// Advanced stealth address functions\r\nimport type { StealthDerivation } from './stealth.js';\r\nimport { scalarMult, scalarMultBase, pointAdd } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\n\r\n/**\r\n * Encrypt an amount using the shared secret.\r\n *\r\n * Uses XOR encryption with SHA256(sharedSecret || \"amount\") as the key.\r\n * This provides confidential amounts in stealth transactions.\r\n *\r\n * @param amount - The amount to encrypt\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns 8-byte encrypted amount\r\n */\r\nexport function encryptAmount(amount: number, sharedSecret: Uint8Array): Uint8Array {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n // Create key material\r\n const keyInput = new Uint8Array(32 + 6);\r\n keyInput.set(sharedSecret, 0);\r\n keyInput.set(new TextEncoder().encode('amount'), 32);\r\n const key = sha256(keyInput);\r\n\r\n // Convert amount to 8-byte little-endian\r\n const amountBytes = new Uint8Array(8);\r\n const view = new DataView(amountBytes.buffer);\r\n view.setFloat64(0, amount, true); // little-endian\r\n\r\n // XOR encrypt\r\n const encrypted = new Uint8Array(8);\r\n for (let i = 0; i < 8; i++) {\r\n encrypted[i] = amountBytes[i]! ^ key[i]!;\r\n }\r\n\r\n return encrypted;\r\n}\r\n\r\n/**\r\n * Decrypt an amount using the shared secret.\r\n *\r\n * @param encrypted - The 8-byte encrypted amount\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns The decrypted amount\r\n * @throws {Error} If encrypted is not exactly 8 bytes\r\n * @throws {Error} If sharedSecret is not exactly 32 bytes\r\n */\r\nexport function decryptAmount(encrypted: Uint8Array, sharedSecret: Uint8Array): number {\r\n // Validate inputs\r\n if (encrypted.length !== 8) {\r\n throw new Error(`Invalid encrypted amount: expected 8 bytes, got ${encrypted.length}`);\r\n }\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n // Create key material\r\n const keyInput = new Uint8Array(32 + 6);\r\n keyInput.set(sharedSecret, 0);\r\n keyInput.set(new TextEncoder().encode('amount'), 32);\r\n const key = sha256(keyInput);\r\n\r\n // XOR decrypt\r\n const decrypted = new Uint8Array(8);\r\n for (let i = 0; i < 8; i++) {\r\n decrypted[i] = encrypted[i]! ^ key[i]!;\r\n }\r\n\r\n // Convert from little-endian to number\r\n const view = new DataView(decrypted.buffer);\r\n return view.getFloat64(0, true); // little-endian\r\n}\r\n\r\nexport interface StealthDerivationWithSecret extends StealthDerivation {\r\n sharedSecret: Uint8Array;\r\n}\r\n\r\n/**\r\n * Derive a stealth address with the shared secret exposed.\r\n *\r\n * Similar to deriveStealthAddress but also returns the shared secret,\r\n * useful for applications that need amount encryption or other\r\n * shared secret-based features.\r\n *\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param viewPubKey - Receiver's 32-byte view public key\r\n * @param ephemeralPrivKey - Sender's 32-byte ephemeral private key\r\n * @returns Stealth derivation including the shared secret\r\n */\r\nexport function deriveStealthAddressWithSecret(\r\n spendPubKey: Uint8Array,\r\n viewPubKey: Uint8Array,\r\n ephemeralPrivKey: Uint8Array\r\n): StealthDerivationWithSecret {\r\n // Compute ephemeral public key R = r*G\r\n const R = scalarMultBase(ephemeralPrivKey);\r\n\r\n // Compute shared secret S = r*K_view\r\n const S = scalarMult(ephemeralPrivKey, viewPubKey);\r\n\r\n // Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Get view tag\r\n const tag = viewTag(S);\r\n\r\n return {\r\n stealthPubKey: P,\r\n stealthAddress: encodePublicKey(P),\r\n ephemeralPubKey: R,\r\n viewTag: tag,\r\n ephemeralPrivKey: ephemeralPrivKey,\r\n sharedSecret: S\r\n };\r\n}","import { generateMnemonic as _generateMnemonic, validateMnemonic as _validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';\r\nimport { wordlist } from '@scure/bip39/wordlists/english';\r\nimport type { StealthKeys } from './types.js';\r\nimport { scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\nconst textEncoder = new TextEncoder();\r\n\r\n/**\r\n * Generate a 12-word BIP-39 mnemonic phrase.\r\n */\r\nexport function generateMnemonic(): string {\r\n return _generateMnemonic(wordlist);\r\n}\r\n\r\n/**\r\n * Validate a mnemonic phrase against the BIP-39 english wordlist.\r\n */\r\nexport function validateMnemonic(mnemonic: string): boolean {\r\n return _validateMnemonic(mnemonic, wordlist);\r\n}\r\n\r\n/**\r\n * Derive stealth spend and view keys from a BIP-39 mnemonic.\r\n *\r\n * Uses domain-separated SHA-256 hashing of the BIP-39 seed to derive\r\n * two independent ed25519 scalars for the spend and view key pairs.\r\n */\r\nexport function mnemonicToStealthKeys(mnemonic: string, passphrase?: string): StealthKeys {\r\n if (!_validateMnemonic(mnemonic, wordlist)) {\r\n throw new Error('Invalid mnemonic phrase');\r\n }\r\n\r\n const seed = mnemonicToSeedSync(mnemonic, passphrase || '');\r\n\r\n const spendTag = textEncoder.encode('stealth-spend');\r\n const viewTag = textEncoder.encode('stealth-view');\r\n\r\n const spendInput = new Uint8Array(spendTag.length + seed.length);\r\n spendInput.set(spendTag, 0);\r\n spendInput.set(seed, spendTag.length);\r\n\r\n const viewInput = new Uint8Array(viewTag.length + seed.length);\r\n viewInput.set(viewTag, 0);\r\n viewInput.set(seed, viewTag.length);\r\n\r\n const spendPrivKey = hashToScalar(spendInput);\r\n const viewPrivKey = hashToScalar(viewInput);\r\n\r\n // Zero sensitive intermediates\r\n seed.fill(0);\r\n spendInput.fill(0);\r\n viewInput.fill(0);\r\n\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: { spendPubKey, viewPubKey },\r\n };\r\n}\r\n","import {\r\n Networks,\r\n Contract,\r\n nativeToScVal,\r\n Asset,\r\n TransactionBuilder,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\n\r\n/** Network configuration resolved from a network name. */\r\nexport interface NetworkConfig {\r\n networkPassphrase: string;\r\n rpcUrl: string;\r\n server: StellarSdk.rpc.Server;\r\n}\r\n\r\n/** Build network config from a network name. */\r\nexport function getNetworkConfig(network: 'local' | 'testnet'): NetworkConfig {\r\n const networkPassphrase = network === 'local'\r\n ? Networks.STANDALONE\r\n : Networks.TESTNET;\r\n\r\n const rpcUrl = network === 'local'\r\n ? 'http://localhost:8000/soroban/rpc'\r\n : 'https://soroban-testnet.stellar.org';\r\n\r\n const server = new StellarSdk.rpc.Server(rpcUrl, {\r\n allowHttp: network === 'local',\r\n });\r\n\r\n return { networkPassphrase, rpcUrl, server };\r\n}\r\n\r\n/** Create a dummy transaction for read-only contract simulation. */\r\nexport function createSimulationTx(\r\n operation: StellarSdk.xdr.Operation,\r\n networkPassphrase: string,\r\n): StellarSdk.Transaction {\r\n return new TransactionBuilder(\r\n new StellarSdk.Account('GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF', '0'),\r\n { fee: '100', networkPassphrase },\r\n )\r\n .addOperation(operation)\r\n .setTimeout(30)\r\n .build();\r\n}\r\n\r\n/** Execute a read-only contract call via simulation. Returns the decoded native result. */\r\nexport async function simulateReadOnly(\r\n contractId: string,\r\n method: string,\r\n args: StellarSdk.xdr.ScVal[],\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<unknown | null> {\r\n const contract = new Contract(contractId);\r\n const op = contract.call(method, ...args);\r\n const sim = await server.simulateTransaction(\r\n createSimulationTx(op, networkPassphrase),\r\n );\r\n\r\n if (StellarSdk.rpc.Api.isSimulationSuccess(sim) && sim.result?.retval) {\r\n return StellarSdk.scValToNative(sim.result.retval);\r\n }\r\n return null;\r\n}\r\n\r\n/** Resolve an asset string (\"native\", \"XLM\", or \"CODE:ISSUER\") to a SAC contract address. */\r\nexport function resolveTokenAddress(\r\n assetArg: string | undefined,\r\n networkPassphrase: string,\r\n): string {\r\n if (!assetArg || assetArg === 'native' || assetArg === 'XLM') {\r\n return Asset.native().contractId(networkPassphrase);\r\n }\r\n const parts = assetArg.split(':');\r\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\r\n throw new Error('Invalid asset format. Use CODE:ISSUER or \"native\"');\r\n }\r\n return new Asset(parts[0], parts[1]).contractId(networkPassphrase);\r\n}\r\n\r\n/** Poll for transaction confirmation. Throws on failure or timeout. */\r\nexport async function waitForTransaction(\r\n server: StellarSdk.rpc.Server,\r\n hash: string,\r\n): Promise<void> {\r\n let attempts = 0;\r\n while (attempts < 30) {\r\n await new Promise(resolve => setTimeout(resolve, 1000));\r\n try {\r\n const result = await server.getTransaction(hash);\r\n if (result.status === 'SUCCESS') return;\r\n if (result.status === 'FAILED') throw new Error('Transaction failed on-chain');\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : String(e);\r\n if (msg === 'Transaction failed on-chain') throw e;\r\n }\r\n attempts++;\r\n }\r\n throw new Error('Transaction confirmation timed out');\r\n}\r\n\r\n/** Fetch announcements from the stealth pool contract. */\r\nexport async function fetchAnnouncements(\r\n contractId: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<RawAnnouncement[]> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_announcements',\r\n [nativeToScVal(0, { type: 'u64' }), nativeToScVal(1000, { type: 'u64' })],\r\n server,\r\n networkPassphrase,\r\n );\r\n\r\n if (!result || !Array.isArray(result)) return [];\r\n\r\n return (result as unknown[]).map((ann: unknown) => {\r\n const a = ann as Record<string, unknown>;\r\n const stealthPk = new Uint8Array(a.stealth_pk as ArrayLike<number>);\r\n return {\r\n ephemeralPubKey: new Uint8Array(a.ephemeral_pk as ArrayLike<number>),\r\n viewTag: a.view_tag as number,\r\n stealthPubKey: stealthPk,\r\n stealthAddress: StrKey.encodeEd25519PublicKey(Buffer.from(stealthPk)),\r\n token: (a.token as { toString(): string })?.toString?.() || 'unknown',\r\n amount: BigInt((a.amount as string | number) || 0),\r\n };\r\n });\r\n}\r\n\r\nexport interface RawAnnouncement {\r\n ephemeralPubKey: Uint8Array;\r\n viewTag: number;\r\n stealthPubKey: Uint8Array;\r\n stealthAddress: string;\r\n token: string;\r\n amount: bigint;\r\n}\r\n\r\n/** Query the contract balance for a stealth key + token pair. */\r\nexport async function queryBalance(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_balance',\r\n [nativeToScVal(Buffer.from(stealthPk)), new StellarSdk.Address(tokenAddress).toScVal()],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\n/** Query the nonce for a stealth key. */\r\nexport async function queryNonce(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_nonce',\r\n [nativeToScVal(Buffer.from(stealthPk))],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\nfunction i128ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(16);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigInt64(0, value >> 64n);\r\n dv.setBigUint64(8, value & 0xFFFFFFFFFFFFFFFFn);\r\n return buf;\r\n}\r\n\r\nfunction u64ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(8);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigUint64(0, value);\r\n return buf;\r\n}\r\n\r\n/** Build the withdraw message hash. Must be byte-identical to the contract's build_withdraw_message. */\r\nexport function buildWithdrawMessage(\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n amount: bigint,\r\n destination: string,\r\n nonce: bigint,\r\n): Uint8Array {\r\n const tokenBytes = Buffer.from(tokenAddress, 'utf-8');\r\n const destBytes = Buffer.from(destination, 'utf-8');\r\n if (tokenBytes.length !== 56) throw new Error(`Token address must be 56 bytes StrKey, got ${tokenBytes.length}`);\r\n if (destBytes.length !== 56) throw new Error(`Destination must be 56 bytes StrKey, got ${destBytes.length}`);\r\n\r\n const amountBytes = i128ToBigEndian(amount);\r\n const nonceBytes = u64ToBigEndian(nonce);\r\n\r\n const msg = new Uint8Array(32 + 56 + 16 + 56 + 8);\r\n let offset = 0;\r\n msg.set(stealthPk, offset); offset += 32;\r\n msg.set(tokenBytes, offset); offset += 56;\r\n msg.set(amountBytes, offset); offset += 16;\r\n msg.set(destBytes, offset); offset += 56;\r\n msg.set(nonceBytes, offset);\r\n\r\n return sha256(msg);\r\n}\r\n","import {\r\n generateMetaAddress,\r\n encodeMetaAddress,\r\n decodeMetaAddress,\r\n deriveStealthAddressWithSecret,\r\n scanAnnouncements,\r\n recoverStealthPrivateKey,\r\n signWithStealthKey,\r\n generateMnemonic,\r\n mnemonicToStealthKeys,\r\n} from '@stealth/crypto';\r\nimport {\r\n Keypair,\r\n TransactionBuilder,\r\n Contract,\r\n nativeToScVal,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { randomBytes } from '@noble/hashes/utils';\r\nimport {\r\n getNetworkConfig,\r\n resolveTokenAddress,\r\n fetchAnnouncements,\r\n queryBalance,\r\n queryNonce,\r\n buildWithdrawMessage,\r\n waitForTransaction,\r\n} from './soroban.js';\r\nimport type {\r\n ClientConfig,\r\n StealthKeys,\r\n SendReceipt,\r\n SendOpts,\r\n Payment,\r\n Balance,\r\n WithdrawReceipt,\r\n WithdrawOpts,\r\n TransactionSigner,\r\n} from './types.js';\r\n\r\n/** Default contract addresses per network. */\r\nconst DEFAULT_CONTRACTS: Record<string, string> = {\r\n local: 'CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGABAX',\r\n};\r\n\r\n/**\r\n * High-level client for stealth payments on Stellar.\r\n *\r\n * Wraps DKSAP cryptography and Soroban contract interaction into a simple API.\r\n * Developers don't need to understand the underlying protocol to use this.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new StealthClient({ network: 'local', contractId: 'CXXX...' });\r\n *\r\n * // Generate keys\r\n * const keys = StealthClient.keygen();\r\n *\r\n * // Send 100 XLM to a stealth address\r\n * const receipt = await client.send(keys.metaAddress, 100, 'SXXX...');\r\n *\r\n * // Scan for received payments\r\n * const payments = await client.scan(keys);\r\n *\r\n * // Withdraw\r\n * await client.withdraw(payments[0].stealthAddress, 'GDEST...', {\r\n * keys,\r\n * feePayer: 'SXXX...',\r\n * });\r\n * ```\r\n */\r\nexport class StealthClient {\r\n private readonly contractId: string;\r\n private readonly networkPassphrase: string;\r\n private readonly server: StellarSdk.rpc.Server;\r\n\r\n constructor(config: ClientConfig) {\r\n this.contractId = config.contractId || DEFAULT_CONTRACTS[config.network] || '';\r\n const netConfig = getNetworkConfig(config.network);\r\n this.networkPassphrase = netConfig.networkPassphrase;\r\n this.server = netConfig.server;\r\n }\r\n\r\n /**\r\n * Generate a new random stealth key pair.\r\n * No network connection needed.\r\n */\r\n static keygen(): StealthKeys {\r\n const keys = generateMetaAddress();\r\n const metaAddress = encodeMetaAddress(keys.metaAddress);\r\n\r\n return {\r\n metaAddress,\r\n spendPubKey: Buffer.from(keys.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(keys.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(keys.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(keys.viewPrivKey).toString('hex'),\r\n };\r\n }\r\n\r\n /**\r\n * Generate stealth keys from a BIP-39 mnemonic.\r\n * Returns the mnemonic alongside the keys for backup.\r\n * No network connection needed.\r\n */\r\n static fromMnemonic(mnemonic?: string): StealthKeys & { mnemonic: string } {\r\n const phrase = mnemonic || generateMnemonic();\r\n const keys = mnemonicToStealthKeys(phrase);\r\n const metaAddress = encodeMetaAddress(keys.metaAddress);\r\n\r\n return {\r\n mnemonic: phrase,\r\n metaAddress,\r\n spendPubKey: Buffer.from(keys.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(keys.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(keys.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(keys.viewPrivKey).toString('hex'),\r\n };\r\n }\r\n\r\n /**\r\n * Send tokens to a stealth address.\r\n *\r\n * Derives a one-time stealth address from the recipient's meta-address,\r\n * deposits tokens into the pool contract, and records the announcement.\r\n *\r\n * Signing: by default the transaction is signed with `senderSecret` (a\r\n * Stellar secret key). If `opts.signTransaction` is provided, signing is\r\n * delegated to that external signer (e.g. a browser wallet) and the\r\n * `senderSecret` argument is treated as the sender's public key instead.\r\n *\r\n * @param metaAddress - Recipient's meta-address (st:stellar:... format)\r\n * @param amount - Amount in whole units (e.g. 100 = 100 XLM)\r\n * @param senderSecret - Sender's secret key, or public key when using `opts.signTransaction`\r\n * @param opts - Optional: asset to send, external signer\r\n */\r\n async send(\r\n metaAddress: string,\r\n amount: number,\r\n senderSecret: string,\r\n opts?: SendOpts,\r\n ): Promise<SendReceipt> {\r\n if (amount <= 0) throw new Error('Amount must be positive');\r\n\r\n const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);\r\n // With an external signer, `senderSecret` carries the public key (G...);\r\n // otherwise derive the public key from the secret as before.\r\n const senderPublicKey = opts?.signTransaction\r\n ? senderSecret\r\n : Keypair.fromSecret(senderSecret).publicKey();\r\n const tokenAddress = resolveTokenAddress(opts?.asset, this.networkPassphrase);\r\n const stroops = BigInt(Math.round(amount * 1e7));\r\n\r\n // Derive stealth address\r\n const ephemeralPrivKey = new Uint8Array(randomBytes(32));\r\n const stealth = deriveStealthAddressWithSecret(\r\n spendPubKey,\r\n viewPubKey,\r\n ephemeralPrivKey,\r\n );\r\n\r\n // Build and submit deposit transaction\r\n const contract = new Contract(this.contractId);\r\n const account = await this.server.getAccount(senderPublicKey);\r\n\r\n const depositTx = new TransactionBuilder(account, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'deposit',\r\n new StellarSdk.Address(senderPublicKey).toScVal(),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(stroops, { type: 'i128' }),\r\n nativeToScVal(Buffer.from(stealth.stealthPubKey)),\r\n nativeToScVal(Buffer.from(stealth.ephemeralPubKey)),\r\n nativeToScVal(stealth.viewTag, { type: 'u32' }),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(depositTx);\r\n const signed = await this.signTx(\r\n prepared,\r\n senderSecret,\r\n senderPublicKey,\r\n opts?.signTransaction,\r\n );\r\n const result = await this.server.sendTransaction(signed);\r\n\r\n if (result.status === 'ERROR') {\r\n throw new Error('Transaction submission failed');\r\n }\r\n if (result.status === 'PENDING') {\r\n await waitForTransaction(this.server, result.hash);\r\n }\r\n\r\n return {\r\n stealthAddress: stealth.stealthAddress,\r\n txHash: result.hash,\r\n };\r\n }\r\n\r\n /**\r\n * Sign a prepared transaction either with a local secret key (legacy path)\r\n * or by delegating to an external signer that returns signed XDR.\r\n *\r\n * @param prepared - The prepared transaction to sign\r\n * @param secretOrPublic - Secret key (local signing) or public key (external)\r\n * @param publicKey - Signer's public key (G...)\r\n * @param signer - Optional external signer; when present, no secret is used\r\n */\r\n private async signTx(\r\n prepared: StellarSdk.Transaction,\r\n secretOrPublic: string,\r\n publicKey: string,\r\n signer?: TransactionSigner,\r\n ): Promise<StellarSdk.Transaction> {\r\n if (signer) {\r\n const signedXdr = await signer(prepared.toXDR(), {\r\n networkPassphrase: this.networkPassphrase,\r\n address: publicKey,\r\n });\r\n const tx = TransactionBuilder.fromXDR(signedXdr, this.networkPassphrase);\r\n return tx as StellarSdk.Transaction;\r\n }\r\n prepared.sign(Keypair.fromSecret(secretOrPublic));\r\n return prepared;\r\n }\r\n\r\n /**\r\n * Scan for stealth payments you received.\r\n *\r\n * Uses the view key to detect which announcements are yours,\r\n * then queries the contract for current balances.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async scan(keys: StealthKeys): Promise<Payment[]> {\r\n const viewPrivKey = Buffer.from(keys.viewPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(keys.spendPubKey, 'hex');\r\n\r\n const announcements = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (announcements.length === 0) return [];\r\n\r\n const matches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map(a => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const payments: Payment[] = [];\r\n\r\n for (const match of matches) {\r\n if (!match) continue;\r\n const ann = announcements.find(a => a.stealthAddress === match.address);\r\n if (!ann) continue;\r\n\r\n const balance = await queryBalance(\r\n this.contractId,\r\n ann.stealthPubKey,\r\n ann.token,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) continue;\r\n\r\n payments.push({\r\n stealthAddress: ann.stealthAddress,\r\n ephemeralPubKey: Buffer.from(ann.ephemeralPubKey).toString('hex'),\r\n token: ann.token,\r\n amount: Number(balance) / 1e7,\r\n });\r\n }\r\n\r\n return payments;\r\n }\r\n\r\n /**\r\n * Get balances for all your stealth addresses in the pool.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async balance(keys: StealthKeys): Promise<Balance[]> {\r\n const payments = await this.scan(keys);\r\n return payments.map(p => ({\r\n stealthAddress: p.stealthAddress,\r\n token: p.token,\r\n amount: p.amount,\r\n }));\r\n }\r\n\r\n /**\r\n * Withdraw tokens from the stealth pool.\r\n *\r\n * Recovers the stealth private key, signs a withdraw message,\r\n * and submits the transaction. Use `opts.relay` for privacy-preserving\r\n * withdrawal via a relayer.\r\n *\r\n * @param stealthAddress - The stealth address to withdraw from\r\n * @param destination - Destination Stellar address (G...)\r\n * @param opts - Withdraw options (keys, feePayer, optional relay/asset/amount)\r\n */\r\n async withdraw(\r\n stealthAddress: string,\r\n destination: string,\r\n opts: WithdrawOpts,\r\n ): Promise<WithdrawReceipt> {\r\n if (!StrKey.isValidEd25519PublicKey(stealthAddress)) {\r\n throw new Error('Invalid stealth address');\r\n }\r\n if (!StrKey.isValidEd25519PublicKey(destination)) {\r\n throw new Error('Invalid destination address');\r\n }\r\n\r\n const viewPrivKey = Buffer.from(opts.keys.viewPrivKey, 'hex');\r\n const spendPrivKey = Buffer.from(opts.keys.spendPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(opts.keys.spendPubKey, 'hex');\r\n const tokenAddress = resolveTokenAddress(opts.asset, this.networkPassphrase);\r\n\r\n // Find matching announcement\r\n const announcements = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n const allMatches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map(a => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const matchedAnn = announcements.find(a => {\r\n if (a.stealthAddress !== stealthAddress) return false;\r\n return allMatches.some(m => m?.address === stealthAddress);\r\n });\r\n\r\n if (!matchedAnn) {\r\n throw new Error('Could not find announcement for this stealth address');\r\n }\r\n\r\n // Recover stealth private key\r\n const stealthPrivKey = recoverStealthPrivateKey(\r\n spendPrivKey,\r\n viewPrivKey,\r\n matchedAnn.ephemeralPubKey,\r\n );\r\n\r\n // Get balance\r\n const balance = await queryBalance(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) throw new Error('Stealth address has no balance in the pool');\r\n\r\n // Determine amount\r\n let withdrawAmount: bigint;\r\n if (opts.amount !== undefined) {\r\n withdrawAmount = BigInt(Math.round(opts.amount * 1e7));\r\n if (withdrawAmount > balance) {\r\n throw new Error(`Requested ${opts.amount} but balance is ${Number(balance) / 1e7}`);\r\n }\r\n } else {\r\n withdrawAmount = balance;\r\n }\r\n\r\n // Get nonce and build signed message\r\n const currentNonce = await queryNonce(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n const nonce = currentNonce + 1n;\r\n\r\n const messageHash = buildWithdrawMessage(\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n withdrawAmount,\r\n destination,\r\n nonce,\r\n );\r\n\r\n const signature = signWithStealthKey(messageHash, stealthPrivKey);\r\n\r\n // Resolve the fee payer. With an external signer we use feePayerAddress\r\n // (a public key); otherwise we derive it from the feePayer secret.\r\n if (!opts.signTransaction && !opts.feePayer) {\r\n throw new Error('Provide either opts.feePayer or opts.signTransaction + opts.feePayerAddress');\r\n }\r\n if (opts.signTransaction && !opts.feePayerAddress) {\r\n throw new Error('opts.feePayerAddress is required when using opts.signTransaction');\r\n }\r\n const feePayerPublicKey = opts.signTransaction\r\n ? (opts.feePayerAddress as string)\r\n : Keypair.fromSecret(opts.feePayer as string).publicKey();\r\n\r\n // Build transaction\r\n const contract = new Contract(this.contractId);\r\n const feePayerAccount = await this.server.getAccount(feePayerPublicKey);\r\n\r\n const withdrawTx = new TransactionBuilder(feePayerAccount, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'withdraw',\r\n nativeToScVal(Buffer.from(matchedAnn.stealthPubKey)),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(withdrawAmount, { type: 'i128' }),\r\n new StellarSdk.Address(destination).toScVal(),\r\n nativeToScVal(nonce, { type: 'u64' }),\r\n nativeToScVal(Buffer.from(signature)),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(withdrawTx);\r\n const signedTx = await this.signTx(\r\n prepared,\r\n opts.feePayer ?? '',\r\n feePayerPublicKey,\r\n opts.signTransaction,\r\n );\r\n\r\n // Submit (direct or via relay)\r\n let txHash: string;\r\n\r\n if (opts.relay) {\r\n const url = opts.relay.endsWith('/relay') ? opts.relay : `${opts.relay}/relay`;\r\n const res = await fetch(url, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ xdr: signedTx.toEnvelope().toXDR('base64') }),\r\n });\r\n if (!res.ok) {\r\n const err = await res.json() as { error?: string };\r\n throw new Error(`Relay error: ${err.error || 'unknown'}`);\r\n }\r\n const data = await res.json() as { txHash: string };\r\n txHash = data.txHash;\r\n } else {\r\n const result = await this.server.sendTransaction(signedTx);\r\n if (result.status === 'ERROR') throw new Error('Transaction submission failed');\r\n if (result.status === 'PENDING') {\r\n await waitForTransaction(this.server, result.hash);\r\n }\r\n txHash = result.hash;\r\n }\r\n\r\n return {\r\n txHash,\r\n amount: Number(withdrawAmount) / 1e7,\r\n };\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../crypto/src/errors.ts","../../crypto/src/ed25519.ts","../../crypto/src/keys.ts","../../crypto/src/hash.ts","../../crypto/src/stellar-keys.ts","../../crypto/src/scan.ts","../../crypto/src/scalar.ts","../../crypto/src/recover.ts","../../crypto/src/advanced.ts","../../crypto/src/hd.ts","../../crypto/src/derive-signature.ts","../src/errors.ts","../src/soroban.ts","../src/wallet.ts","../src/horizon.ts","../src/indexer.ts","../src/stroops.ts","../src/relayer.ts","../src/relayerPool.ts","../src/methods/sign.ts","../src/methods/restore.ts","../src/methods/pool.ts","../src/methods/account.ts","../src/methods/spp.ts","../src/client.ts","../src/session.ts"],"names":["randomBytes","bytesToNumberLE","numberToBytesLE","ed25519","sha256","sha512","_generateMnemonic","wordlist","_validateMnemonic","mnemonicToSeedSync","viewTag","textEncoder","Networks","StellarSdk","TransactionBuilder","Contract","Asset","nativeToScVal","StrKey","Transaction","TIMED_OUT","withTimeout","Keypair","rpc","BASE_FEE","Operation","StellarSdk2","txHash","MuxedAccount","Memo","Account","Claimant","finalCursor","withCreate"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Custom error types for crypto operations\r\n */\r\n\r\n/**\r\n * Error thrown when a point operation results in the point at infinity\r\n */\r\nexport class PointAtInfinity extends Error {\r\n constructor(operation: string) {\r\n super(`Point at infinity encountered in ${operation}`);\r\n this.name = 'PointAtInfinity';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a public key is not on the ed25519 curve\r\n */\r\nexport class InvalidPublicKey extends Error {\r\n constructor(message = 'Invalid public key: not on curve') {\r\n super(message);\r\n this.name = 'InvalidPublicKey';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a scalar value is invalid (e.g., zero where not allowed)\r\n */\r\nexport class InvalidScalar extends Error {\r\n constructor(message = 'Invalid scalar value') {\r\n super(message);\r\n this.name = 'InvalidScalar';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when meta-address encoding/decoding fails\r\n */\r\nexport class InvalidMetaAddress extends Error {\r\n constructor(message = 'Invalid meta-address format') {\r\n super(message);\r\n this.name = 'InvalidMetaAddress';\r\n }\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { randomBytes } from '@noble/hashes/utils';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { PointAtInfinity, InvalidPublicKey, InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Curve order L for ed25519\r\n */\r\nexport const L = 2n ** 252n + 27742317777372353535851937790883648493n;\r\n\r\n/**\r\n * Generate a random scalar reduced modulo L.\r\n *\r\n * Draws 32 cryptographically secure random bytes, interprets them as a\r\n * little-endian integer, and reduces modulo the curve order L.\r\n *\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n */\r\nexport function generateRandomScalar(): Uint8Array {\r\n const bytes = randomBytes(32);\r\n const scalar = bytesToNumberLE(bytes) % L;\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Validate that a point is a valid ed25519 public key.\r\n *\r\n * Accepts only points that lie on the curve AND belong to the prime-order\r\n * subgroup (torsion-free). This rejects the identity and the small-order\r\n * (torsion) points, preventing small-subgroup attacks through the ECDH and\r\n * point-addition paths that flow through `R`, `K_view`, and `K_spend`.\r\n *\r\n * @param point 32-byte compressed point\r\n * @returns true if valid\r\n * @throws InvalidPublicKey if not on curve or not in the prime-order subgroup\r\n */\r\nexport function validatePoint(point: Uint8Array): boolean {\r\n if (point.length !== 32) {\r\n throw new InvalidPublicKey('Invalid point length');\r\n }\r\n\r\n let p: InstanceType<typeof ed25519.ExtendedPoint>;\r\n try {\r\n // This will throw if point is not on curve\r\n p = ed25519.ExtendedPoint.fromHex(point);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) throw e;\r\n throw new InvalidPublicKey('Point not on curve');\r\n }\r\n\r\n // Reject the identity (point at infinity) explicitly: it is technically\r\n // torsion-free per noble but is a degenerate, order-1 key.\r\n if (p.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new InvalidPublicKey('Point is the identity element');\r\n }\r\n\r\n // Reject small-order (torsion) points not in the prime-order subgroup.\r\n if (!p.isTorsionFree()) {\r\n throw new InvalidPublicKey('Point is not in the prime-order subgroup');\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Add two ed25519 points.\r\n * @param p1 First point (32-byte compressed)\r\n * @param p2 Second point (32-byte compressed)\r\n * @returns Result point (32-byte compressed)\r\n * @throws PointAtInfinity if result is point at infinity\r\n * @throws InvalidPublicKey if points are not on curve\r\n */\r\nexport function pointAdd(p1: Uint8Array, p2: Uint8Array): Uint8Array {\r\n if (p1.length !== 32) throw new InvalidPublicKey('Invalid p1 length');\r\n if (p2.length !== 32) throw new InvalidPublicKey('Invalid p2 length');\r\n\r\n // Validate both points are on curve\r\n validatePoint(p1);\r\n validatePoint(p2);\r\n\r\n const point1 = ed25519.ExtendedPoint.fromHex(p1);\r\n const point2 = ed25519.ExtendedPoint.fromHex(p2);\r\n const result = point1.add(point2);\r\n\r\n // Check for point at infinity\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('pointAdd');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with generator point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n */\r\nexport function scalarMultBase(scalar: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const result = ed25519.ExtendedPoint.BASE.multiply(s);\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with arbitrary point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param point 32-byte compressed point\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n * @throws InvalidPublicKey if point is not on curve\r\n * @throws PointAtInfinity if result is point at infinity\r\n */\r\nexport function scalarMult(scalar: Uint8Array, point: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n if (point.length !== 32) throw new InvalidPublicKey('Invalid point length');\r\n\r\n // Validate point is on curve\r\n validatePoint(point);\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const p = ed25519.ExtendedPoint.fromHex(point);\r\n const result = p.multiply(s);\r\n\r\n // Check for point at infinity (should not happen with valid inputs)\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('scalarMult');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Add two scalars modulo curve order L.\r\n * @param s1 First scalar (32-byte, little-endian)\r\n * @param s2 Second scalar (32-byte, little-endian)\r\n * @returns Result scalar (32-byte, little-endian)\r\n * @throws InvalidScalar if inputs have wrong length or the sum reduces to zero\r\n */\r\nexport function scalarAdd(s1: Uint8Array, s2: Uint8Array): Uint8Array {\r\n if (s1.length !== 32) throw new InvalidScalar('Invalid s1 length');\r\n if (s2.length !== 32) throw new InvalidScalar('Invalid s2 length');\r\n\r\n const a = bytesToNumberLE(s1) % L;\r\n const b = bytesToNumberLE(s2) % L;\r\n const result = (a + b) % L;\r\n\r\n // A zero result yields a degenerate scalar whose public key is the identity;\r\n // mirror scalarMultBase's zero guard and reject it.\r\n if (result === 0n) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n\r\n return numberToBytesLE(result, 32);\r\n}","import { sha256 } from '@noble/hashes/sha256';\r\nimport type { StealthKeys, StealthMetaAddress } from './types.js';\r\nimport { scalarMultBase, validatePoint, generateRandomScalar } from './ed25519.js';\r\nimport { InvalidMetaAddress, InvalidPublicKey } from './errors.js';\r\n\r\n/**\r\n * Generate a new stealth meta-address with random keys.\r\n *\r\n * Creates a complete stealth key pair using cryptographically secure\r\n * random number generation. The resulting keys can be used for:\r\n * - Receiving stealth payments (using the meta-address)\r\n * - Scanning for incoming payments (using view private key)\r\n * - Spending from stealth addresses (using spend private key)\r\n *\r\n * @returns Complete stealth keys including private keys and meta-address\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n *\r\n * // Share the meta-address publicly\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log('Share this:', encoded);\r\n *\r\n * // Keep private keys secure\r\n * saveSecurely(keys.spendPrivKey, keys.viewPrivKey);\r\n * ```\r\n */\r\nexport function generateMetaAddress(): StealthKeys {\r\n // Generate two random 32-byte scalars (reduced mod L)\r\n const spendPrivKey = generateRandomScalar();\r\n const viewPrivKey = generateRandomScalar();\r\n\r\n // Derive public keys\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: {\r\n spendPubKey,\r\n viewPubKey,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Encode a stealth meta-address to a string format with checksum.\r\n *\r\n * Encodes the meta-address into a shareable string format that includes:\r\n * - Protocol identifier (\"shade:stellar:\")\r\n * - Concatenated public keys (spend || view)\r\n * - CRC32 checksum for error detection\r\n *\r\n * @param meta - Stealth meta-address containing spend and view public keys\r\n * @returns Encoded string in format \"shade:stellar:<hex(spend_pk || view_pk)><checksum>\"\r\n * @throws {InvalidMetaAddress} If public keys are invalid length or not on curve\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log(encoded); // \"shade:stellar:abc123...def456\"\r\n *\r\n * // Share this encoded string with senders\r\n * publishMetaAddress(encoded);\r\n * ```\r\n */\r\nexport function encodeMetaAddress(meta: StealthMetaAddress): string {\r\n if (meta.spendPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid spend public key length');\r\n }\r\n if (meta.viewPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid view public key length');\r\n }\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(meta.spendPubKey);\r\n validatePoint(meta.viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n // Concatenate both public keys\r\n const payload = new Uint8Array(64);\r\n payload.set(meta.spendPubKey, 0);\r\n payload.set(meta.viewPubKey, 32);\r\n\r\n // Calculate checksum (last 4 bytes of SHA-256)\r\n const hash = sha256(payload);\r\n const checksum = hash.slice(28, 32);\r\n\r\n // Combine payload and checksum\r\n const combined = new Uint8Array(68);\r\n combined.set(payload, 0);\r\n combined.set(checksum, 64);\r\n\r\n // Convert to hex\r\n const hex = Array.from(combined)\r\n .map((b) => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n\r\n return `shade:stellar:${hex}`;\r\n}\r\n\r\n/**\r\n * Decode a string-encoded stealth meta-address with checksum validation.\r\n *\r\n * Parses an encoded meta-address string and validates:\r\n * - Correct format and prefix\r\n * - Valid hex encoding\r\n * - Checksum integrity\r\n * - Public keys are on curve\r\n *\r\n * @param encoded - Encoded meta-address string (\"shade:stellar:...\")\r\n * @returns Decoded stealth meta-address with public keys\r\n * @throws {InvalidMetaAddress} If format, checksum, or keys are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * const encoded = \"shade:stellar:abc123...def456\";\r\n * const meta = decodeMetaAddress(encoded);\r\n *\r\n * // Use for deriving stealth addresses\r\n * const stealth = deriveStealthAddress(meta);\r\n * ```\r\n */\r\nexport function decodeMetaAddress(encoded: string): StealthMetaAddress {\r\n if (!encoded.startsWith('shade:stellar:')) {\r\n throw new InvalidMetaAddress('Invalid meta-address prefix');\r\n }\r\n\r\n const hex = encoded.slice(14); // Remove \"shade:stellar:\" prefix\r\n if (hex.length !== 136) {\r\n // 64 bytes payload + 4 bytes checksum = 68 bytes = 136 hex chars\r\n throw new InvalidMetaAddress('Invalid meta-address length');\r\n }\r\n\r\n // Strictly validate the full hex payload before parsing. parseInt would\r\n // silently accept a malformed nibble (e.g. \"1g\" -> 1), so reject anything\r\n // that is not exactly 136 lowercase/uppercase hex characters.\r\n if (!/^[0-9a-fA-F]{136}$/.test(hex)) {\r\n throw new InvalidMetaAddress('Invalid hex encoding');\r\n }\r\n\r\n // Parse hex to bytes\r\n const combined = new Uint8Array(68);\r\n for (let i = 0; i < 68; i++) {\r\n combined[i] = parseInt(hex.substr(i * 2, 2), 16);\r\n }\r\n\r\n // Split payload and checksum\r\n const payload = combined.slice(0, 64);\r\n const checksum = combined.slice(64, 68);\r\n\r\n // Verify checksum\r\n const hash = sha256(payload);\r\n const expectedChecksum = hash.slice(28, 32);\r\n\r\n let checksumValid = true;\r\n for (let i = 0; i < 4; i++) {\r\n if (checksum[i] !== expectedChecksum[i]) {\r\n checksumValid = false;\r\n break;\r\n }\r\n }\r\n\r\n if (!checksumValid) {\r\n throw new InvalidMetaAddress('Invalid checksum');\r\n }\r\n\r\n const spendPubKey = payload.slice(0, 32);\r\n const viewPubKey = payload.slice(32, 64);\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(spendPubKey);\r\n validatePoint(viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key in meta-address: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n return {\r\n spendPubKey,\r\n viewPubKey,\r\n };\r\n}","import { sha256 } from '@noble/hashes/sha256';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L } from './ed25519.js';\r\nimport { InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Hash data to a scalar value modulo curve order L.\r\n *\r\n * Implements the hash-to-scalar function used in DKSAP for deriving\r\n * the blinding factor from the shared secret.\r\n *\r\n * @param data - Input data to hash (typically a 32-byte shared secret)\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n * @throws {InvalidScalar} If hash produces zero scalar (extremely unlikely)\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(ephemeralPrivKey, viewPubKey);\r\n * const s = hashToScalar(sharedSecret);\r\n * // Use s as blinding factor for stealth key derivation\r\n * ```\r\n */\r\nexport function hashToScalar(data: Uint8Array): Uint8Array {\r\n const hash = sha256(data);\r\n const scalar = bytesToNumberLE(hash) % L;\r\n\r\n // In the extremely unlikely event the hash produces zero mod L\r\n if (scalar === 0n) {\r\n throw new InvalidScalar('Hash produced zero scalar');\r\n }\r\n\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Extract view tag from shared secret.\r\n *\r\n * The view tag is the first byte of SHA256(shared_secret) and enables\r\n * ~2x faster scanning by filtering announcements before expensive EC operations.\r\n *\r\n * @param sharedSecret - 32-byte shared secret from ECDH\r\n * @returns Single byte view tag (0-255)\r\n * @throws {Error} If shared secret is not 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(viewPrivKey, ephemeralPubKey);\r\n * const tag = viewTag(sharedSecret);\r\n * // Use tag for fast announcement filtering\r\n * ```\r\n */\r\nexport function viewTag(sharedSecret: Uint8Array): number {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error('Invalid shared secret length');\r\n }\r\n const hash = sha256(sharedSecret);\r\n return hash[0]!;\r\n}","/**\r\n * Stellar StrKey encoding (base32check) for ed25519 public keys.\r\n * This module provides pure TypeScript implementation without @stellar/stellar-sdk dependency.\r\n */\r\n\r\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\r\nconst VERSION_BYTE_PUBLIC_KEY = 6 << 3; // G addresses\r\n\r\n/**\r\n * CRC16-XModem checksum implementation.\r\n */\r\nfunction crc16XModem(data: Uint8Array): number {\r\n let crc = 0x0000;\r\n for (let i = 0; i < data.length; i++) {\r\n crc ^= data[i]! << 8;\r\n for (let j = 0; j < 8; j++) {\r\n if (crc & 0x8000) {\r\n crc = (crc << 1) ^ 0x1021;\r\n } else {\r\n crc = crc << 1;\r\n }\r\n }\r\n }\r\n return crc & 0xffff;\r\n}\r\n\r\n/**\r\n * Base32 encode (RFC 4648) without padding.\r\n */\r\nfunction base32Encode(data: Uint8Array): string {\r\n let bits = 0;\r\n let value = 0;\r\n let output = '';\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n value = (value << 8) | data[i]!;\r\n bits += 8;\r\n\r\n while (bits >= 5) {\r\n output += ALPHABET[(value >>> (bits - 5)) & 31];\r\n bits -= 5;\r\n }\r\n }\r\n\r\n if (bits > 0) {\r\n output += ALPHABET[(value << (5 - bits)) & 31];\r\n }\r\n\r\n return output;\r\n}\r\n\r\n/**\r\n * Base32 decode (RFC 4648).\r\n */\r\nfunction base32Decode(str: string): Uint8Array {\r\n const output: number[] = [];\r\n let bits = 0;\r\n let value = 0;\r\n\r\n for (let i = 0; i < str.length; i++) {\r\n const idx = ALPHABET.indexOf(str[i]!);\r\n if (idx === -1) {\r\n throw new Error(`Invalid base32 character: ${str[i]}`);\r\n }\r\n\r\n value = (value << 5) | idx;\r\n bits += 5;\r\n\r\n while (bits >= 8) {\r\n output.push((value >>> (bits - 8)) & 255);\r\n bits -= 8;\r\n }\r\n }\r\n\r\n return new Uint8Array(output);\r\n}\r\n\r\n/**\r\n * Encode ed25519 public key to Stellar address format (G...).\r\n *\r\n * Implements Stellar's StrKey encoding (SEP-23) using base32check format.\r\n *\r\n * @param pubKey - 32-byte ed25519 public key\r\n * @returns Stellar address in StrKey format (G...)\r\n * @throws {Error} If public key is not exactly 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const pubKey = new Uint8Array(32); // Your public key\r\n * const address = encodePublicKey(pubKey);\r\n * console.log(address); // \"GABC...XYZ\"\r\n * ```\r\n */\r\nexport function encodePublicKey(pubKey: Uint8Array): string {\r\n if (pubKey.length !== 32) {\r\n throw new Error('Public key must be 32 bytes');\r\n }\r\n\r\n const versionedPayload = new Uint8Array(33);\r\n versionedPayload[0] = VERSION_BYTE_PUBLIC_KEY;\r\n versionedPayload.set(pubKey, 1);\r\n\r\n const checksum = crc16XModem(versionedPayload);\r\n const checksumBytes = new Uint8Array(2);\r\n checksumBytes[0] = checksum & 0xff;\r\n checksumBytes[1] = (checksum >>> 8) & 0xff;\r\n\r\n const fullPayload = new Uint8Array(35);\r\n fullPayload.set(versionedPayload, 0);\r\n fullPayload.set(checksumBytes, 33);\r\n\r\n return base32Encode(fullPayload);\r\n}\r\n\r\n/**\r\n * Decode Stellar address to ed25519 public key.\r\n *\r\n * Implements Stellar's StrKey decoding (SEP-23) with checksum validation.\r\n *\r\n * @param address - Stellar address in StrKey format (G...)\r\n * @returns 32-byte ed25519 public key\r\n * @throws {Error} If address format is invalid or checksum fails\r\n *\r\n * @example\r\n * ```typescript\r\n * const address = \"GABC...XYZ\";\r\n * const pubKey = decodePublicKey(address);\r\n * console.log(pubKey.length); // 32\r\n * ```\r\n */\r\nexport function decodePublicKey(address: string): Uint8Array {\r\n if (!address.startsWith('G')) {\r\n throw new Error('Invalid Stellar address: must start with G');\r\n }\r\n\r\n const decoded = base32Decode(address);\r\n if (decoded.length !== 35) {\r\n throw new Error('Invalid Stellar address: incorrect length');\r\n }\r\n\r\n const versionByte = decoded[0]!;\r\n if (versionByte !== VERSION_BYTE_PUBLIC_KEY) {\r\n throw new Error('Invalid Stellar address: wrong version byte');\r\n }\r\n\r\n const versionedPayload = decoded.slice(0, 33);\r\n const providedChecksum = (decoded[34]! << 8) | decoded[33]!;\r\n const calculatedChecksum = crc16XModem(versionedPayload);\r\n\r\n if (providedChecksum !== calculatedChecksum) {\r\n throw new Error('Invalid Stellar address: checksum mismatch');\r\n }\r\n\r\n return decoded.slice(1, 33);\r\n}","import type { Announcement, StealthAddress } from './types.js';\r\nimport { scalarMult, pointAdd, scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\n\r\n/**\r\n * Check if a view tag matches for a given ephemeral public key.\r\n *\r\n * This is a fast pre-filter before doing the expensive EC operations.\r\n * Only computes the shared secret and extracts the first byte for comparison.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param expectedTag - Expected view tag from announcement (0-255)\r\n * @returns Object with match result and shared secret if matched\r\n * @throws {Error} If key lengths are invalid or tag is out of range\r\n *\r\n * @example\r\n * ```typescript\r\n * // Fast filtering before full verification\r\n * const result = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n * if (result.matches) {\r\n * // Use the shared secret for further verification\r\n * const s = hashToScalar(result.sharedSecret);\r\n * }\r\n * ```\r\n */\r\nexport function checkViewTag(\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n expectedTag: number\r\n): { matches: boolean; sharedSecret?: Uint8Array } {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n if (expectedTag < 0 || expectedTag > 255) {\r\n throw new Error('Invalid view tag');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Extract and compare view tag (first byte of SHA256(S))\r\n const computedTag = viewTag(S);\r\n\r\n if (computedTag === expectedTag) {\r\n return { matches: true, sharedSecret: S };\r\n }\r\n return { matches: false };\r\n}\r\n\r\n/**\r\n * Scan announcements to find stealth addresses belonging to the receiver.\r\n *\r\n * This implements an optimized two-pass scanning algorithm:\r\n * - Pass 1: Filter by view tag (cheap byte comparison)\r\n * - Pass 2: Full EC math (scalarMult + pointAdd) only on tag matches\r\n *\r\n * This optimization provides ~2x speedup for large announcement sets\r\n * by avoiding expensive EC operations on non-matching announcements.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param announcements - List of announcements to scan\r\n * @returns Array of stealth addresses belonging to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Scan blockchain announcements\r\n * const announcements = await fetchAnnouncements();\r\n * const myAddresses = scanAnnouncements(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcements\r\n * );\r\n *\r\n * // Check balances of discovered addresses\r\n * for (const addr of myAddresses) {\r\n * const balance = await getBalance(addr.address);\r\n * console.log(`${addr.address}: ${balance} XLM`);\r\n * }\r\n * ```\r\n */\r\nexport function scanAnnouncements(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n announcements: Announcement[]\r\n): StealthAddress[] {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n\r\n const results: StealthAddress[] = [];\r\n\r\n // Two-pass scanning for optimization\r\n // Pass 1: Quick view tag filtering with shared secret caching\r\n const tagMatches: Array<{ announcement: Announcement; sharedSecret: Uint8Array }> = [];\r\n for (const announcement of announcements) {\r\n // A malicious or malformed announcement may carry an invalid ephemeral\r\n // key (e.g. a small-order/torsion point). Skip it rather than aborting\r\n // the entire scan.\r\n try {\r\n const tagResult = checkViewTag(\r\n viewPrivKey,\r\n announcement.ephemeralPubKey,\r\n announcement.viewTag\r\n );\r\n if (tagResult.matches && tagResult.sharedSecret) {\r\n tagMatches.push({ announcement, sharedSecret: tagResult.sharedSecret });\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // Pass 2: Full verification only on tag matches (reusing shared secrets)\r\n for (const { announcement, sharedSecret } of tagMatches) {\r\n // Hash to scalar s = SHA256(S) mod L (using cached shared secret)\r\n const s = hashToScalar(sharedSecret);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n if (computedAddress === announcement.stealthAddress) {\r\n results.push({\r\n publicKey: P,\r\n address: computedAddress,\r\n });\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Check if a specific stealth address belongs to the receiver.\r\n *\r\n * Performs full DKSAP verification to determine ownership of a stealth address.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param stealthAddress - Stellar address to check (G... format)\r\n * @returns True if the stealth address belongs to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Check if a payment is for you\r\n * const isMine = isMyStealthAddress(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcement.ephemeralPubKey,\r\n * announcement.stealthAddress\r\n * );\r\n *\r\n * if (isMine) {\r\n * console.log('Found payment to:', announcement.stealthAddress);\r\n * }\r\n * ```\r\n */\r\nexport function isMyStealthAddress(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n stealthAddress: string\r\n): boolean {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Hash to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n return computedAddress === stealthAddress;\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { sha512 } from '@noble/hashes/sha512';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L, scalarMultBase } from './ed25519.js';\r\nimport { InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Sign a message with a raw 32-byte ed25519 scalar — the signing core shared\r\n * by {@link StealthScalar.sign} and `signWithStealthKey`'s deprecated\r\n * raw-bytes path. Module-internal: not re-exported from the package index.\r\n *\r\n * Standard ed25519.sign() hashes a SEED to derive the signing scalar, but\r\n * stealth private keys are already raw scalars from modular addition\r\n * (k_spend + s mod L). This constructs a valid ed25519 signature directly\r\n * from the raw scalar, producing signatures that verify with standard\r\n * ed25519.verify() against the corresponding public key (scalar * G).\r\n *\r\n * @param message - The message to sign\r\n * @param privateScalar - 32-byte raw scalar (stealth private key)\r\n * @returns 64-byte ed25519 signature (R || S)\r\n */\r\nexport function signWithRawScalarBytes(\r\n message: Uint8Array,\r\n privateScalar: Uint8Array,\r\n): Uint8Array {\r\n if (privateScalar.length !== 32) {\r\n throw new Error('Invalid stealth private key length');\r\n }\r\n if (message.length === 0) {\r\n throw new Error('Message cannot be empty');\r\n }\r\n\r\n const a = bytesToNumberLE(privateScalar) % L;\r\n const pubKeyBytes = scalarMultBase(privateScalar);\r\n\r\n // Deterministic nonce: r = SHA-512(privateScalar || message) mod L\r\n const nonceInput = new Uint8Array(32 + message.length);\r\n nonceInput.set(privateScalar, 0);\r\n nonceInput.set(message, 32);\r\n const r = bytesToNumberLE(sha512(nonceInput)) % L;\r\n\r\n // Zero the sensitive intermediate (contains the private scalar).\r\n nonceInput.fill(0);\r\n\r\n const R = ed25519.ExtendedPoint.BASE.multiply(r);\r\n const Rbytes = R.toRawBytes();\r\n\r\n // Challenge: k = SHA-512(R || pubKey || message) mod L\r\n const challengeInput = new Uint8Array(32 + 32 + message.length);\r\n challengeInput.set(Rbytes, 0);\r\n challengeInput.set(pubKeyBytes, 32);\r\n challengeInput.set(message, 64);\r\n const k = bytesToNumberLE(sha512(challengeInput)) % L;\r\n\r\n // challengeInput holds only public data (R, pubKey, message); zeroing it is\r\n // uniform zeroization hygiene, not a secrecy requirement.\r\n challengeInput.fill(0);\r\n\r\n // Response: S = (r + k * a) mod L\r\n const S = (r + k * a) % L;\r\n\r\n const sig = new Uint8Array(64);\r\n sig.set(Rbytes, 0);\r\n sig.set(numberToBytesLE(S, 32), 32);\r\n return sig;\r\n}\r\n\r\n/**\r\n * A recovered stealth private key: a raw ed25519 SCALAR (k_spend + s mod L),\r\n * wrapped so it can only be used correctly.\r\n *\r\n * WHY A CLASS AND NOT A `Uint8Array`: a raw scalar is NOT an ed25519 seed.\r\n * Every seed-based keypair API — `Keypair.fromRawEd25519Seed()`,\r\n * `ed25519.sign()`, wallet imports — HASHES its input to derive a different\r\n * signing scalar, producing a keypair whose public key does not match the\r\n * stealth address. Signatures from such a keypair are rejected on-chain and\r\n * the funds become PERMANENTLY UNWITHDRAWABLE. Because this wrapper is not\r\n * structurally a `Uint8Array` (the private field makes it incompatible),\r\n * `Keypair.fromRawEd25519Seed(scalar)` and `Buffer.from(scalar)` are compile\r\n * errors instead of silent fund loss.\r\n *\r\n * Use {@link sign} to sign, {@link publicKey} to verify correspondence with\r\n * the stealth address, and {@link zeroize} to clear the key from memory once\r\n * done. {@link dangerouslyToRawBytes} is the explicit, misuse-warned escape\r\n * hatch for raw-scalar interop.\r\n */\r\nexport class StealthScalar {\r\n /** Private field: invisible to structural typing, inaccessible outside. */\r\n #bytes: Uint8Array;\r\n\r\n private constructor(bytes: Uint8Array) {\r\n this.#bytes = bytes;\r\n }\r\n\r\n /**\r\n * Wrap a raw 32-byte ed25519 scalar (interop/tests). The bytes are\r\n * defensively copied — mutating (or zeroing) the input afterwards does not\r\n * affect the wrapper, and vice versa.\r\n *\r\n * @param bytes - 32-byte raw scalar (little-endian)\r\n * @throws {InvalidScalar} If `bytes` is not exactly 32 bytes.\r\n */\r\n static fromBytes(bytes: Uint8Array): StealthScalar {\r\n if (bytes.length !== 32) {\r\n throw new InvalidScalar('Invalid stealth private key length');\r\n }\r\n return new StealthScalar(new Uint8Array(bytes));\r\n }\r\n\r\n /** Throw if the scalar has been zeroized (an all-zero scalar is never valid). */\r\n #assertLive(): void {\r\n if (this.#bytes.every((b) => b === 0)) {\r\n throw new InvalidScalar(\r\n 'Stealth scalar is all-zero (already zeroized?) — it can no longer be used',\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Sign a message with the wrapped raw scalar. Produces a standard ed25519\r\n * signature that verifies against {@link publicKey} (scalar * G).\r\n *\r\n * @param message - The message to sign (must be non-empty)\r\n * @returns 64-byte ed25519 signature (R || S)\r\n * @throws {InvalidScalar} If the scalar has been {@link zeroize}d.\r\n */\r\n sign(message: Uint8Array): Uint8Array {\r\n this.#assertLive();\r\n return signWithRawScalarBytes(message, this.#bytes);\r\n }\r\n\r\n /**\r\n * The stealth public key this scalar signs for (scalar * G). Compare it to\r\n * the announced stealth public key to verify correspondence.\r\n *\r\n * @throws {InvalidScalar} If the scalar has been {@link zeroize}d.\r\n */\r\n publicKey(): Uint8Array {\r\n this.#assertLive();\r\n return scalarMultBase(this.#bytes);\r\n }\r\n\r\n /**\r\n * Overwrite the wrapped scalar with zeros. Call once you are done signing;\r\n * any later {@link sign}/{@link publicKey}/{@link dangerouslyToRawBytes}\r\n * throws instead of operating on a dead key. Idempotent.\r\n */\r\n zeroize(): void {\r\n this.#bytes.fill(0);\r\n }\r\n\r\n /**\r\n * DANGER — escape hatch returning a copy of the raw 32-byte scalar. Misuse\r\n * of these bytes permanently destroys funds:\r\n *\r\n * The value is a raw ed25519 SCALAR, **not an ed25519 seed**. Seed-based\r\n * Keypair APIs (`Keypair.fromRawEd25519Seed()`, `ed25519.sign()`, wallet\r\n * key imports) HASH the input to derive a different signing scalar, so the\r\n * resulting keypair's public key does NOT match the stealth address — the\r\n * contract/network rejects its signatures and the funds at that address\r\n * become PERMANENTLY UNWITHDRAWABLE.\r\n *\r\n * Only pass these bytes to APIs that consume raw scalars directly (e.g. the\r\n * deprecated `signWithStealthKey(message, rawBytes)` overload). Prefer\r\n * {@link sign}/{@link publicKey}, and zero any copy you make (`copy.fill(0)`)\r\n * as soon as you are done with it.\r\n *\r\n * @returns A fresh copy of the 32-byte raw scalar.\r\n * @throws {InvalidScalar} If the scalar has been {@link zeroize}d.\r\n */\r\n dangerouslyToRawBytes(): Uint8Array {\r\n this.#assertLive();\r\n return new Uint8Array(this.#bytes);\r\n }\r\n}\r\n","import { scalarMult, scalarAdd } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\nimport { StealthScalar } from './scalar.js';\r\n\r\n/**\r\n * Recover the stealth private key for a stealth address.\r\n *\r\n * This implements the receiver's private key recovery:\r\n * 1. Compute shared secret S = k_view * R\r\n * 2. Hash to scalar s = SHA256(S) mod L\r\n * 3. Compute stealth private key p = k_spend + s mod L\r\n *\r\n * The recovered key can be used to:\r\n * - Sign transactions from the stealth address ({@link StealthScalar.sign})\r\n * - Derive the corresponding public key for verification\r\n * ({@link StealthScalar.publicKey})\r\n *\r\n * WARNING: The recovered value is a RAW ed25519 SCALAR (k_spend + s mod L),\r\n * NOT an ed25519 seed — which is why it is returned as a {@link StealthScalar}\r\n * wrapper instead of bytes. Do NOT extract the bytes\r\n * ({@link StealthScalar.dangerouslyToRawBytes}) to construct a Stellar/ed25519\r\n * Keypair via `Keypair.fromRawEd25519Seed()` or any seed-based API: those APIs\r\n * HASH the input to derive a different signing scalar, producing a key that\r\n * does not match the stealth public key — the contract will reject the\r\n * signature and the funds become permanently unwithdrawable. Sign through the\r\n * wrapper (or `signWithStealthKey`) instead.\r\n *\r\n * @param spendPrivKey - Receiver's 32-byte spend private key\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @returns The stealth private key (raw scalar) wrapped as a {@link StealthScalar}\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * import { recoverStealthPrivateKey } from '@shade/crypto';\r\n *\r\n * // Recover the stealth scalar to withdraw funds\r\n * const stealthKey = recoverStealthPrivateKey(\r\n * keys.spendPrivKey,\r\n * keys.viewPrivKey,\r\n * announcement.ephemeralPubKey\r\n * );\r\n *\r\n * // Sign the withdrawal message through the wrapper (do NOT build a Keypair\r\n * // from the raw bytes — seed APIs hash to a different, fund-losing key).\r\n * const signature = stealthKey.sign(withdrawMessage);\r\n *\r\n * // IMPORTANT: Clear the private key from memory after use\r\n * stealthKey.zeroize();\r\n * ```\r\n */\r\nexport function recoverStealthPrivateKey(\r\n spendPrivKey: Uint8Array,\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array\r\n): StealthScalar {\r\n if (spendPrivKey.length !== 32) {\r\n throw new Error('Invalid spend private key length');\r\n }\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Step 1: Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Step 2: Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Step 3: Compute stealth private key p = k_spend + s mod L\r\n const stealthPrivKey = scalarAdd(spendPrivKey, s);\r\n\r\n // The wrapper copies the bytes; zero the loose intermediate so the wrapper\r\n // holds the only live copy (zeroize() then actually clears the key).\r\n const scalar = StealthScalar.fromBytes(stealthPrivKey);\r\n stealthPrivKey.fill(0);\r\n\r\n return scalar;\r\n}\r\n\r\n/**\r\n * Recover the stealth private key as raw bytes (pre-0.1.0 behavior).\r\n *\r\n * @deprecated Use {@link recoverStealthPrivateKey}, which returns a\r\n * {@link StealthScalar} wrapper: sign with `.sign(message)`, verify with\r\n * `.publicKey()`, clear with `.zeroize()`. If you truly need raw bytes,\r\n * call `.dangerouslyToRawBytes()` — and NEVER feed them to a seed-based\r\n * Keypair API (`Keypair.fromRawEd25519Seed()` etc.), which hashes the input\r\n * into a mismatched key and makes the funds permanently unwithdrawable.\r\n *\r\n * @param spendPrivKey - Receiver's 32-byte spend private key\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @returns 32-byte stealth private key (raw scalar) for signing transactions\r\n * @throws {Error} If key lengths are invalid\r\n */\r\nexport function recoverStealthPrivateKeyBytes(\r\n spendPrivKey: Uint8Array,\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array\r\n): Uint8Array {\r\n return recoverStealthPrivateKey(\r\n spendPrivKey,\r\n viewPrivKey,\r\n ephemeralPubKey,\r\n ).dangerouslyToRawBytes();\r\n}\r\n","// Advanced stealth address functions\r\nimport type { StealthDerivation } from './stealth.js';\r\nimport { scalarMult, scalarMultBase, pointAdd } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\nimport { hmac } from '@noble/hashes/hmac';\r\n\r\n/** Number of bytes used to serialize a stroop amount (fits any i64/u64 value). */\r\nconst AMOUNT_BYTES = 8;\r\n/** Length of the appended authentication tag. */\r\nconst TAG_BYTES = 32;\r\n/** Total ciphertext length: encrypted amount || HMAC tag. */\r\nconst CIPHERTEXT_BYTES = AMOUNT_BYTES + TAG_BYTES;\r\n/** Maximum representable amount: Stellar stroop amounts are i64 (max 2^63 - 1). */\r\nconst MAX_AMOUNT = (1n << 63n) - 1n;\r\n\r\nconst encKeyLabel = new TextEncoder().encode('amount');\r\nconst macKeyLabel = new TextEncoder().encode('amount-mac');\r\n\r\n/**\r\n * Derive a domain-separated 32-byte subkey from the shared secret.\r\n */\r\nfunction deriveSubkey(sharedSecret: Uint8Array, label: Uint8Array): Uint8Array {\r\n const input = new Uint8Array(sharedSecret.length + label.length);\r\n input.set(sharedSecret, 0);\r\n input.set(label, sharedSecret.length);\r\n return sha256(input);\r\n}\r\n\r\n/**\r\n * Serialize a non-negative integer stroop amount to fixed-width big-endian bytes.\r\n * @throws {Error} If the amount is non-finite, negative, non-integer, or too large.\r\n */\r\nfunction serializeAmount(amount: bigint | number): Uint8Array {\r\n let value: bigint;\r\n if (typeof amount === 'bigint') {\r\n value = amount;\r\n } else {\r\n if (!Number.isFinite(amount)) {\r\n throw new Error('Invalid amount: must be a finite integer');\r\n }\r\n if (!Number.isInteger(amount)) {\r\n throw new Error('Invalid amount: must be an integer number of stroops');\r\n }\r\n value = BigInt(amount);\r\n }\r\n\r\n if (value < 0n) {\r\n throw new Error('Invalid amount: must be non-negative');\r\n }\r\n if (value > MAX_AMOUNT) {\r\n throw new Error('Invalid amount: exceeds maximum stroop value');\r\n }\r\n\r\n const bytes = new Uint8Array(AMOUNT_BYTES);\r\n for (let i = AMOUNT_BYTES - 1; i >= 0; i--) {\r\n bytes[i] = Number(value & 0xffn);\r\n value >>= 8n;\r\n }\r\n return bytes;\r\n}\r\n\r\n/**\r\n * Encrypt a stroop amount using the shared secret (encrypt-then-MAC).\r\n *\r\n * The amount is serialized as a fixed-width 8-byte big-endian integer (stroops),\r\n * XORed with a keystream derived from the shared secret, then authenticated with\r\n * an HMAC-SHA256 tag. Tampering with the ciphertext is detected on decrypt.\r\n *\r\n * @param amount - The amount in stroops (non-negative integer, `bigint` or `number`)\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns 40-byte authenticated ciphertext (8-byte encrypted amount || 32-byte tag)\r\n * @throws {Error} If the shared secret length is wrong or the amount is invalid\r\n */\r\nexport function encryptAmount(amount: bigint | number, sharedSecret: Uint8Array): Uint8Array {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n const amountBytes = serializeAmount(amount);\r\n\r\n // Keystream: SHA256(sharedSecret || \"amount\"); XOR-encrypt the amount bytes.\r\n const keystream = deriveSubkey(sharedSecret, encKeyLabel);\r\n const ciphertext = new Uint8Array(CIPHERTEXT_BYTES);\r\n for (let i = 0; i < AMOUNT_BYTES; i++) {\r\n ciphertext[i] = amountBytes[i]! ^ keystream[i]!;\r\n }\r\n\r\n // Encrypt-then-MAC: authenticate the encrypted amount with HMAC-SHA256.\r\n const macKey = deriveSubkey(sharedSecret, macKeyLabel);\r\n const tag = hmac(sha256, macKey, ciphertext.subarray(0, AMOUNT_BYTES));\r\n ciphertext.set(tag, AMOUNT_BYTES);\r\n\r\n return ciphertext;\r\n}\r\n\r\n/**\r\n * Decrypt and authenticate a stroop amount using the shared secret.\r\n *\r\n * Verifies the HMAC-SHA256 tag in constant time before decrypting. Any\r\n * modification to the ciphertext (or a wrong shared secret) causes a throw\r\n * rather than returning a malleable, silently-wrong value.\r\n *\r\n * @param encrypted - The 40-byte authenticated ciphertext from {@link encryptAmount}\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns The decrypted amount in stroops as a `bigint`\r\n * @throws {Error} If the ciphertext length is wrong, the shared secret length is\r\n * wrong, or the authentication tag does not verify\r\n */\r\nexport function decryptAmount(encrypted: Uint8Array, sharedSecret: Uint8Array): bigint {\r\n if (encrypted.length !== CIPHERTEXT_BYTES) {\r\n throw new Error(\r\n `Invalid encrypted amount: expected ${CIPHERTEXT_BYTES} bytes, got ${encrypted.length}`\r\n );\r\n }\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n const body = encrypted.subarray(0, AMOUNT_BYTES);\r\n const tag = encrypted.subarray(AMOUNT_BYTES);\r\n\r\n // Verify the authentication tag in constant time (encrypt-then-MAC).\r\n const macKey = deriveSubkey(sharedSecret, macKeyLabel);\r\n const expectedTag = hmac(sha256, macKey, body);\r\n let diff = 0;\r\n for (let i = 0; i < TAG_BYTES; i++) {\r\n diff |= tag[i]! ^ expectedTag[i]!;\r\n }\r\n if (diff !== 0) {\r\n throw new Error('Invalid encrypted amount: authentication failed');\r\n }\r\n\r\n // XOR-decrypt and deserialize the big-endian stroop integer.\r\n const keystream = deriveSubkey(sharedSecret, encKeyLabel);\r\n let value = 0n;\r\n for (let i = 0; i < AMOUNT_BYTES; i++) {\r\n const plain = body[i]! ^ keystream[i]!;\r\n value = (value << 8n) | BigInt(plain);\r\n }\r\n return value;\r\n}\r\n\r\nexport interface StealthDerivationWithSecret extends StealthDerivation {\r\n sharedSecret: Uint8Array;\r\n}\r\n\r\n/**\r\n * Derive a stealth address with the shared secret exposed.\r\n *\r\n * Similar to deriveStealthAddress but also returns the shared secret,\r\n * useful for applications that need amount encryption or other\r\n * shared secret-based features.\r\n *\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param viewPubKey - Receiver's 32-byte view public key\r\n * @param ephemeralPrivKey - Sender's 32-byte ephemeral private key\r\n * @returns Stealth derivation including the shared secret\r\n */\r\nexport function deriveStealthAddressWithSecret(\r\n spendPubKey: Uint8Array,\r\n viewPubKey: Uint8Array,\r\n ephemeralPrivKey: Uint8Array\r\n): StealthDerivationWithSecret {\r\n // Compute ephemeral public key R = r*G\r\n const R = scalarMultBase(ephemeralPrivKey);\r\n\r\n // Compute shared secret S = r*K_view\r\n const S = scalarMult(ephemeralPrivKey, viewPubKey);\r\n\r\n // Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Get view tag\r\n const tag = viewTag(S);\r\n\r\n return {\r\n stealthPubKey: P,\r\n stealthAddress: encodePublicKey(P),\r\n ephemeralPubKey: R,\r\n viewTag: tag,\r\n ephemeralPrivKey: ephemeralPrivKey,\r\n sharedSecret: S\r\n };\r\n}","import { generateMnemonic as _generateMnemonic, validateMnemonic as _validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';\r\nimport { wordlist } from '@scure/bip39/wordlists/english';\r\nimport type { StealthKeys } from './types.js';\r\nimport { scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\nconst textEncoder = new TextEncoder();\r\n\r\n/**\r\n * Generate a 12-word BIP-39 mnemonic phrase.\r\n */\r\nexport function generateMnemonic(): string {\r\n return _generateMnemonic(wordlist);\r\n}\r\n\r\n/**\r\n * Validate a mnemonic phrase against the BIP-39 english wordlist.\r\n */\r\nexport function validateMnemonic(mnemonic: string): boolean {\r\n return _validateMnemonic(mnemonic, wordlist);\r\n}\r\n\r\n/**\r\n * Derive stealth spend and view keys from a BIP-39 mnemonic.\r\n *\r\n * Uses domain-separated SHA-256 hashing of the BIP-39 seed to derive\r\n * two independent ed25519 scalars for the spend and view key pairs.\r\n */\r\nexport function mnemonicToStealthKeys(mnemonic: string, passphrase?: string): StealthKeys {\r\n if (!_validateMnemonic(mnemonic, wordlist)) {\r\n throw new Error('Invalid mnemonic phrase');\r\n }\r\n\r\n const seed = mnemonicToSeedSync(mnemonic, passphrase || '');\r\n\r\n const spendTag = textEncoder.encode('shade-spend');\r\n const viewTag = textEncoder.encode('shade-view');\r\n\r\n const spendInput = new Uint8Array(spendTag.length + seed.length);\r\n spendInput.set(spendTag, 0);\r\n spendInput.set(seed, spendTag.length);\r\n\r\n const viewInput = new Uint8Array(viewTag.length + seed.length);\r\n viewInput.set(viewTag, 0);\r\n viewInput.set(seed, viewTag.length);\r\n\r\n const spendPrivKey = hashToScalar(spendInput);\r\n const viewPrivKey = hashToScalar(viewInput);\r\n\r\n // Zero sensitive intermediates\r\n seed.fill(0);\r\n spendInput.fill(0);\r\n viewInput.fill(0);\r\n\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: { spendPubKey, viewPubKey },\r\n };\r\n}\r\n","import type { StealthKeys } from './types.js';\r\nimport { scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\nimport { InvalidScalar } from './errors.js';\r\n\r\nconst textEncoder = new TextEncoder();\r\n\r\n/**\r\n * Domain-separation context string identifying the v1 wallet-signature\r\n * key-derivation scheme. Embedded as the first line of the message a wallet\r\n * signs to derive stealth keys.\r\n */\r\nexport const KEY_DERIVATION_CONTEXT_V1 = 'stellar-shade-keys-v1';\r\n\r\n/**\r\n * Build the canonical message a wallet signs to derive its stealth keys.\r\n *\r\n * The message is a deterministic, human-readable, newline-separated string.\r\n * Because RFC 8032 ed25519 signatures are deterministic, the same wallet\r\n * signing this exact message always yields the same signature, and therefore\r\n * the same stealth keys — that determinism is the whole point.\r\n *\r\n * This is a pure string builder with NO `@stellar/stellar-sdk` dependency, in\r\n * keeping with the crypto package's zero-SDK rule. Callers are responsible for\r\n * having the wallet sign the returned string.\r\n *\r\n * Security model:\r\n * - The `appId` scopes keys per application: different apps signing the same\r\n * wallet produce independent stealth keys, so a leak in one app does not\r\n * expose another.\r\n * - Users must NEVER sign this exact message for any other purpose. Signing it\r\n * anywhere untrusted hands over the ability to derive (and thus control) the\r\n * stealth keys. The WARNING line makes this explicit to the signer.\r\n *\r\n * @param opts - Optional scoping parameters.\r\n * @param opts.network - Network label to bind keys to (defaults to `'any'`).\r\n * @param opts.appId - Application identifier to scope keys (defaults to `'default'`).\r\n * @returns The exact newline-separated message to be signed.\r\n *\r\n * @example\r\n * ```typescript\r\n * const message = buildKeyDerivationMessage({ network: 'testnet', appId: 'my-app' });\r\n * const signature = await wallet.sign(message); // 64-byte ed25519 signature\r\n * const keys = deriveKeysFromSignature(signature);\r\n * ```\r\n */\r\nexport function buildKeyDerivationMessage(opts?: { network?: string; appId?: string }): string {\r\n const network = opts?.network ?? 'any';\r\n const appId = opts?.appId ?? 'default';\r\n\r\n return [\r\n KEY_DERIVATION_CONTEXT_V1,\r\n `network:${network}`,\r\n `app:${appId}`,\r\n 'WARNING: Signing this message derives your stealth keys. Only sign it in apps you trust.',\r\n ].join('\\n');\r\n}\r\n\r\n/**\r\n * Derive stealth spend and view keys from a wallet's ed25519 signature.\r\n *\r\n * Uses domain-separated SHA-256 hashing of the signature to derive two\r\n * independent ed25519 scalars for the spend and view key pairs, mirroring the\r\n * BIP-39 derivation in `hd.ts`.\r\n *\r\n * The input signature should be produced by having the wallet sign the message\r\n * from {@link buildKeyDerivationMessage}. RFC 8032 ed25519 signatures are\r\n * deterministic, so the same wallet signing the same message always re-derives\r\n * the same stealth keys — that reproducibility is the feature that lets a user\r\n * recover their stealth keys from just their wallet.\r\n *\r\n * Security model:\r\n * - Requires a DETERMINISTIC signer (RFC 8032 / RFC 6979 style). A wallet that\r\n * randomises signatures would derive different keys on every call and break\r\n * recovery. Do not use this with non-deterministic signers.\r\n * - Wallet compromise EQUALS stealth key compromise: anyone who can produce the\r\n * signature can re-derive these keys. This is an accepted trade-off in\r\n * exchange for keyless, recoverable-from-wallet stealth keys.\r\n * - Users must NEVER sign the derivation message for any other purpose; doing so\r\n * exposes the derived keys. See the WARNING line in the signed message.\r\n * - Key scoping (network/appId) is handled upstream in the signed message, so\r\n * distinct apps yield independent keys.\r\n *\r\n * @param signature - A 64-byte ed25519 signature over the derivation message.\r\n * @returns Stealth keys in the same shape returned by `generateMetaAddress`.\r\n * @throws {InvalidScalar} If the signature is not 64 bytes or is all zeros.\r\n *\r\n * @example\r\n * ```typescript\r\n * const message = buildKeyDerivationMessage({ appId: 'my-app' });\r\n * const signature = await wallet.sign(message);\r\n * const keys = deriveKeysFromSignature(signature);\r\n * // keys.metaAddress is the receiver's public meta-address\r\n * ```\r\n */\r\nexport function deriveKeysFromSignature(signature: Uint8Array): StealthKeys {\r\n if (signature.length !== 64) {\r\n throw new InvalidScalar('Signature must be 64 bytes');\r\n }\r\n if (signature.every((byte) => byte === 0)) {\r\n throw new InvalidScalar('Signature must not be all zeros');\r\n }\r\n\r\n const spendTag = textEncoder.encode('shade-spend');\r\n const viewTag = textEncoder.encode('shade-view');\r\n\r\n const spendInput = new Uint8Array(spendTag.length + signature.length);\r\n spendInput.set(spendTag, 0);\r\n spendInput.set(signature, spendTag.length);\r\n\r\n const viewInput = new Uint8Array(viewTag.length + signature.length);\r\n viewInput.set(viewTag, 0);\r\n viewInput.set(signature, viewTag.length);\r\n\r\n const spendPrivKey = hashToScalar(spendInput);\r\n const viewPrivKey = hashToScalar(viewInput);\r\n\r\n // Zero sensitive intermediates\r\n spendInput.fill(0);\r\n viewInput.fill(0);\r\n\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: { spendPubKey, viewPubKey },\r\n };\r\n}\r\n","import type { DeliveryMethod } from './types.js';\r\n\r\n/**\r\n * Base class for every error the SDK throws deliberately.\r\n *\r\n * Carries a stable, machine-readable {@link code} so applications can branch on\r\n * the error KIND without string-matching messages (which may be reworded) or\r\n * relying on `instanceof` (which breaks across duplicated package instances).\r\n * Subclasses keep their own `name` and human-readable message.\r\n */\r\nexport class ShadeError extends Error {\r\n /**\r\n * Stable machine-readable identifier for this error kind (snake_case).\r\n * Guaranteed not to change across SDK versions, unlike the message text.\r\n */\r\n readonly code: string;\r\n\r\n constructor(code: string, message: string) {\r\n super(message);\r\n this.name = 'ShadeError';\r\n this.code = code;\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when `send()` is called without an explicit delivery method.\r\n * The SDK deliberately has NO implicit default: the app must choose a method\r\n * (or `'auto'`) on every send so the privacy trade-off is always a conscious one.\r\n */\r\nexport class MethodRequiredError extends ShadeError {\r\n constructor() {\r\n super(\r\n 'method_required',\r\n \"A delivery method is required. Pass opts.method: 'pool' | 'account' | 'auto'.\",\r\n );\r\n this.name = 'MethodRequiredError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when a requested delivery method is not present in the client's\r\n * configured `methods` list.\r\n */\r\nexport class MethodNotEnabledError extends ShadeError {\r\n constructor(method: DeliveryMethod) {\r\n super(\r\n 'method_not_enabled',\r\n `Delivery method '${method}' is not enabled. Add it to ClientConfig.methods to use it.`,\r\n );\r\n this.name = 'MethodNotEnabledError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when a delivery method exists but cannot service the request\r\n * (e.g. a non-native asset over the account method, or the reserved spp method).\r\n */\r\nexport class MethodNotAvailableError extends ShadeError {\r\n constructor(message: string) {\r\n super('method_not_available', message);\r\n this.name = 'MethodNotAvailableError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when an account-method XLM send is below the protocol minimum\r\n * (amount must be strictly greater than 1 XLM to fund a new stealth account).\r\n */\r\nexport class MinimumAmountError extends ShadeError {\r\n constructor(amount: number) {\r\n super(\r\n 'minimum_amount',\r\n `Account sends require an amount strictly greater than 1 XLM (got ${amount}).`,\r\n );\r\n this.name = 'MinimumAmountError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when a partial account claim requests more than the stealth account can\r\n * pay out while keeping its base reserve and covering the fee. The message names\r\n * the maximum claimable amount so the caller can retry within bounds.\r\n */\r\nexport class ClaimAmountError extends ShadeError {\r\n /** The maximum amount that could be claimed for this account. */\r\n readonly max: number;\r\n constructor(requested: number, max: number) {\r\n super(\r\n 'claim_amount_exceeds_max',\r\n `Partial claim of ${requested} XLM exceeds the maximum claimable ${max} XLM ` +\r\n '(account must retain its base reserve and cover the fee).',\r\n );\r\n this.name = 'ClaimAmountError';\r\n this.max = max;\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when `opts.amount` is passed to a claim that CANNOT honor it, instead\r\n * of silently moving a different amount (fund-safety):\r\n * - An account-method NATIVE claim with an effective merge (`merge` omitted or\r\n * `true`) sweeps the ENTIRE balance via AccountMerge — `amount` would be\r\n * ignored. Pass `merge: false` for a partial claim, or drop `amount` to sweep.\r\n * - An account-method TOKEN claim always claims the claimable balance in full;\r\n * `amount` is not supported there at all.\r\n *\r\n * Pool claims are unaffected: `amount` is honored as a partial withdrawal.\r\n */\r\nexport class ClaimAmountRequiresNoMergeError extends ShadeError {\r\n constructor(kind: 'native-merge' | 'token' = 'native-merge') {\r\n super(\r\n 'claim_amount_requires_no_merge',\r\n kind === 'token'\r\n ? 'opts.amount is not supported on an account-method token claim: the ' +\r\n 'claimable balance is always claimed (and paid out) in full. Drop ' +\r\n 'opts.amount, then transfer any partial amount onward separately.'\r\n : 'opts.amount was passed but this account-method native claim would MERGE ' +\r\n 'the stealth account and sweep its ENTIRE balance, ignoring amount. ' +\r\n 'Pass opts.merge: false for a partial claim, or drop opts.amount to sweep.',\r\n );\r\n this.name = 'ClaimAmountRequiresNoMergeError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when a send/claim amount is not a positive finite number, caught before\r\n * building the transaction so the caller gets an actionable SDK error rather than\r\n * an on-chain failure after the fee is burned.\r\n */\r\nexport class InvalidAmountError extends ShadeError {\r\n constructor(amount: unknown) {\r\n super(\r\n 'invalid_amount',\r\n `Amount must be a positive finite number (got ${String(amount)}).`,\r\n );\r\n this.name = 'InvalidAmountError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the sponsored token-claim path when the relayer-prepared XDR does\r\n * NOT match the operation list the client re-derives from its own trusted inputs\r\n * (stealth address, asset, balanceId, destination, amount). A malicious relayer\r\n * could otherwise redirect the payout or append an AccountMerge to steal the\r\n * just-claimed token; the client refuses to sign such a transaction. The message\r\n * names the specific mismatch (e.g. a tampered payout destination or an extra\r\n * appended operation) so the failure is diagnosable.\r\n */\r\nexport class SponsoredClaimMismatchError extends ShadeError {\r\n constructor(detail: string) {\r\n super(\r\n 'sponsored_claim_mismatch',\r\n `Refusing to sign sponsored claim: prepared transaction does not match ` +\r\n `the expected operations (${detail}). The relayer may be malicious.`,\r\n );\r\n this.name = 'SponsoredClaimMismatchError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by {@link StealthSession.unlock} when the supplied password fails to\r\n * decrypt the stored envelope. Surfaces as an AES-GCM authentication failure\r\n * (the tag does not verify), which is indistinguishable from tampering — either\r\n * way the key material must not be trusted.\r\n */\r\nexport class WrongPasswordError extends ShadeError {\r\n constructor() {\r\n super(\r\n 'wrong_password',\r\n 'Wrong password: could not decrypt the stored stealth keys.',\r\n );\r\n this.name = 'WrongPasswordError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by {@link StealthSession.unlock} when the public keys stored in the\r\n * clear on the envelope do NOT match the public keys re-derived from the\r\n * decrypted private scalars. The private material is protected by AES-GCM, but\r\n * the cleartext `spendPublicKey`/`viewPublicKey` are not — a storage-WRITE\r\n * attacker (no password) could otherwise substitute a wrong pubkey and silently\r\n * break scanning (denial of discovery). Re-deriving and asserting equality on\r\n * unlock turns that silent mis-scan into a loud, diagnosable failure.\r\n */\r\nexport class SessionIntegrityError extends ShadeError {\r\n constructor(which: 'spend' | 'view') {\r\n super(\r\n 'session_integrity',\r\n `Session integrity check failed: the stored ${which} public key does not ` +\r\n 'match the decrypted private key. The stored session may have been tampered with.',\r\n );\r\n this.name = 'SessionIntegrityError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the pool withdraw path when the resolved stealth address holds no\r\n * balance in the pool contract for the requested asset — there is nothing to\r\n * withdraw. Recoverable: the caller may have already withdrawn, or is querying\r\n * the wrong asset.\r\n */\r\nexport class NoBalanceError extends ShadeError {\r\n constructor() {\r\n super('no_balance', 'Stealth address has no balance in the pool.');\r\n this.name = 'NoBalanceError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the pool withdraw path when no announcement matching the given\r\n * stealth address can be found for these keys — the payment is not ours or has\r\n * not yet been indexed.\r\n */\r\nexport class AnnouncementNotFoundError extends ShadeError {\r\n constructor() {\r\n super(\r\n 'announcement_not_found',\r\n 'Could not find announcement for this stealth address.',\r\n );\r\n this.name = 'AnnouncementNotFoundError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the account claim path when the stealth account cannot be found on\r\n * Horizon — typically because the funding send has not yet confirmed.\r\n */\r\nexport class StealthAccountNotFoundError extends ShadeError {\r\n constructor() {\r\n super(\r\n 'stealth_account_not_found',\r\n 'Stealth account not found on Horizon — has the send confirmed?',\r\n );\r\n this.name = 'StealthAccountNotFoundError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by a token claim when the destination account does not (or cannot yet)\r\n * trust the asset being claimed. The message names the actionable fix — add the\r\n * trustline on the destination before claiming.\r\n */\r\nexport class DestinationTrustlineError extends ShadeError {\r\n constructor(message: string) {\r\n super('destination_trustline', message);\r\n this.name = 'DestinationTrustlineError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the pool withdraw path when a fee-payer secret is required (to pay\r\n * the Soroban invocation fee) but none was supplied.\r\n */\r\nexport class FeePayerRequiredError extends ShadeError {\r\n constructor() {\r\n super(\r\n 'fee_payer_required',\r\n 'A fee payer secret is required for pool withdrawals.',\r\n );\r\n this.name = 'FeePayerRequiredError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the pool claim path when an external {@link TransactionSigner} is\r\n * supplied (via `signTransaction`) but no `feePayerAddress` is given. A pool\r\n * claim needs a fee payer; with external signing the fee payer is identified by\r\n * its G-address, never a secret. Failing loudly here prevents the SDK from ever\r\n * calling `Keypair.fromSecret` on a public key.\r\n */\r\nexport class FeePayerAddressRequiredError extends ShadeError {\r\n constructor() {\r\n super(\r\n 'fee_payer_address_required',\r\n 'feePayerAddress is required when signTransaction is set on a pool claim. ' +\r\n 'Pass the fee payer G-address (opts.feePayerAddress) — the SDK signs it via signTransaction.',\r\n );\r\n this.name = 'FeePayerAddressRequiredError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the pool withdraw path when the recipient's persistent Balance/Nonce\r\n * ledger entry has been archived (Soroban state expiration) and the automatic\r\n * RestoreFootprint transaction that must precede the withdraw could not be\r\n * completed. Withdrawing over an archived footprint fails on-chain even though\r\n * `get_balance`/`scan` still report the funds, so the SDK restores the entry\r\n * first; if that restore itself fails the funds are recoverable but the withdraw\r\n * cannot proceed until the entry is restored. The message carries the underlying\r\n * cause so the operator can diagnose (e.g. an unfunded fee payer or a relayer\r\n * rejection).\r\n */\r\nexport class EntryArchivedRestoringError extends ShadeError {\r\n constructor(cause: string) {\r\n super(\r\n 'entry_archived_restoring',\r\n `Stealth entry is archived and the automatic restore failed (${cause}). ` +\r\n 'The funds are safe but the withdraw cannot proceed until the Balance/Nonce ' +\r\n 'entry is restored — retry, or restore the footprint manually.',\r\n );\r\n this.name = 'EntryArchivedRestoringError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when the RPC `sendTransaction` returns a non-terminal status that means\r\n * the transaction did NOT land — `TRY_AGAIN_LATER` (the node dropped it without\r\n * queueing) or any other non-`PENDING`/`SUCCESS` status. Nothing was submitted,\r\n * so the caller may safely retry with a fresh submission. Treating this as a\r\n * (retryable) failure prevents returning a success receipt for a tx that never\r\n * entered the ledger (SDK-01).\r\n */\r\nexport class TransactionRetryableError extends ShadeError {\r\n /** Marks this error as safe to retry (the tx never entered the ledger). */\r\n readonly retryable = true as const;\r\n constructor(status: string) {\r\n super(\r\n 'transaction_retryable',\r\n `Transaction was not submitted (RPC status: ${status}). Nothing landed on-chain — ` +\r\n 'retry the submission with a fresh transaction.',\r\n );\r\n this.name = 'TransactionRetryableError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when confirmation polling gives up while the transaction is still\r\n * PENDING. The transaction was ACCEPTED by the RPC and MAY STILL LAND on-chain\r\n * after this error — blindly resubmitting could double-send the funds. The\r\n * error carries {@link txHash} so callers can keep polling that hash (e.g.\r\n * `getTransaction`) to a terminal status before deciding to retry;\r\n * `retryable` is `false` to distinguish it from\r\n * {@link TransactionRetryableError} in shared retry loops.\r\n */\r\nexport class TransactionTimeoutError extends ShadeError {\r\n /**\r\n * NOT safe to blind-retry: unlike {@link TransactionRetryableError}, the\r\n * transaction may still be applied after this error is thrown.\r\n */\r\n readonly retryable = false as const;\r\n /** Hash of the still-pending transaction — poll it before any resubmission. */\r\n readonly txHash: string;\r\n constructor(txHash: string) {\r\n super(\r\n 'transaction_timeout',\r\n `Transaction ${txHash} confirmation timed out while still pending. It may ` +\r\n 'STILL land on-chain — do NOT blindly resubmit (risk of double-send); ' +\r\n 'poll this hash to a terminal status first.',\r\n );\r\n this.name = 'TransactionTimeoutError';\r\n this.txHash = txHash;\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when a relayer HTTP endpoint responds non-2xx. Carries the HTTP\r\n * {@link status} and the relayer's own machine-readable {@link relayerCode}\r\n * (e.g. `insufficient_credit`, `missing_auth`) so callers — and the\r\n * `RelayerPool` failover — can branch on the KIND of failure: 5xx is a relayer\r\n * fault worth failing over, 4xx is this request's fault and would only repeat.\r\n */\r\nexport class RelayerHttpError extends ShadeError {\r\n /** HTTP status the relayer responded with. */\r\n readonly status: number;\r\n /** The relayer's own `code` field from the error body, when present. */\r\n readonly relayerCode?: string;\r\n constructor(path: string, status: number, relayerCode?: string, detail?: string) {\r\n super(\r\n 'relayer_http_error',\r\n `Relayer ${path} failed (${status}): ${relayerCode ?? detail ?? 'unknown'}`,\r\n );\r\n this.name = 'RelayerHttpError';\r\n this.status = status;\r\n this.relayerCode = relayerCode;\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when a relayer cannot be reached at the transport level (DNS failure,\r\n * refused connection, aborted fetch, invalid response body). Distinct from\r\n * {@link RelayerHttpError} so the `RelayerPool` can treat it as a candidate\r\n * fault (fail over) rather than a request fault.\r\n */\r\nexport class RelayerNetworkError extends ShadeError {\r\n constructor(path: string, detail: string) {\r\n super('relayer_unreachable', `Relayer ${path} unreachable: ${detail}`);\r\n this.name = 'RelayerNetworkError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when an indexer HTTP endpoint responds non-2xx. Carries the HTTP\r\n * {@link status} and the indexer's own machine-readable {@link indexerCode}\r\n * from the `{ error, code }` body so callers can branch on the failure KIND.\r\n * The account scan treats it as \"abandon the indexer segment\" and falls back\r\n * to the Horizon walk — Horizon remains the source of truth.\r\n */\r\nexport class IndexerHttpError extends ShadeError {\r\n /** HTTP status the indexer responded with. */\r\n readonly status: number;\r\n /** The indexer's own `code` field from the error body, when present. */\r\n readonly indexerCode?: string;\r\n constructor(path: string, status: number, indexerCode?: string, detail?: string) {\r\n super(\r\n 'indexer_http_error',\r\n `Indexer ${path} failed (${status}): ${indexerCode ?? detail ?? 'unknown'}`,\r\n );\r\n this.name = 'IndexerHttpError';\r\n this.status = status;\r\n this.indexerCode = indexerCode;\r\n }\r\n}\r\n\r\n/**\r\n * Thrown when an indexer cannot be reached at the transport level (DNS\r\n * failure, refused connection, request timeout, invalid response body).\r\n * Distinct from {@link IndexerHttpError} for parity with the relayer errors;\r\n * the account scan treats both the same way (fall back to Horizon).\r\n */\r\nexport class IndexerNetworkError extends ShadeError {\r\n constructor(path: string, detail: string) {\r\n super('indexer_network_error', `Indexer ${path} unreachable: ${detail}`);\r\n this.name = 'IndexerNetworkError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the `RelayerPool` when no candidate relayer is usable for this\r\n * call. {@link candidates} maps every probed URL to the reason it was rejected\r\n * (`unreachable: ...`, `timeout`, `http_<status>`, `status_not_ok`,\r\n * `network_mismatch (...)`, `balance_below_min (...)`,\r\n * `credit_gated_no_funding_auth`), so the failure is diagnosable per relayer\r\n * instead of a bare \"nothing worked\".\r\n */\r\nexport class NoHealthyRelayerError extends ShadeError {\r\n /** Per-URL rejection reason for every probed candidate. */\r\n readonly candidates: Record<string, string>;\r\n constructor(candidates: Record<string, string>) {\r\n const detail = Object.entries(candidates)\r\n .map(([url, reason]) => `${url}: ${reason}`)\r\n .join('; ');\r\n super(\r\n 'no_healthy_relayer',\r\n `No healthy relayer among ${Object.keys(candidates).length} candidate(s) — ${detail}`,\r\n );\r\n this.name = 'NoHealthyRelayerError';\r\n this.candidates = candidates;\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by the {@link StealthClient} constructor when a pool-capable method is\r\n * enabled but no contract id was supplied (there are no built-in defaults —\r\n * pool deployments are per-operator). Failing here — rather than deep inside a\r\n * later Soroban call with an opaque error — makes the misconfiguration obvious:\r\n * pass `contractId` explicitly.\r\n */\r\nexport class ContractIdRequiredError extends ShadeError {\r\n constructor(network: string) {\r\n super(\r\n 'contract_id_required',\r\n `contractId is required for network '${network}'. Deploy the pool contract ` +\r\n 'and pass its C-address as ClientConfig.contractId (there is no built-in default).',\r\n );\r\n this.name = 'ContractIdRequiredError';\r\n }\r\n}\r\n\r\n/**\r\n * Thrown by `getNetworkConfig` (and therefore the {@link StealthClient}\r\n * constructor) when the requested network name is not in the `NETWORKS` table.\r\n * The type system already restricts `network` to the supported names; this is\r\n * the runtime guard for plain-JS callers and stale configs. The message lists\r\n * the currently supported networks, so it stays accurate as new networks\r\n * (e.g. `'public'` after the external audit) are added to the table.\r\n */\r\nexport class UnsupportedNetworkError extends ShadeError {\r\n /** The unknown network name that was requested. */\r\n readonly network: string;\r\n /** The network names this SDK build supports. */\r\n readonly supported: string[];\r\n constructor(network: string, supported: string[]) {\r\n super(\r\n 'unsupported_network',\r\n `Unsupported network '${network}'. Supported: ${supported.join(', ')}. ` +\r\n '(The local network has been removed — dev/test runs on testnet; ' +\r\n 'mainnet arrives after the external audit.)',\r\n );\r\n this.name = 'UnsupportedNetworkError';\r\n this.network = network;\r\n this.supported = supported;\r\n }\r\n}\r\n","import {\r\n Networks,\r\n Contract,\r\n nativeToScVal,\r\n Asset,\r\n TransactionBuilder,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\nimport {\r\n TransactionRetryableError,\r\n TransactionTimeoutError,\r\n UnsupportedNetworkError,\r\n} from './errors.js';\r\n\r\n/** Static endpoints and passphrase for one supported Stellar network. */\r\nexport interface NetworkDefinition {\r\n networkPassphrase: string;\r\n rpcUrl: string;\r\n horizonUrl: string;\r\n allowHttp: boolean;\r\n}\r\n\r\n/**\r\n * The single source of truth for the networks this SDK can talk to. Adding a\r\n * network is ONE new entry here: {@link NetworkName} (and with it every\r\n * `ClientConfig.network` union across the SDK and its consumers) widens\r\n * automatically.\r\n */\r\nexport const NETWORKS = {\r\n testnet: {\r\n networkPassphrase: Networks.TESTNET,\r\n rpcUrl: 'https://soroban-testnet.stellar.org',\r\n horizonUrl: 'https://horizon-testnet.stellar.org',\r\n allowHttp: false,\r\n },\r\n // post-audit (mainnet): uncomment and fill in the production RPC endpoint.\r\n // public: {\r\n // networkPassphrase: Networks.PUBLIC,\r\n // rpcUrl: '<soroban mainnet rpc>',\r\n // horizonUrl: 'https://horizon.stellar.org',\r\n // allowHttp: false,\r\n // },\r\n} as const satisfies Record<string, NetworkDefinition>;\r\n\r\n/** The names of the currently supported networks (today: `'testnet'`). */\r\nexport type NetworkName = keyof typeof NETWORKS;\r\n\r\n/** Network configuration resolved from a network name. */\r\nexport interface NetworkConfig extends NetworkDefinition {\r\n server: StellarSdk.rpc.Server;\r\n}\r\n\r\n/**\r\n * Reverse lookup: the {@link NETWORKS} name whose passphrase matches, or\r\n * `undefined` for a passphrase outside the table. Lets components that only\r\n * hold a passphrase (the delivery adapters) derive the network name a relayer\r\n * `/health` should report; an unknown passphrase yields `undefined`, which\r\n * callers treat as \"skip the check\" rather than a failure (mainnet-open).\r\n */\r\nexport function networkNameForPassphrase(\r\n passphrase: string,\r\n): NetworkName | undefined {\r\n for (const [name, def] of Object.entries(NETWORKS)) {\r\n if (def.networkPassphrase === passphrase) return name as NetworkName;\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Build network config (endpoints + a connected RPC server) from a network\r\n * name. Unknown names throw {@link UnsupportedNetworkError} — the type system\r\n * already prevents them, but plain-JS callers and stale configs need the\r\n * runtime guard too.\r\n */\r\nexport function getNetworkConfig(network: NetworkName): NetworkConfig {\r\n const def = NETWORKS[network];\r\n if (!def) {\r\n throw new UnsupportedNetworkError(network, Object.keys(NETWORKS));\r\n }\r\n return {\r\n ...def,\r\n server: new StellarSdk.rpc.Server(def.rpcUrl, { allowHttp: def.allowHttp }),\r\n };\r\n}\r\n\r\n/** Create a dummy transaction for read-only contract simulation. */\r\nexport function createSimulationTx(\r\n operation: StellarSdk.xdr.Operation,\r\n networkPassphrase: string,\r\n): StellarSdk.Transaction {\r\n return new TransactionBuilder(\r\n new StellarSdk.Account('GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF', '0'),\r\n { fee: '100', networkPassphrase },\r\n )\r\n .addOperation(operation)\r\n .setTimeout(30)\r\n .build();\r\n}\r\n\r\n/** Execute a read-only contract call via simulation. Returns the decoded native result. */\r\nexport async function simulateReadOnly(\r\n contractId: string,\r\n method: string,\r\n args: StellarSdk.xdr.ScVal[],\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<unknown | null> {\r\n const contract = new Contract(contractId);\r\n const op = contract.call(method, ...args);\r\n const sim = await server.simulateTransaction(\r\n createSimulationTx(op, networkPassphrase),\r\n );\r\n\r\n if (StellarSdk.rpc.Api.isSimulationSuccess(sim) && sim.result?.retval) {\r\n return StellarSdk.scValToNative(sim.result.retval);\r\n }\r\n return null;\r\n}\r\n\r\n/** Resolve an asset string (\"native\", \"XLM\", or \"CODE:ISSUER\") to a SAC contract address. */\r\nexport function resolveTokenAddress(\r\n assetArg: string | undefined,\r\n networkPassphrase: string,\r\n): string {\r\n if (!assetArg || assetArg === 'native' || assetArg === 'XLM') {\r\n return Asset.native().contractId(networkPassphrase);\r\n }\r\n const parts = assetArg.split(':');\r\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\r\n throw new Error('Invalid asset format. Use CODE:ISSUER or \"native\"');\r\n }\r\n return new Asset(parts[0], parts[1]).contractId(networkPassphrase);\r\n}\r\n\r\n/**\r\n * Give a human-readable label for a SAC token contract address (the opaque\r\n * `C...` string stored in pool announcements). The native XLM SAC has a\r\n * deterministic contract id — `Asset.native().contractId(passphrase)` — so we\r\n * detect it and return `'XLM'`; anything else cannot be reversed to CODE:ISSUER\r\n * from the address alone, so the original `C...` address is returned unchanged.\r\n *\r\n * This is what turns a balance/scan row from an unreadable C-address into a\r\n * recognizable token name for the common (native) case.\r\n *\r\n * @param tokenAddress - The token's SAC contract address, or 'native'/'unknown'.\r\n * @param networkPassphrase - Passphrase used to derive the native SAC id.\r\n * @returns 'XLM' for the native SAC (or the literal 'native'); otherwise the input.\r\n */\r\nexport function labelForToken(\r\n tokenAddress: string,\r\n networkPassphrase: string,\r\n): string {\r\n if (!tokenAddress || tokenAddress === 'unknown') return tokenAddress;\r\n if (tokenAddress === 'native' || tokenAddress === 'XLM') return 'XLM';\r\n try {\r\n if (tokenAddress === Asset.native().contractId(networkPassphrase)) {\r\n return 'XLM';\r\n }\r\n } catch {\r\n // Fall through to the raw address.\r\n }\r\n return tokenAddress;\r\n}\r\n\r\n/**\r\n * The minimal transaction-status surface of `rpc.Server` needed to poll a tx\r\n * hash to a terminal status. Structural, so confirm-polling callers (e.g. the\r\n * `RelayerClient` confirm option) can inject a real server or a test stub.\r\n */\r\nexport interface TransactionStatusSource {\r\n getTransaction(hash: string): Promise<{ status: string }>;\r\n}\r\n\r\n/**\r\n * Poll for transaction confirmation. Throws on failure or timeout.\r\n *\r\n * The timeout is a typed {@link TransactionTimeoutError} carrying the tx hash:\r\n * a still-PENDING transaction MAY land after we stop polling, so callers must\r\n * be able to distinguish \"gave up waiting\" (poll the hash, do NOT resubmit)\r\n * from a hard failure — a generic error here invites retry loops that\r\n * double-send funds.\r\n */\r\nexport async function waitForTransaction(\r\n server: TransactionStatusSource,\r\n hash: string,\r\n): Promise<void> {\r\n let attempts = 0;\r\n while (attempts < 30) {\r\n await new Promise(resolve => setTimeout(resolve, 1000));\r\n try {\r\n const result = await server.getTransaction(hash);\r\n if (result.status === 'SUCCESS') return;\r\n if (result.status === 'FAILED') throw new Error('Transaction failed on-chain');\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : String(e);\r\n if (msg === 'Transaction failed on-chain') throw e;\r\n }\r\n attempts++;\r\n }\r\n throw new TransactionTimeoutError(hash);\r\n}\r\n\r\n/**\r\n * Interpret a `sendTransaction` result and resolve to a landed transaction hash,\r\n * or throw. Only `SUCCESS` (already landed) and `PENDING` (queued — then polled\r\n * to completion) count as landed. Every other status means nothing entered the\r\n * ledger and must NOT return a success receipt (SDK-01):\r\n * - `ERROR` -> a hard submission failure (throw).\r\n * - `TRY_AGAIN_LATER` (and any other non-terminal status) -> the node dropped\r\n * the tx without queueing; throw a retryable error so the caller resubmits.\r\n * - `DUPLICATE` -> the exact tx is already in flight; poll its hash rather than\r\n * assuming success.\r\n */\r\nexport async function resolveSendResult(\r\n server: StellarSdk.rpc.Server,\r\n result: { status: string; hash: string },\r\n): Promise<string> {\r\n switch (result.status) {\r\n case 'SUCCESS':\r\n return result.hash;\r\n case 'PENDING':\r\n await waitForTransaction(server, result.hash);\r\n return result.hash;\r\n case 'DUPLICATE':\r\n await waitForTransaction(server, result.hash);\r\n return result.hash;\r\n case 'ERROR':\r\n throw new Error('Transaction submission failed');\r\n default:\r\n throw new TransactionRetryableError(result.status);\r\n }\r\n}\r\n\r\n/** Fetch announcements from the stealth pool contract (paged by start/limit). */\r\nexport async function fetchAnnouncements(\r\n contractId: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n start = 0,\r\n limit = 1000,\r\n): Promise<RawAnnouncement[]> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_announcements',\r\n [\r\n nativeToScVal(start, { type: 'u64' }),\r\n nativeToScVal(limit, { type: 'u64' }),\r\n ],\r\n server,\r\n networkPassphrase,\r\n );\r\n\r\n if (!result || !Array.isArray(result)) return [];\r\n\r\n return (result as unknown[]).map((ann: unknown) => {\r\n const a = ann as Record<string, unknown>;\r\n const stealthPk = new Uint8Array(a.stealth_pk as ArrayLike<number>);\r\n return {\r\n ephemeralPubKey: new Uint8Array(a.ephemeral_pk as ArrayLike<number>),\r\n viewTag: a.view_tag as number,\r\n stealthPubKey: stealthPk,\r\n stealthAddress: StrKey.encodeEd25519PublicKey(Buffer.from(stealthPk)),\r\n token: (a.token as { toString(): string })?.toString?.() || 'unknown',\r\n amount: BigInt((a.amount as string | number) || 0),\r\n };\r\n });\r\n}\r\n\r\n/** Cheap freshness check: total announcement count stored in the pool. */\r\nexport async function fetchAnnouncementCount(\r\n contractId: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<number> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_announcement_count',\r\n [],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result === null || result === undefined) return 0;\r\n return Number(result as string | number);\r\n}\r\n\r\nexport interface RawAnnouncement {\r\n ephemeralPubKey: Uint8Array;\r\n viewTag: number;\r\n stealthPubKey: Uint8Array;\r\n stealthAddress: string;\r\n token: string;\r\n amount: bigint;\r\n}\r\n\r\n/** Query the contract balance for a stealth key + token pair. */\r\nexport async function queryBalance(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_balance',\r\n [nativeToScVal(Buffer.from(stealthPk)), new StellarSdk.Address(tokenAddress).toScVal()],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\n/** Query the nonce for a stealth key. */\r\nexport async function queryNonce(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_nonce',\r\n [nativeToScVal(Buffer.from(stealthPk))],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\nfunction i128ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(16);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigInt64(0, value >> 64n);\r\n dv.setBigUint64(8, value & 0xFFFFFFFFFFFFFFFFn);\r\n return buf;\r\n}\r\n\r\nfunction u64ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(8);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigUint64(0, value);\r\n return buf;\r\n}\r\n\r\n/**\r\n * Build the withdraw message hash. Must be byte-identical to the contract's\r\n * `build_withdraw_message`.\r\n *\r\n * Layout (concatenated, then SHA-256) — 278-byte preimage:\r\n * domain_tag[22] (\"SHADE-POOL-WITHDRAW-V1\" ASCII) || stealth_pk[32]\r\n * || token_strkey_ascii[56] || amount_be_i128[16]\r\n * || dest_strkey_ascii[56] || nonce_be_u64[8]\r\n * || contract_strkey_ascii[56] || network_id[32]\r\n *\r\n * The leading static domain tag (SH-3) separates withdraw preimages from any\r\n * other message a stealth key might sign; the trailing contract address and\r\n * network id provide domain separation so a signature cannot be replayed on a\r\n * different deployment or network.\r\n * `networkId` equals `SHA-256(utf8(networkPassphrase))`, which matches the\r\n * on-chain `env.ledger().network_id()`.\r\n */\r\nexport function buildWithdrawMessage(\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n amount: bigint,\r\n destination: string,\r\n nonce: bigint,\r\n contractId: string,\r\n networkPassphrase: string,\r\n): Uint8Array {\r\n // Static domain-separation tag: 22 ASCII bytes (SH-3). Must match the\r\n // contract's WITHDRAW_MSG_DOMAIN_TAG byte-for-byte.\r\n const domainTag = Buffer.from('SHADE-POOL-WITHDRAW-V1', 'utf-8');\r\n const tokenBytes = Buffer.from(tokenAddress, 'utf-8');\r\n const destBytes = Buffer.from(destination, 'utf-8');\r\n const contractBytes = Buffer.from(contractId, 'utf-8');\r\n if (tokenBytes.length !== 56) throw new Error(`Token address must be 56 bytes StrKey, got ${tokenBytes.length}`);\r\n if (destBytes.length !== 56) throw new Error(`Destination must be 56 bytes StrKey, got ${destBytes.length}`);\r\n if (contractBytes.length !== 56) throw new Error(`Contract address must be 56 bytes StrKey, got ${contractBytes.length}`);\r\n\r\n const amountBytes = i128ToBigEndian(amount);\r\n const nonceBytes = u64ToBigEndian(nonce);\r\n const networkId = sha256(Buffer.from(networkPassphrase, 'utf-8'));\r\n\r\n const msg = new Uint8Array(22 + 32 + 56 + 16 + 56 + 8 + 56 + 32); // 278 bytes\r\n let offset = 0;\r\n msg.set(domainTag, offset); offset += 22;\r\n msg.set(stealthPk, offset); offset += 32;\r\n msg.set(tokenBytes, offset); offset += 56;\r\n msg.set(amountBytes, offset); offset += 16;\r\n msg.set(destBytes, offset); offset += 56;\r\n msg.set(nonceBytes, offset); offset += 8;\r\n msg.set(contractBytes, offset); offset += 56;\r\n msg.set(networkId, offset);\r\n\r\n return sha256(msg);\r\n}\r\n","import {\r\n buildKeyDerivationMessage,\r\n deriveKeysFromSignature,\r\n encodeMetaAddress,\r\n} from '@shade/crypto';\r\n// Deliberately the SDK's own mirror, not '@shade/crypto' — this type appears in\r\n// an exported signature, and crypto's version cannot be inlined into the\r\n// published .d.ts. ./raw-keys.ts proves the two stay structurally identical.\r\nimport type { RawStealthKeys } from './raw-keys.js';\r\nimport type { StealthKeys } from './types.js';\r\n\r\n/**\r\n * Convert crypto's raw stealth keys (Uint8Array scalars + meta-address object,\r\n * as returned by `generateMetaAddress`, `mnemonicToStealthKeys`, or\r\n * `deriveKeysFromSignature`) into the SDK's hex-string {@link StealthKeys}\r\n * shape used by every client/session API.\r\n *\r\n * The two packages deliberately reuse the name `StealthKeys` for different\r\n * shapes; import the raw one as `RawStealthKeys` (re-exported from the SDK\r\n * index) and convert at the boundary with this helper.\r\n */\r\nexport function stealthKeysFromRaw(raw: RawStealthKeys): StealthKeys {\r\n return {\r\n metaAddress: encodeMetaAddress(raw.metaAddress),\r\n spendPubKey: Buffer.from(raw.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(raw.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(raw.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(raw.viewPrivKey).toString('hex'),\r\n };\r\n}\r\n\r\n/**\r\n * A wallet signer. Given the derivation message it returns an ed25519 signature\r\n * in one of the shapes real wallets produce: raw bytes, a hex/base64 string, or\r\n * Freighter's `{ signedMessage }` envelope.\r\n */\r\nexport type WalletSigner = (\r\n message: string,\r\n) => Promise<\r\n Uint8Array | string | { signedMessage: string | Uint8Array }\r\n>;\r\n\r\n/**\r\n * The default key-derivation scope. This is DECOUPLED from any transport network\r\n * (e.g. testnet vs. local) so that a wallet re-derives the same stealth keys\r\n * regardless of which network a transaction is later submitted to. The CLI's\r\n * `--key-scope` flag defaults to this exact value so both tools line up.\r\n */\r\nexport const DEFAULT_KEY_SCOPE = 'stealth';\r\n\r\n/** The default application id used to scope derived keys. */\r\nexport const DEFAULT_APP_ID = 'default';\r\n\r\n/** Options for {@link keysFromWalletSignature}. */\r\nexport interface WalletKeysOpts {\r\n /**\r\n * Key-derivation scope folded into the signed message (crypto's `network`\r\n * field). This MUST be decoupled from the transport network: use the same\r\n * value everywhere you derive from this wallet, or you will get different\r\n * (unrecoverable) keys. Defaults to {@link DEFAULT_KEY_SCOPE} (`'stealth'`),\r\n * matching the CLI's `--key-scope` default so both tools derive identical keys.\r\n */\r\n keyScope?: string;\r\n /**\r\n * Application id to scope keys (folded into the signed message). Defaults to\r\n * {@link DEFAULT_APP_ID} (`'default'`), matching the CLI's `--app-id` default.\r\n */\r\n appId?: string;\r\n /**\r\n * Sign the message TWICE and throw when the two signatures differ. This guards\r\n * against randomized/hardware signers that would otherwise derive different\r\n * (unrecoverable) keys on every call. Defaults to `true`; pass `false` only\r\n * for a signer you KNOW is deterministic (RFC 8032) to skip the extra signature.\r\n */\r\n verifyDeterminism?: boolean;\r\n}\r\n\r\nfunction decodeToBytes(raw: string): Uint8Array {\r\n // Treat the input as hex ONLY when it is exactly 128 hex chars (a 64-byte\r\n // ed25519 signature). This avoids the ambiguity where a base64 payload that\r\n // happens to be all-hex-and-even-length would be silently mis-decoded as hex.\r\n const isSignatureHex = raw.length === 128 && /^[0-9a-fA-F]+$/.test(raw);\r\n const bytes = isSignatureHex\r\n ? new Uint8Array(Buffer.from(raw, 'hex'))\r\n : new Uint8Array(Buffer.from(raw, 'base64'));\r\n\r\n if (bytes.length !== 64) {\r\n throw new Error(\r\n `Wallet signature must decode to exactly 64 bytes, got ${bytes.length}`,\r\n );\r\n }\r\n return bytes;\r\n}\r\n\r\nfunction normalizeSignature(\r\n result: Uint8Array | string | { signedMessage: string | Uint8Array },\r\n): Uint8Array {\r\n let bytes: Uint8Array;\r\n if (result instanceof Uint8Array) {\r\n bytes = result;\r\n } else if (typeof result === 'string') {\r\n bytes = decodeToBytes(result);\r\n } else if (result && typeof result === 'object' && 'signedMessage' in result) {\r\n const inner = result.signedMessage;\r\n bytes = inner instanceof Uint8Array ? inner : decodeToBytes(inner);\r\n } else {\r\n throw new Error('Unsupported signer result shape');\r\n }\r\n\r\n if (bytes.length !== 64) {\r\n throw new Error(\r\n `Wallet signature must be exactly 64 bytes, got ${bytes.length}`,\r\n );\r\n }\r\n return bytes;\r\n}\r\n\r\nfunction equalBytes(a: Uint8Array, b: Uint8Array): boolean {\r\n if (a.length !== b.length) return false;\r\n for (let i = 0; i < a.length; i++) {\r\n if (a[i] !== b[i]) return false;\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * Derive stealth keys from a wallet's signature over the canonical derivation\r\n * message.\r\n *\r\n * Because RFC 8032 ed25519 signatures are deterministic, the same wallet\r\n * signing the same message always re-derives the same stealth keys — that is\r\n * what lets a user recover stealth keys from their wallet alone, with no extra\r\n * secret to store. Wallet compromise equals stealth-key compromise; this is the\r\n * accepted trade-off for keyless recovery.\r\n *\r\n * @param signer - Callback that signs the derivation message (see {@link WalletSigner}).\r\n * @param opts - Optional keyScope/appId scoping and determinism verification.\r\n * `keyScope` and `appId` MUST match across every tool that derives from this\r\n * wallet (they default to `'stealth'` / `'default'`, the same as the CLI).\r\n * @returns Hex-string {@link StealthKeys} in the same shape as `keygen()`.\r\n * @throws If the signature is not exactly 64 bytes, or (unless\r\n * `verifyDeterminism: false`) if two signatures over the same message differ.\r\n *\r\n * @example\r\n * ```typescript\r\n * // verifyDeterminism defaults to true; pass false only for a known-good signer.\r\n * const keys = await keysFromWalletSignature(\r\n * (msg) => freighter.signMessage(msg),\r\n * { appId: 'my-app' },\r\n * );\r\n * ```\r\n */\r\nexport async function keysFromWalletSignature(\r\n signer: WalletSigner,\r\n opts?: WalletKeysOpts,\r\n): Promise<StealthKeys> {\r\n const message = buildKeyDerivationMessage({\r\n network: opts?.keyScope ?? DEFAULT_KEY_SCOPE,\r\n appId: opts?.appId ?? DEFAULT_APP_ID,\r\n });\r\n\r\n const signature = normalizeSignature(await signer(message));\r\n\r\n if (opts?.verifyDeterminism !== false) {\r\n const second = normalizeSignature(await signer(message));\r\n if (!equalBytes(signature, second)) {\r\n throw new Error(\r\n 'Signer is non-deterministic: two signatures over the same message differ. ' +\r\n 'Wallet-derived stealth keys require a deterministic (RFC 8032) signer.',\r\n );\r\n }\r\n }\r\n\r\n return stealthKeysFromRaw(deriveKeysFromSignature(signature));\r\n}\r\n","/**\r\n * Minimal Horizon REST helper with an injectable `fetch`.\r\n *\r\n * The account delivery method relies only on Horizon's classic REST API\r\n * (transaction paging + operations + account probe + submit). Keeping this in a\r\n * tiny, dependency-free wrapper with an injectable fetch makes the account\r\n * scanner unit-testable fully offline: tests pass a stub fetch returning\r\n * synthetic fixtures, no docker network required.\r\n */\r\n\r\n/** A subset of a Horizon transaction record relevant to the account method. */\r\nexport interface HorizonTx {\r\n id: string;\r\n hash: string;\r\n paging_token: string;\r\n memo_type: string;\r\n memo?: string;\r\n successful?: boolean;\r\n /** The account that submitted (and pays for) the transaction. */\r\n source_account?: string;\r\n}\r\n\r\n/**\r\n * A CAP-23 claim predicate as Horizon serializes it. A missing/`unconditional`\r\n * predicate is always claimable; the time-bounded variants are evaluated\r\n * against ledger time so an unsatisfiable CB is not reported as income.\r\n */\r\nexport interface HorizonPredicate {\r\n unconditional?: boolean;\r\n and?: HorizonPredicate[];\r\n or?: HorizonPredicate[];\r\n not?: HorizonPredicate;\r\n /** RFC-3339 timestamp: claimable strictly BEFORE this absolute time. */\r\n abs_before?: string;\r\n /** Same bound as an epoch-seconds string (Horizon includes both). */\r\n abs_before_epoch?: string;\r\n /** Seconds since the CB was created after which it becomes claimable. */\r\n rel_before?: string;\r\n}\r\n\r\n/** A single claimant on a create_claimable_balance operation. */\r\nexport interface HorizonClaimant {\r\n destination: string;\r\n predicate?: HorizonPredicate;\r\n}\r\n\r\n/** A subset of a Horizon operation record relevant to the account method. */\r\nexport interface HorizonOp {\r\n id: string;\r\n type: string;\r\n transaction_hash: string;\r\n /** create_account: the newly created account */\r\n account?: string;\r\n /** create_account: starting balance (string, whole units) */\r\n starting_balance?: string;\r\n /** payment: destination account */\r\n to?: string;\r\n /** payment: amount (string, whole units) */\r\n amount?: string;\r\n /** payment / create_claimable_balance: asset type ('native' for XLM) */\r\n asset_type?: string;\r\n /** create_claimable_balance: asset in \"CODE:ISSUER\" form (or 'native') */\r\n asset?: string;\r\n /** create_claimable_balance: the claimants list */\r\n claimants?: HorizonClaimant[];\r\n}\r\n\r\n/** A Horizon claimable-balance record (used by the token account method). */\r\nexport interface HorizonClaimableBalance {\r\n id: string;\r\n asset: string;\r\n amount: string;\r\n sponsor?: string;\r\n claimants: HorizonClaimant[];\r\n /** Horizon paging token — used to resume the next page of a listing. */\r\n paging_token?: string;\r\n}\r\n\r\n/** Horizon account record subset (used to probe existence + sequence). */\r\nexport interface HorizonAccount {\r\n id: string;\r\n sequence: string;\r\n balances: Array<{ asset_type: string; balance: string }>;\r\n}\r\n\r\n/** Injectable fetch signature (compatible with the global `fetch`). */\r\nexport type FetchLike = (\r\n url: string,\r\n init?: { method?: string; headers?: Record<string, string>; body?: string },\r\n) => Promise<{\r\n ok: boolean;\r\n status: number;\r\n json(): Promise<unknown>;\r\n}>;\r\n\r\ninterface HorizonPage<T> {\r\n _links?: { next?: { href?: string } };\r\n _embedded?: { records?: T[] };\r\n}\r\n\r\n/** Horizon's maximum (and our fixed) page size for claimable-balance listings. */\r\nconst CLAIMABLE_BALANCE_PAGE_LIMIT = 200;\r\n\r\n/**\r\n * Defensive upper bound on claimable-balance pages fetched per listing\r\n * (50 pages x 200 records = 10,000 balances). Listing MUST page through every\r\n * record — an attacker can cheaply create claimable balances naming a stealth\r\n * address to push the genuine payment past page 1 — but the loop still needs a\r\n * hard stop so a misbehaving Horizon (or an extreme spam flood) cannot spin the\r\n * scanner forever.\r\n */\r\nconst MAX_CLAIMABLE_BALANCE_PAGES = 50;\r\n\r\n/** A thin, injectable-fetch Horizon REST client. */\r\nexport class HorizonClient {\r\n private readonly baseUrl: string;\r\n private readonly fetchFn: FetchLike;\r\n\r\n /**\r\n * @param baseUrl - Horizon root URL (no trailing slash required).\r\n * @param fetchFn - Injectable fetch (defaults to the global `fetch`).\r\n */\r\n constructor(baseUrl: string, fetchFn?: FetchLike) {\r\n this.baseUrl = baseUrl.replace(/\\/$/, '');\r\n this.fetchFn = fetchFn ?? (globalThis.fetch as unknown as FetchLike);\r\n }\r\n\r\n private async getJson<T>(path: string): Promise<T> {\r\n const res = await this.fetchFn(`${this.baseUrl}${path}`);\r\n if (!res.ok) {\r\n throw new Error(`Horizon GET ${path} failed: ${res.status}`);\r\n }\r\n return (await res.json()) as T;\r\n }\r\n\r\n /**\r\n * Page transactions in ascending order.\r\n *\r\n * @param cursor - Paging token to resume from (omit for the beginning).\r\n * @param limit - Page size (default 200, Horizon's max).\r\n * @returns The page's transaction records (may be empty).\r\n */\r\n async getTransactions(cursor?: string, limit = 200): Promise<HorizonTx[]> {\r\n const params = new URLSearchParams({\r\n order: 'asc',\r\n limit: String(limit),\r\n });\r\n if (cursor) params.set('cursor', cursor);\r\n const page = await this.getJson<HorizonPage<HorizonTx>>(\r\n `/transactions?${params.toString()}`,\r\n );\r\n return page._embedded?.records ?? [];\r\n }\r\n\r\n /**\r\n * The paging token of the newest transaction this Horizon serves (one\r\n * `order=desc&limit=1` page), or undefined on an empty network. The scan\r\n * uses it to sanity-clamp cursors adopted from indexer-supplied data: a\r\n * persisted scan cursor must never exceed the chain position Horizon\r\n * itself reports, or a malicious feed could blind every future scan.\r\n */\r\n async getLatestTransactionToken(): Promise<string | undefined> {\r\n const params = new URLSearchParams({ order: 'desc', limit: '1' });\r\n const page = await this.getJson<HorizonPage<HorizonTx>>(\r\n `/transactions?${params.toString()}`,\r\n );\r\n return page._embedded?.records?.[0]?.paging_token;\r\n }\r\n\r\n /**\r\n * Fetch the operations belonging to a single transaction.\r\n *\r\n * @param txHash - Transaction hash.\r\n * @returns The transaction's operation records.\r\n */\r\n async getTransactionOperations(txHash: string): Promise<HorizonOp[]> {\r\n const page = await this.getJson<HorizonPage<HorizonOp>>(\r\n `/transactions/${txHash}/operations?limit=200`,\r\n );\r\n return page._embedded?.records ?? [];\r\n }\r\n\r\n /**\r\n * Probe an account. Returns null if the account does not exist (404).\r\n *\r\n * @param address - Stellar G-address.\r\n */\r\n async getAccount(address: string): Promise<HorizonAccount | null> {\r\n const res = await this.fetchFn(`${this.baseUrl}/accounts/${address}`);\r\n if (res.status === 404) return null;\r\n if (!res.ok) throw new Error(`Horizon GET account failed: ${res.status}`);\r\n return (await res.json()) as HorizonAccount;\r\n }\r\n\r\n /**\r\n * List ALL claimable balances for which the given address is a claimant,\r\n * paging through every Horizon page (not just the first).\r\n *\r\n * Used by the token account method: a direct token send lands as a\r\n * CreateClaimableBalance to the derived stealth address, which the recipient\r\n * later claims. Returns an empty array when the account has none.\r\n *\r\n * Paging matters for correctness, not just completeness: anyone can create a\r\n * claimable balance naming a (public, on-chain) stealth address as claimant,\r\n * so an attacker could spam cheap balances to push the genuine payment past\r\n * the first page and make the scanner silently miss it. Each page is resumed\r\n * via the last record's `paging_token` (falling back to the `cursor` in\r\n * `_links.next.href`), stopping on a short page, a non-advancing cursor, or\r\n * the defensive {@link MAX_CLAIMABLE_BALANCE_PAGES} bound.\r\n *\r\n * @param claimant - Stellar G-address to filter claimable balances by.\r\n */\r\n async getClaimableBalances(\r\n claimant: string,\r\n ): Promise<HorizonClaimableBalance[]> {\r\n const all: HorizonClaimableBalance[] = [];\r\n let cursor: string | undefined;\r\n\r\n for (let i = 0; i < MAX_CLAIMABLE_BALANCE_PAGES; i++) {\r\n const cursorParam = cursor ? `&cursor=${encodeURIComponent(cursor)}` : '';\r\n const page = await this.getJson<HorizonPage<HorizonClaimableBalance>>(\r\n `/claimable_balances?claimant=${claimant}` +\r\n `&limit=${CLAIMABLE_BALANCE_PAGE_LIMIT}${cursorParam}`,\r\n );\r\n const records = page._embedded?.records ?? [];\r\n all.push(...records);\r\n\r\n // A short (or empty) page is the last page.\r\n if (records.length < CLAIMABLE_BALANCE_PAGE_LIMIT) break;\r\n\r\n const next =\r\n records[records.length - 1]?.paging_token ??\r\n this.cursorFromNextLink(page._links?.next?.href);\r\n // No cursor to advance with (or a stalled one) — stop rather than loop.\r\n if (!next || next === cursor) break;\r\n cursor = next;\r\n }\r\n\r\n return all;\r\n }\r\n\r\n /**\r\n * Extract the `cursor` query parameter from a Horizon `_links.next.href`.\r\n * Fallback for full pages whose records carry no `paging_token`.\r\n */\r\n private cursorFromNextLink(href: string | undefined): string | undefined {\r\n if (!href) return undefined;\r\n try {\r\n return new URL(href, this.baseUrl).searchParams.get('cursor') ?? undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Submit a base64 transaction envelope XDR to Horizon.\r\n *\r\n * @param xdr - base64-encoded transaction envelope.\r\n * @returns The submitted transaction hash.\r\n */\r\n async submitTransaction(xdr: string): Promise<{ hash: string }> {\r\n const res = await this.fetchFn(`${this.baseUrl}/transactions`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\r\n body: `tx=${encodeURIComponent(xdr)}`,\r\n });\r\n const body = (await res.json()) as {\r\n hash?: string;\r\n extras?: { result_codes?: unknown };\r\n };\r\n if (!res.ok || !body.hash) {\r\n throw new Error(\r\n `Horizon submit failed: ${JSON.stringify(body.extras?.result_codes ?? res.status)}`,\r\n );\r\n }\r\n return { hash: body.hash };\r\n }\r\n}\r\n","import type { FetchLike, HorizonOp } from './horizon.js';\r\nimport { IndexerHttpError, IndexerNetworkError } from './errors.js';\r\n\r\n/**\r\n * Indexer `/health` response. Coverage is the OPEN interval\r\n * `(startCursor, cursor]` over Horizon's ascending transaction feed: the tx\r\n * whose paging_token equals `startCursor` is NOT covered (the scan fetches it\r\n * from Horizon), while everything after it up to `cursor` is.\r\n */\r\nexport interface IndexerHealth {\r\n status: string;\r\n network?: string;\r\n /** Announcement store backend. */\r\n store?: string;\r\n /** Feed position fully covered by the indexer; `null` before first ingest. */\r\n cursor: string | null;\r\n /** First covered feed position (exclusive); `null` before first ingest. */\r\n startCursor: string | null;\r\n /** Close time of the last ingested ledger (ISO timestamp). */\r\n lastCloseTime?: string | null;\r\n /** Seconds the indexer lags the network head. */\r\n lagSeconds?: number | null;\r\n /** Total announcements held by the store. */\r\n announcements?: number;\r\n /**\r\n * Coverage holes (ledger ranges the indexer knows it skipped). A gapped\r\n * indexer reports `status: 'degraded'` and is therefore skipped by the\r\n * scan's health guard — listed here so operators can see WHAT is missing.\r\n */\r\n gaps?: Array<{ fromLedger: number; toLedger: number; detectedAt: string }>;\r\n /** Ingest-loop diagnostics (shape owned by the indexer service). */\r\n ingest?: unknown;\r\n}\r\n\r\n/**\r\n * One announcement served by the indexer: a successful hash-memo transaction\r\n * with its operation records inlined VERBATIM (the same `HorizonOp` shapes\r\n * Horizon's `/transactions/{hash}/operations` returns), so consumers need no\r\n * per-tx Horizon round-trip.\r\n */\r\nexport interface IndexerAnnouncement {\r\n hash: string;\r\n paging_token: string;\r\n /** base64 32-byte ephemeral key R (Horizon's MemoHash encoding). */\r\n memo: string;\r\n memo_type: string;\r\n successful: boolean;\r\n created_at?: string;\r\n /**\r\n * Transaction-level source account, when the indexer has it. Enables the\r\n * sponsor-precise claimable-balance binding without a per-tx Horizon\r\n * round-trip; older feeds omit it and the scan falls back to the\r\n * asset+amount binding.\r\n */\r\n source_account?: string;\r\n /** Verbatim Horizon operation records for this transaction. */\r\n operations: HorizonOp[];\r\n}\r\n\r\n/**\r\n * Response page from `GET /announcements`. `records` ascend by paging_token\r\n * and are strictly greater than the request cursor. `cursor` is the position\r\n * to adopt directly for the next call: the last record's token on a full\r\n * page, otherwise max(request cursor, indexer global cursor).\r\n */\r\nexport interface AnnouncementsPage {\r\n records: IndexerAnnouncement[];\r\n cursor: string;\r\n}\r\n\r\nconst DEFAULT_TIMEOUT_MS = 10_000;\r\n\r\n/** Race marker distinguishing a timeout from any value the fetch can produce. */\r\nconst TIMED_OUT: unique symbol = Symbol('timed out');\r\n\r\n/**\r\n * Race a promise against a clearable timer (same rationale as relayerPool's\r\n * helper: the injectable {@link FetchLike} carries no abort signal, and a\r\n * plain `setTimeout` stays visible to vitest's fake timers). The losing\r\n * promise keeps running; its rejection is swallowed by the detached guard.\r\n */\r\nfunction withTimeout<T>(\r\n promise: Promise<T>,\r\n ms: number,\r\n): Promise<T | typeof TIMED_OUT> {\r\n void promise.catch(() => {});\r\n let timer: ReturnType<typeof setTimeout> | undefined;\r\n const timeout = new Promise<typeof TIMED_OUT>((resolve) => {\r\n timer = setTimeout(() => resolve(TIMED_OUT), ms);\r\n });\r\n return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));\r\n}\r\n\r\n/**\r\n * Thin HTTP client for the announcement indexer service — the account\r\n * method's discovery accelerator. Horizon remains the source of truth: every\r\n * failure here surfaces as a typed error the scan treats as \"fall back to the\r\n * Horizon walk\", never as a lost payment.\r\n *\r\n * Transport failures and timeouts throw {@link IndexerNetworkError}; non-2xx\r\n * responses throw {@link IndexerHttpError} carrying the HTTP status and the\r\n * indexer's `{ error, code }` body code.\r\n *\r\n * @example\r\n * ```typescript\r\n * const indexer = new IndexerClient('http://localhost:3100');\r\n * const { cursor } = await indexer.health();\r\n * ```\r\n */\r\nexport class IndexerClient {\r\n private readonly baseUrl: string;\r\n private readonly fetchFn: FetchLike;\r\n private readonly timeoutMs: number;\r\n\r\n /**\r\n * @param baseUrl - Indexer root URL (no trailing slash required).\r\n * @param fetchFn - Injectable fetch (defaults to the global `fetch`).\r\n * @param opts - Optional per-request timeout in ms (default 10000).\r\n */\r\n constructor(\r\n baseUrl: string,\r\n fetchFn?: FetchLike,\r\n opts?: { timeoutMs?: number },\r\n ) {\r\n this.baseUrl = baseUrl.replace(/\\/$/, '');\r\n this.fetchFn = fetchFn ?? (globalThis.fetch as unknown as FetchLike);\r\n this.timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\r\n }\r\n\r\n private async get<T>(path: string): Promise<T> {\r\n let res: Awaited<ReturnType<FetchLike>>;\r\n try {\r\n const raced = await withTimeout(\r\n this.fetchFn(`${this.baseUrl}${path}`),\r\n this.timeoutMs,\r\n );\r\n if (raced === TIMED_OUT) {\r\n throw new IndexerNetworkError(\r\n path,\r\n `request timed out after ${this.timeoutMs}ms`,\r\n );\r\n }\r\n res = raced;\r\n } catch (err) {\r\n if (err instanceof IndexerNetworkError) throw err;\r\n throw new IndexerNetworkError(\r\n path,\r\n err instanceof Error ? err.message : String(err),\r\n );\r\n }\r\n return this.decode<T>(path, res);\r\n }\r\n\r\n /**\r\n * Decode an indexer response. A non-JSON body on an error status (e.g. a\r\n * proxy's HTML 502 page) must not mask the status, so decode failures fall\r\n * back to an empty body there; a non-JSON body on a 2xx is a broken indexer\r\n * and surfaces as a transport error.\r\n */\r\n private async decode<T>(\r\n path: string,\r\n res: Awaited<ReturnType<FetchLike>>,\r\n ): Promise<T> {\r\n let data: (T & { error?: string; code?: string }) | undefined;\r\n try {\r\n data = (await res.json()) as T & { error?: string; code?: string };\r\n } catch {\r\n data = undefined;\r\n }\r\n if (!res.ok) {\r\n throw new IndexerHttpError(path, res.status, data?.code, data?.error);\r\n }\r\n if (data === undefined) {\r\n throw new IndexerNetworkError(path, 'invalid JSON response body');\r\n }\r\n return data as T;\r\n }\r\n\r\n /** Probe the indexer's health and coverage window. */\r\n async health(): Promise<IndexerHealth> {\r\n return this.get<IndexerHealth>('/health');\r\n }\r\n\r\n /**\r\n * Fetch one page of announcements strictly after `cursor` (omit for the\r\n * start of coverage).\r\n *\r\n * @param cursor - Feed position to resume from (records returned are > it).\r\n * @param limit - Page size (the service caps it at 200).\r\n * @returns The page's records plus the cursor to adopt for the next call.\r\n */\r\n async getAnnouncements(\r\n cursor?: string,\r\n limit?: number,\r\n ): Promise<AnnouncementsPage> {\r\n const params = new URLSearchParams();\r\n if (cursor !== undefined) params.set('cursor', cursor);\r\n if (limit !== undefined) params.set('limit', String(limit));\r\n const query = params.toString();\r\n return this.get<AnnouncementsPage>(\r\n `/announcements${query ? `?${query}` : ''}`,\r\n );\r\n }\r\n}\r\n","/**\r\n * Exact decimal <-> stroop conversions.\r\n *\r\n * A stroop is 1e-7 of a Stellar asset unit. Converting whole-unit amounts with\r\n * `Math.round(amount * 1e7)` or `Number(stroops) / 1e7` silently loses precision\r\n * once the magnitude exceeds `Number.MAX_SAFE_INTEGER` stroops (~9.007e8 XLM) —\r\n * a float can no longer represent every integer stroop, so large sends drift.\r\n * These helpers keep the value as a `bigint` count of stroops end to end and\r\n * only render a string at the display edge, so no amount ever round-trips\r\n * through a lossy float.\r\n */\r\n\r\nconst STROOP_DECIMALS = 7;\r\nconst STROOPS_PER_UNIT = 10n ** BigInt(STROOP_DECIMALS);\r\n\r\n/**\r\n * Parse a decimal amount string (whole units, e.g. `\"100.5\"`) into an exact\r\n * `bigint` count of stroops.\r\n *\r\n * @param amount - Decimal string with at most 7 fractional digits.\r\n * @throws {Error} If the input is not a non-negative decimal, or carries more\r\n * than 7 fractional digits (which cannot be represented in stroops).\r\n */\r\nexport function parseStroops(amount: string): bigint {\r\n const trimmed = amount.trim();\r\n if (!/^\\d+(\\.\\d+)?$/.test(trimmed)) {\r\n throw new Error(\r\n `Invalid amount \"${amount}\" — expected a non-negative decimal number.`,\r\n );\r\n }\r\n\r\n const parts = trimmed.split('.');\r\n const wholePart = parts[0] ?? '0';\r\n const fracPartRaw = parts[1] ?? '';\r\n if (fracPartRaw.length > STROOP_DECIMALS) {\r\n throw new Error(\r\n `Amount \"${amount}\" has more than ${STROOP_DECIMALS} decimal places ` +\r\n '(smaller than one stroop).',\r\n );\r\n }\r\n\r\n const fracPart = fracPartRaw.padEnd(STROOP_DECIMALS, '0');\r\n return BigInt(wholePart) * STROOPS_PER_UNIT + BigInt(fracPart);\r\n}\r\n\r\n/**\r\n * Convert a `number` amount (whole units) into exact stroops, rejecting values\r\n * that cannot be represented exactly (non-finite, negative, or with sub-stroop\r\n * fractional precision). Prefer {@link parseStroops} when the amount originates\r\n * as a string; this exists for the numeric SDK surface.\r\n *\r\n * @param amount - Non-negative finite whole-unit amount.\r\n */\r\nexport function numberToStroops(amount: number): bigint {\r\n if (!Number.isFinite(amount) || amount < 0) {\r\n throw new Error(`Invalid amount ${amount} — expected a non-negative number.`);\r\n }\r\n return parseStroops(amount.toString());\r\n}\r\n\r\n/**\r\n * Render an exact `bigint` stroop count back to a fixed 7-decimal string\r\n * (e.g. `12345000000n` -> `\"1234.5000000\"`). Never goes through a float.\r\n *\r\n * @param stroops - Stroop count (non-negative).\r\n */\r\nexport function formatStroops(stroops: bigint): string {\r\n const negative = stroops < 0n;\r\n const abs = negative ? -stroops : stroops;\r\n const whole = abs / STROOPS_PER_UNIT;\r\n const frac = abs % STROOPS_PER_UNIT;\r\n const fracStr = frac.toString().padStart(STROOP_DECIMALS, '0');\r\n return `${negative ? '-' : ''}${whole.toString()}.${fracStr}`;\r\n}\r\n","import { Transaction } from '@stellar/stellar-sdk';\r\nimport type { FetchLike } from './horizon.js';\r\nimport { waitForTransaction, type TransactionStatusSource } from './soroban.js';\r\nimport { parseStroops } from './stroops.js';\r\nimport { RelayerHttpError, RelayerNetworkError } from './errors.js';\r\n\r\n/**\r\n * Signs a canonical challenge message with the funding account's ed25519 key,\r\n * proving control of that account for a fee-spending relayer request. Returns\r\n * the signature as base64 or hex (or raw bytes). Kept abstract so an app can\r\n * back it by a wallet, an HSM, or a raw secret key without the SDK ever holding\r\n * the funding key.\r\n */\r\nexport type FundingSigner = (\r\n message: string,\r\n) => Promise<Uint8Array | string> | Uint8Array | string;\r\n\r\n/** Response from `GET /credit/challenge`. */\r\nexport interface CreditChallenge {\r\n account: string;\r\n nonce: string;\r\n}\r\n\r\n/**\r\n * Canonical single-line message the funding account signs to authorize a spend.\r\n * MUST match the relayer's `challengeMessage` byte-for-byte. When `bind` is\r\n * supplied (e.g. the inner-tx hash on the `/relay` path) it is appended so the\r\n * signature is pinned to that specific transaction and cannot be paired with a\r\n * different attacker-signed inner XDR of the same amount.\r\n */\r\nexport function challengeMessage(\r\n endpoint: string,\r\n fundingAccount: string,\r\n nonce: string,\r\n amount: string,\r\n bind?: string,\r\n): string {\r\n const base = `shade-relayer:v1:${endpoint}:${fundingAccount}:${nonce}:${amount}`;\r\n return bind ? `${base}:${bind}` : base;\r\n}\r\n\r\n/** Relayer `/health` response. */\r\nexport interface RelayerHealth {\r\n status: string;\r\n network?: string;\r\n relayerAddress?: string;\r\n balance?: string;\r\n /** Whether the relayer gates fee-spending endpoints on credit. */\r\n requireCredit?: boolean;\r\n /** Advertised ceiling (XLM) on a fee-bump — the amount a client authorizes. */\r\n maxRelayFeeXlm?: number;\r\n /**\r\n * The reserve component (7-dp XLM string, e.g. `'1.0000000'`) a credit-gated\r\n * relayer adds to a sponsor-claim tx's fee when verifying the\r\n * proof-of-control signature. Clients signing the EXACT `fee + reserve`\r\n * total should prefer this over mirroring the relayer-side constant.\r\n */\r\n sponsoredReserveEstimate?: string;\r\n /** Credit-ledger backend: `'postgres'` (durable) or `'json'` (dev fallback). */\r\n store?: string;\r\n /** Nonce/rate-limit backend: `'redis'` (multi-instance) or `'memory'`. */\r\n sharedState?: string;\r\n}\r\n\r\n/** Options for {@link RelayerClient.relay}. */\r\nexport interface RelayOpts {\r\n /** App account to debit the fee-bump fee against (credit-gated relayers). */\r\n fundingAccount?: string;\r\n /** Signer proving control of `fundingAccount` (credit-gated relayers). */\r\n fundingSigner?: FundingSigner;\r\n /**\r\n * The fee/amount (7-dp XLM string) the proof-of-control signature authorizes.\r\n * MUST equal the fee the relayer will charge, or the relayer rejects with 401.\r\n */\r\n authAmount?: string;\r\n /**\r\n * Network passphrase used to compute the inner-tx hash bound into the\r\n * proof-of-control signature. MUST match the passphrase the relayer verifies\r\n * under, or a credit-gated relayer rejects with 401. Required to bind the\r\n * inner tx on a credit-gated `/relay`; omit for the free/default path.\r\n */\r\n networkPassphrase?: string;\r\n /**\r\n * Do not trust the relayer's returned txHash at face value: poll it to a\r\n * terminal on-chain status before resolving (SDK-TXHASH-TRUST). Requires an\r\n * `rpcServer` in the {@link RelayerClient} constructor opts. Throws\r\n * `TransactionTimeoutError` (carrying the txHash) if the poll window closes\r\n * while the tx is still unseen/pending, or an error if it FAILED on-chain.\r\n * Default `false`: resolve as soon as the relayer responds, exactly as before.\r\n */\r\n confirm?: boolean;\r\n}\r\n\r\n/** Options for {@link RelayerClient.sponsor}. */\r\nexport interface SponsorOpts {\r\n /** Starting balance for the newly created account (whole XLM). */\r\n startingBalance?: string;\r\n /** App account to debit against (credit-gated relayers). */\r\n fundingAccount?: string;\r\n /** Signer proving control of `fundingAccount` (credit-gated relayers). */\r\n fundingSigner?: FundingSigner;\r\n /**\r\n * The total (startingBalance + fee, 7-dp XLM string) the proof-of-control\r\n * signature authorizes. MUST equal what the relayer will charge.\r\n */\r\n authAmount?: string;\r\n}\r\n\r\n/** Arguments for {@link RelayerClient.sponsorClaimPrepare}. */\r\nexport interface SponsorClaimPrepareArgs {\r\n /** The stealth address that will claim the balance. */\r\n stealthAddress: string;\r\n /** Asset to add a trustline for, in \"CODE:ISSUER\" form. */\r\n asset: string;\r\n /** Claimable balance id to claim. */\r\n balanceId: string;\r\n /** Destination that the claimed token is paid out to (must trust the asset). */\r\n destination: string;\r\n /** Amount of the claimed token to pay out to the destination (7-dp string). */\r\n amount: string;\r\n}\r\n\r\n/** Response from {@link RelayerClient.sponsorClaimPrepare}. */\r\nexport interface SponsorClaimPrepared {\r\n /** Unsigned transaction XDR for the client to co-sign with the stealth key. */\r\n xdr: string;\r\n /** ISO timestamp after which the prepared tx's timebounds expire. */\r\n expiresAt: string;\r\n}\r\n\r\n/** A read-only credit-ledger view for an app funding account. */\r\nexport interface CreditView {\r\n fundingAccount: string;\r\n balance: string;\r\n updatedAt?: string;\r\n}\r\n\r\n/**\r\n * Thin HTTP client for the reserve relayer service. Every fee-spending endpoint\r\n * is exposed as a typed method so the SDK (and apps) never hand-roll fetch calls\r\n * or URL joining. Construct once and reuse.\r\n *\r\n * @example\r\n * ```typescript\r\n * const relayer = new RelayerClient('http://localhost:3000');\r\n * const { status } = await relayer.health();\r\n * ```\r\n */\r\nexport class RelayerClient {\r\n private readonly baseUrl: string;\r\n private readonly fetchFn: FetchLike;\r\n private readonly fundingSigner?: FundingSigner;\r\n private readonly fundingAccount?: string;\r\n private readonly rpcServer?: TransactionStatusSource;\r\n\r\n /**\r\n * @param baseUrl - Relayer root URL. A trailing `/relay` is stripped so a\r\n * bare relay URL (back-compat) resolves to the service root.\r\n * @param fetchFn - Injectable fetch (defaults to the global `fetch`).\r\n * @param opts - Optional default `fundingAccount` + `fundingSigner` used to\r\n * authenticate fee-spending requests against a credit-gated relayer, and\r\n * an optional `rpcServer` (an `rpc.Server`, or any object with its\r\n * `getTransaction`) used to confirm-poll returned tx hashes when a call\r\n * sets `confirm: true`.\r\n */\r\n constructor(\r\n baseUrl: string,\r\n fetchFn?: FetchLike,\r\n opts?: {\r\n fundingAccount?: string;\r\n fundingSigner?: FundingSigner;\r\n rpcServer?: TransactionStatusSource;\r\n },\r\n ) {\r\n this.baseUrl = baseUrl.replace(/\\/relay\\/?$/, '').replace(/\\/$/, '');\r\n this.fetchFn = fetchFn ?? (globalThis.fetch as unknown as FetchLike);\r\n this.fundingAccount = opts?.fundingAccount;\r\n this.fundingSigner = opts?.fundingSigner;\r\n this.rpcServer = opts?.rpcServer;\r\n }\r\n\r\n /**\r\n * Poll a relayer-returned txHash until it lands on-chain (SDK-TXHASH-TRUST).\r\n * A relayer could return a fabricated or failed hash with a 200; polling to a\r\n * terminal status is what turns \"the relayer said so\" into \"the chain says\r\n * so\". Deliberately loud when no poll handle exists — silently skipping the\r\n * confirmation a caller asked for would defeat its purpose. On timeout the\r\n * underlying `waitForTransaction` throws `TransactionTimeoutError` carrying\r\n * the txHash, so the caller can keep polling instead of blindly resubmitting.\r\n */\r\n private async confirmOnChain(txHash: string): Promise<void> {\r\n if (!this.rpcServer) {\r\n throw new Error(\r\n 'confirm: true requires an RPC handle: pass opts.rpcServer (an rpc.Server ' +\r\n 'for the same network) to the RelayerClient constructor.',\r\n );\r\n }\r\n await waitForTransaction(this.rpcServer, txHash);\r\n }\r\n\r\n /**\r\n * Fetch a fresh challenge nonce for `fundingAccount`, sign the canonical\r\n * message binding `endpoint` + account + nonce + `amount`, and return the\r\n * `{ fundingAccount, nonce, signature }` to attach to a fee-spending request.\r\n * Returns `undefined` when no signer is available (non-gated relayer path).\r\n */\r\n private async signedAuth(\r\n endpoint: string,\r\n fundingAccount: string | undefined,\r\n signer: FundingSigner | undefined,\r\n amount: string | undefined,\r\n bind?: string,\r\n ): Promise<{ nonce: string; signature: string } | undefined> {\r\n const account = fundingAccount ?? this.fundingAccount;\r\n const fundingSigner = signer ?? this.fundingSigner;\r\n if (!account || !fundingSigner) return undefined;\r\n const authAmount = amount ?? '0';\r\n const { nonce } = await this.get<CreditChallenge>(\r\n `/credit/challenge?account=${encodeURIComponent(account)}`,\r\n );\r\n const message = challengeMessage(endpoint, account, nonce, authAmount, bind);\r\n const raw = await fundingSigner(message);\r\n const signature =\r\n typeof raw === 'string' ? raw : Buffer.from(raw).toString('base64');\r\n return { nonce, signature };\r\n }\r\n\r\n // Transport failures throw RelayerNetworkError and non-2xx responses throw\r\n // RelayerHttpError (message text unchanged) so callers — and RelayerPool's\r\n // failover — can branch on the failure KIND: unreachable/5xx is a relayer\r\n // fault worth failing over, 4xx is this request's fault and would repeat.\r\n private async post<T>(path: string, body: unknown): Promise<T> {\r\n let res: Awaited<ReturnType<FetchLike>>;\r\n try {\r\n res = await this.fetchFn(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(body),\r\n });\r\n } catch (err) {\r\n throw new RelayerNetworkError(\r\n path,\r\n err instanceof Error ? err.message : String(err),\r\n );\r\n }\r\n return this.decode<T>(path, res);\r\n }\r\n\r\n private async get<T>(path: string): Promise<T> {\r\n let res: Awaited<ReturnType<FetchLike>>;\r\n try {\r\n res = await this.fetchFn(`${this.baseUrl}${path}`);\r\n } catch (err) {\r\n throw new RelayerNetworkError(\r\n path,\r\n err instanceof Error ? err.message : String(err),\r\n );\r\n }\r\n return this.decode<T>(path, res);\r\n }\r\n\r\n /**\r\n * Decode a relayer response. A non-JSON body on an error status (e.g. a\r\n * proxy's HTML 502 page) must not mask the status, so decode failures fall\r\n * back to an empty body there; a non-JSON body on a 2xx is a broken relayer\r\n * and surfaces as a transport error.\r\n */\r\n private async decode<T>(\r\n path: string,\r\n res: Awaited<ReturnType<FetchLike>>,\r\n ): Promise<T> {\r\n let data: (T & { error?: string; code?: string }) | undefined;\r\n try {\r\n data = (await res.json()) as T & { error?: string; code?: string };\r\n } catch {\r\n data = undefined;\r\n }\r\n if (!res.ok) {\r\n throw new RelayerHttpError(path, res.status, data?.code, data?.error);\r\n }\r\n if (data === undefined) {\r\n throw new RelayerNetworkError(path, 'invalid JSON response body');\r\n }\r\n return data as T;\r\n }\r\n\r\n /** Probe the relayer's health, balance, and address. */\r\n async health(): Promise<RelayerHealth> {\r\n return this.get<RelayerHealth>('/health');\r\n }\r\n\r\n /**\r\n * Fee-bump and submit a signed transaction envelope.\r\n *\r\n * @param xdr - base64 signed transaction envelope.\r\n * @param opts - Optional funding account to debit the fee against, and\r\n * `confirm` to poll the returned hash to an on-chain terminal status.\r\n * @returns The submitted transaction hash.\r\n */\r\n async relay(xdr: string, opts?: RelayOpts): Promise<{ txHash: string }> {\r\n const fundingAccount = opts?.fundingAccount ?? this.fundingAccount;\r\n const fundingSigner = opts?.fundingSigner ?? this.fundingSigner;\r\n // Bind the inner-tx hash into the proof-of-control signature so a captured\r\n // {nonce, signature} cannot be paired with a different inner XDR (REL-01\r\n // tx-binding). MUST use the same network passphrase the relayer verifies\r\n // under; only computable when a passphrase is supplied.\r\n const innerTxHash = opts?.networkPassphrase\r\n ? new Transaction(xdr, opts.networkPassphrase).hash().toString('hex')\r\n : undefined;\r\n // The signed amount is a fee CEILING, not the exact fee: a client cannot\r\n // predict the relayer's built fee (it depends on the relayer's clamped\r\n // base-fee fetch), so it authorizes \"debit up to authAmount for THIS inner\r\n // tx\". Default the ceiling to the relayer's advertised max fee when a\r\n // signer is in play and the caller didn't pin one.\r\n let authAmount = opts?.authAmount;\r\n if (fundingAccount && fundingSigner && authAmount === undefined) {\r\n authAmount = await this.maxRelayFee();\r\n }\r\n const auth = await this.signedAuth(\r\n 'relay',\r\n fundingAccount,\r\n opts?.fundingSigner,\r\n authAmount,\r\n innerTxHash,\r\n );\r\n const result = await this.post<{ txHash: string }>('/relay', {\r\n xdr,\r\n fundingAccount,\r\n ...(auth ? { ...auth, authAmount } : {}),\r\n });\r\n if (opts?.confirm) {\r\n await this.confirmOnChain(result.txHash);\r\n }\r\n return result;\r\n }\r\n\r\n /** Cached per-client relayer fee ceiling (XLM, 7-dp), fetched from /health. */\r\n private cachedMaxRelayFee?: string;\r\n\r\n /**\r\n * The relayer's advertised max fee-bump fee (`maxRelayFeeXlm` from /health),\r\n * as the fee ceiling to authorize. Falls back to the protocol default cap\r\n * (0.1 XLM) when an older relayer does not advertise it. Cached per client.\r\n */\r\n private async maxRelayFee(): Promise<string> {\r\n if (this.cachedMaxRelayFee) return this.cachedMaxRelayFee;\r\n let cap = 0.1;\r\n try {\r\n const h = await this.health();\r\n if (typeof h.maxRelayFeeXlm === 'number' && h.maxRelayFeeXlm > 0) {\r\n cap = h.maxRelayFeeXlm;\r\n }\r\n } catch {\r\n // Unreachable /health: fall back to the documented default cap.\r\n }\r\n this.cachedMaxRelayFee = cap.toFixed(7);\r\n return this.cachedMaxRelayFee;\r\n }\r\n\r\n /** Cached per-client sponsored-reserve estimate; `null` = fetched, absent. */\r\n private cachedSponsoredReserve?: bigint | null;\r\n\r\n /**\r\n * The relayer's advertised sponsored-reserve estimate\r\n * (`sponsoredReserveEstimate` from /health), parsed to exact stroops.\r\n * Returns `undefined` when the relayer does not advertise one, the value is\r\n * unparsable, or /health is unreachable — the caller falls back to its own\r\n * mirrored constant, so a health fault never breaks a claim. Cached per\r\n * client, mirroring {@link maxRelayFee}.\r\n */\r\n async sponsoredReserveEstimateStroops(): Promise<bigint | undefined> {\r\n if (this.cachedSponsoredReserve === undefined) {\r\n let estimate: bigint | null = null;\r\n try {\r\n const h = await this.health();\r\n if (typeof h.sponsoredReserveEstimate === 'string') {\r\n estimate = parseStroops(h.sponsoredReserveEstimate);\r\n }\r\n } catch {\r\n // Unreachable /health or an unparsable value: leave null so the\r\n // caller's fallback applies.\r\n }\r\n this.cachedSponsoredReserve = estimate;\r\n }\r\n return this.cachedSponsoredReserve ?? undefined;\r\n }\r\n\r\n /**\r\n * Create a stealth account from the relayer's own balance (funded\r\n * CreateAccount — no sponsorship sandwich).\r\n *\r\n * @param address - Stealth G-address to create.\r\n * @param opts - Starting balance and optional funding account.\r\n */\r\n async sponsor(\r\n address: string,\r\n opts?: SponsorOpts,\r\n ): Promise<{ txHash: string }> {\r\n const fundingAccount = opts?.fundingAccount ?? this.fundingAccount;\r\n const auth = await this.signedAuth(\r\n 'sponsor',\r\n fundingAccount,\r\n opts?.fundingSigner,\r\n opts?.authAmount,\r\n );\r\n return this.post<{ txHash: string }>('/sponsor', {\r\n address,\r\n startingBalance: opts?.startingBalance,\r\n fundingAccount,\r\n ...(auth ?? {}),\r\n });\r\n }\r\n\r\n /**\r\n * Ask the relayer to build the sponsored claimable-balance-claim transaction.\r\n * Returns UNSIGNED XDR the client must co-sign with the stealth key before\r\n * calling {@link sponsorClaimSubmit}.\r\n */\r\n async sponsorClaimPrepare(\r\n args: SponsorClaimPrepareArgs,\r\n ): Promise<SponsorClaimPrepared> {\r\n return this.post<SponsorClaimPrepared>('/sponsor-claim/prepare', args);\r\n }\r\n\r\n /**\r\n * Submit a sponsor-claim transaction the client has co-signed. The relayer\r\n * re-derives the expected operations from the trusted inputs\r\n * (`stealthAddress`, `asset`, `balanceId`) and verifies the submitted ops\r\n * match field-by-field before adding its signature and submitting.\r\n *\r\n * @param xdr - The stealth-co-signed transaction XDR.\r\n * @param args - The trusted claim inputs (and optional funding account).\r\n * `confirm: true` polls the returned hash to an on-chain terminal status\r\n * (requires `rpcServer` in the constructor opts).\r\n */\r\n async sponsorClaimSubmit(\r\n xdr: string,\r\n args: {\r\n stealthAddress: string;\r\n asset: string;\r\n balanceId: string;\r\n destination: string;\r\n amount: string;\r\n fundingAccount?: string;\r\n fundingSigner?: FundingSigner;\r\n /** Total (reserve + fee) the proof-of-control signature authorizes. */\r\n authAmount?: string;\r\n /** Poll the returned txHash until it lands on-chain (see {@link RelayOpts.confirm}). */\r\n confirm?: boolean;\r\n },\r\n ): Promise<{ txHash: string }> {\r\n const fundingAccount = args.fundingAccount ?? this.fundingAccount;\r\n const auth = await this.signedAuth(\r\n 'sponsor-claim',\r\n fundingAccount,\r\n args.fundingSigner,\r\n args.authAmount,\r\n );\r\n const result = await this.post<{ txHash: string }>('/sponsor-claim/submit', {\r\n xdr,\r\n stealthAddress: args.stealthAddress,\r\n asset: args.asset,\r\n balanceId: args.balanceId,\r\n destination: args.destination,\r\n amount: args.amount,\r\n fundingAccount,\r\n ...(auth ?? {}),\r\n });\r\n if (args.confirm) {\r\n await this.confirmOnChain(result.txHash);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Report a completed on-chain deposit to the relayer so it credits the app's\r\n * funding account with the paid amount.\r\n */\r\n async creditClaim(\r\n fundingAccount: string,\r\n txHash: string,\r\n ): Promise<CreditView> {\r\n return this.post<CreditView>('/credit/claim', { fundingAccount, txHash });\r\n }\r\n\r\n /** Read the current credit balance for an app funding account. */\r\n async creditBalance(fundingAccount: string): Promise<CreditView> {\r\n return this.get<CreditView>(`/credit/${fundingAccount}`);\r\n }\r\n}\r\n","import { RelayerClient } from './relayer.js';\r\nimport type { FundingSigner, RelayerHealth } from './relayer.js';\r\nimport type { FetchLike } from './horizon.js';\r\nimport type { NetworkName, TransactionStatusSource } from './soroban.js';\r\nimport {\r\n NoHealthyRelayerError,\r\n RelayerHttpError,\r\n RelayerNetworkError,\r\n} from './errors.js';\r\n\r\n/**\r\n * How a healthy relayer is picked from the candidate list. `'random'` is the\r\n * default deliberately: users spread across the relayer set instead of herding\r\n * onto the first entry, preserving the anonymity-set benefit of shared\r\n * relayers. `'first'` gives deterministic priority ordering.\r\n */\r\nexport type RelayerSelection = 'random' | 'first';\r\n\r\n/** Tuning knobs for a {@link RelayerPool}. Every field has a safe default. */\r\nexport interface RelayerPoolOpts {\r\n /**\r\n * Network name a candidate's `/health` must report. Omit (or an unknown\r\n * passphrase upstream) to skip the check; a candidate that reports no\r\n * network also passes — only an explicit contradiction rejects.\r\n */\r\n network?: NetworkName;\r\n /** Selection strategy. Default `'random'`. */\r\n selection?: RelayerSelection;\r\n /** Injectable fetch (tests); defaults to the global `fetch`. */\r\n fetchFn?: FetchLike;\r\n /** Shared parallel `/health` probe budget in ms. Default 2500. */\r\n probeTimeoutMs?: number;\r\n /**\r\n * Per-attempt budget in ms inside {@link RelayerPool.withRelayer}, applied\r\n * ONLY while a failover alternative remains. Default 10000.\r\n */\r\n attemptTimeoutMs?: number;\r\n /**\r\n * Minimum XLM balance a candidate must report to count as healthy — a\r\n * relayer one fee-bump from empty is operationally dead. Default 1 XLM\r\n * (~10 fee-bumps at the default 0.1 cap).\r\n */\r\n minBalanceXlm?: number;\r\n /** Probe cache TTL in ms (per pool instance). Default 30000. */\r\n probeTtlMs?: number;\r\n /** Injectable RNG for `'random'` selection (tests). Default `Math.random`. */\r\n rng?: () => number;\r\n}\r\n\r\n/**\r\n * Per-call context the health rule and the built clients need: a credit-gated\r\n * relayer only counts as healthy when the caller can actually pass its gate\r\n * (`fundingAccount` + `fundingSigner` present).\r\n */\r\nexport interface RelayerCallCtx {\r\n fundingAccount?: string;\r\n fundingSigner?: FundingSigner;\r\n rpcServer?: TransactionStatusSource;\r\n}\r\n\r\n/** One candidate's probe result: a health document, or the rejection reason. */\r\nexport interface ProbeOutcome {\r\n url: string;\r\n health?: RelayerHealth;\r\n reason?: string;\r\n}\r\n\r\n/**\r\n * Normalize a relayer config value into a clean URL list: trims entries, drops\r\n * empties, and collapses an empty result to `undefined` so `[]` and `['']`\r\n * mean \"no relayer\" everywhere a truthiness check gates relayed behavior\r\n * (e.g. the account claim's merge-fee arithmetic).\r\n */\r\nexport function normalizeRelayList(\r\n relay?: string | string[],\r\n): string[] | undefined {\r\n if (relay === undefined) return undefined;\r\n const list = (Array.isArray(relay) ? relay : [relay])\r\n .map((url) => url.trim())\r\n .filter(Boolean);\r\n return list.length > 0 ? list : undefined;\r\n}\r\n\r\nconst DEFAULT_PROBE_TIMEOUT_MS = 2_500;\r\nconst DEFAULT_ATTEMPT_TIMEOUT_MS = 10_000;\r\nconst DEFAULT_MIN_RELAYER_BALANCE_XLM = 1;\r\nconst DEFAULT_PROBE_TTL_MS = 30_000;\r\n\r\n/** Race marker distinguishing a timeout from any value the work can produce. */\r\nconst TIMED_OUT: unique symbol = Symbol('timed out');\r\n\r\n/**\r\n * Race a promise against a clearable timer. Deliberately NOT\r\n * `AbortSignal.timeout`: the injectable {@link FetchLike} carries no signal,\r\n * and platform timers are invisible to vitest's fake timers — a plain\r\n * `setTimeout` keeps both the abandonment semantics and the tests honest. The\r\n * losing promise is left running; its rejection (if any) is swallowed by the\r\n * detached guard so it cannot surface as an unhandled rejection.\r\n */\r\nfunction withTimeout<T>(\r\n promise: Promise<T>,\r\n ms: number,\r\n): Promise<T | typeof TIMED_OUT> {\r\n void promise.catch(() => {});\r\n let timer: ReturnType<typeof setTimeout> | undefined;\r\n const timeout = new Promise<typeof TIMED_OUT>((resolve) => {\r\n timer = setTimeout(() => resolve(TIMED_OUT), ms);\r\n });\r\n return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));\r\n}\r\n\r\n/** Fisher–Yates shuffle in place with an injectable RNG. */\r\nfunction shuffle<T>(items: T[], rng: () => number): void {\r\n for (let i = items.length - 1; i > 0; i--) {\r\n const j = Math.floor(rng() * (i + 1));\r\n [items[i], items[j]] = [items[j]!, items[i]!];\r\n }\r\n}\r\n\r\n/**\r\n * Health-probing selector and failover harness over a list of relayer URLs\r\n * (A3 BYO-relayer discovery).\r\n *\r\n * A candidate is healthy iff its `/health` reports `status === 'ok'`, its\r\n * network matches the expected one (when both sides are known), its balance\r\n * meets the minimum, and its credit gate is passable — `requireCredit ===\r\n * false`, or the caller brought funding auth. `requireCredit` missing is\r\n * treated as gated (fail-closed, matching the relayer's gating-on default).\r\n *\r\n * A single-URL pool is a transparent pass-through: no probe, no timeout —\r\n * byte-identical behavior to constructing a `RelayerClient` directly, so\r\n * existing single-relayer callers see no new traffic or failure modes.\r\n */\r\nexport class RelayerPool {\r\n readonly candidates: readonly string[];\r\n private readonly network?: NetworkName;\r\n private readonly selection: RelayerSelection;\r\n private readonly fetchFn?: FetchLike;\r\n private readonly probeTimeoutMs: number;\r\n private readonly attemptTimeoutMs: number;\r\n private readonly minBalanceXlm: number;\r\n private readonly probeTtlMs: number;\r\n private readonly rng: () => number;\r\n private cachedProbe?: ProbeOutcome[];\r\n private cachedProbeAt = 0;\r\n\r\n constructor(candidates: string[], opts?: RelayerPoolOpts) {\r\n if (candidates.length === 0) {\r\n throw new Error('RelayerPool requires at least one candidate URL');\r\n }\r\n this.candidates = [...candidates];\r\n this.network = opts?.network;\r\n this.selection = opts?.selection ?? 'random';\r\n this.fetchFn = opts?.fetchFn;\r\n this.probeTimeoutMs = opts?.probeTimeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;\r\n this.attemptTimeoutMs = opts?.attemptTimeoutMs ?? DEFAULT_ATTEMPT_TIMEOUT_MS;\r\n this.minBalanceXlm = opts?.minBalanceXlm ?? DEFAULT_MIN_RELAYER_BALANCE_XLM;\r\n this.probeTtlMs = opts?.probeTtlMs ?? DEFAULT_PROBE_TTL_MS;\r\n this.rng = opts?.rng ?? Math.random;\r\n }\r\n\r\n /**\r\n * Build a pool from any accepted relayer config shape, or `undefined` when\r\n * the input normalizes to \"no relayer\" — the back-compat seam that lets\r\n * `RelayerPool.from(opts.relay)` slot in wherever a single URL was used.\r\n */\r\n static from(\r\n relay: string | string[] | undefined,\r\n opts?: RelayerPoolOpts,\r\n ): RelayerPool | undefined {\r\n const list = normalizeRelayList(relay);\r\n return list ? new RelayerPool(list, opts) : undefined;\r\n }\r\n\r\n /**\r\n * Probe every candidate's `/health` in parallel under one shared time\r\n * budget. Results are cached per pool instance for {@link\r\n * RelayerPoolOpts.probeTtlMs}; `force` refreshes. Only transport-level\r\n * outcomes are recorded here — health-rule classification happens per call\r\n * in {@link select}/{@link withRelayer}, because it depends on the caller's\r\n * funding context.\r\n */\r\n async probe(force = false): Promise<ProbeOutcome[]> {\r\n const now = Date.now();\r\n if (\r\n !force &&\r\n this.cachedProbe &&\r\n now - this.cachedProbeAt < this.probeTtlMs\r\n ) {\r\n return this.cachedProbe;\r\n }\r\n const outcomes = await Promise.all(\r\n this.candidates.map(async (url): Promise<ProbeOutcome> => {\r\n const client = new RelayerClient(url, this.fetchFn);\r\n try {\r\n const health = await withTimeout(client.health(), this.probeTimeoutMs);\r\n if (health === TIMED_OUT) return { url, reason: 'timeout' };\r\n return { url, health };\r\n } catch (err) {\r\n if (err instanceof RelayerHttpError) {\r\n return { url, reason: `http_${err.status}` };\r\n }\r\n const detail = err instanceof Error ? err.message : String(err);\r\n return { url, reason: `unreachable: ${detail}` };\r\n }\r\n }),\r\n );\r\n this.cachedProbe = outcomes;\r\n this.cachedProbeAt = now;\r\n return outcomes;\r\n }\r\n\r\n /**\r\n * Pick one healthy relayer URL for this call, or throw\r\n * {@link NoHealthyRelayerError} naming every candidate's rejection reason.\r\n * A single-candidate pool returns its URL without probing (pass-through).\r\n */\r\n async select(ctx?: RelayerCallCtx): Promise<string> {\r\n if (this.candidates.length === 1) return this.candidates[0]!;\r\n const { healthy, reasons } = await this.rankHealthy(ctx);\r\n if (healthy.length === 0) throw new NoHealthyRelayerError(reasons);\r\n return healthy[0]!;\r\n }\r\n\r\n /**\r\n * Run `fn` against a selected relayer, failing over to the next healthy\r\n * candidate ONLY on transport faults — {@link RelayerNetworkError}, a 5xx\r\n * {@link RelayerHttpError}, or an attempt timeout. A 4xx (bad request,\r\n * insufficient credit) or any non-transport error would just repeat and\r\n * rethrows immediately. At most 2 attempts; the attempt timeout applies\r\n * only while another candidate remains.\r\n *\r\n * Failover after an ambiguous timeout cannot double-spend: both attempts\r\n * fee-bump the SAME signed inner tx, so its sequence number lets at most\r\n * one land (`txBAD_SEQ` for the loser).\r\n */\r\n async withRelayer<T>(\r\n fn: (client: RelayerClient, url: string) => Promise<T>,\r\n ctx?: RelayerCallCtx,\r\n ): Promise<T> {\r\n if (this.candidates.length === 1) {\r\n const url = this.candidates[0]!;\r\n return fn(this.buildClient(url, ctx), url);\r\n }\r\n const { healthy, reasons } = await this.rankHealthy(ctx);\r\n if (healthy.length === 0) throw new NoHealthyRelayerError(reasons);\r\n\r\n const attempts = healthy.slice(0, 2);\r\n let lastError: unknown;\r\n for (let i = 0; i < attempts.length; i++) {\r\n const url = attempts[i]!;\r\n const hasFallback = i < attempts.length - 1;\r\n try {\r\n const attempt = fn(this.buildClient(url, ctx), url);\r\n const result = hasFallback\r\n ? await withTimeout(attempt, this.attemptTimeoutMs)\r\n : await attempt;\r\n if (result === TIMED_OUT) {\r\n lastError = new RelayerNetworkError(\r\n url,\r\n `attempt timed out after ${this.attemptTimeoutMs}ms`,\r\n );\r\n continue;\r\n }\r\n return result as T;\r\n } catch (err) {\r\n const transient =\r\n err instanceof RelayerNetworkError ||\r\n (err instanceof RelayerHttpError && err.status >= 500);\r\n if (transient && hasFallback) {\r\n lastError = err;\r\n continue;\r\n }\r\n throw err;\r\n }\r\n }\r\n throw lastError;\r\n }\r\n\r\n /** Per-call client carrying the caller's funding auth + confirm handle. */\r\n private buildClient(url: string, ctx?: RelayerCallCtx): RelayerClient {\r\n return new RelayerClient(url, this.fetchFn, {\r\n fundingAccount: ctx?.fundingAccount,\r\n fundingSigner: ctx?.fundingSigner,\r\n rpcServer: ctx?.rpcServer,\r\n });\r\n }\r\n\r\n /**\r\n * Classify every probed candidate for this call's context and order the\r\n * healthy ones by the selection strategy.\r\n */\r\n private async rankHealthy(ctx?: RelayerCallCtx): Promise<{\r\n healthy: string[];\r\n reasons: Record<string, string>;\r\n }> {\r\n const outcomes = await this.probe();\r\n const healthy: string[] = [];\r\n const reasons: Record<string, string> = {};\r\n for (const outcome of outcomes) {\r\n if (!outcome.health) {\r\n reasons[outcome.url] = outcome.reason ?? 'unreachable';\r\n continue;\r\n }\r\n const reason = this.healthReason(outcome.health, ctx);\r\n if (reason) reasons[outcome.url] = reason;\r\n else healthy.push(outcome.url);\r\n }\r\n if (this.selection === 'random') shuffle(healthy, this.rng);\r\n return { healthy, reasons };\r\n }\r\n\r\n /** The health rule. Returns the rejection reason, or `undefined` = healthy. */\r\n private healthReason(\r\n health: RelayerHealth,\r\n ctx?: RelayerCallCtx,\r\n ): string | undefined {\r\n if (health.status !== 'ok') return 'status_not_ok';\r\n if (\r\n this.network !== undefined &&\r\n health.network !== undefined &&\r\n health.network !== this.network\r\n ) {\r\n return `network_mismatch (${health.network} != ${this.network})`;\r\n }\r\n if (health.balance !== undefined) {\r\n const balance = Number(health.balance);\r\n if (!Number.isFinite(balance) || balance < this.minBalanceXlm) {\r\n return `balance_below_min (${health.balance} < ${this.minBalanceXlm})`;\r\n }\r\n }\r\n // requireCredit missing = treated as gated: the relayer defaults gating ON,\r\n // so an old/withholding relayer must not be routed to without funding auth.\r\n const hasFundingAuth = !!(ctx?.fundingAccount && ctx?.fundingSigner);\r\n if (health.requireCredit !== false && !hasFundingAuth) {\r\n return 'credit_gated_no_funding_auth';\r\n }\r\n return undefined;\r\n }\r\n}\r\n","import {\r\n Keypair,\r\n Transaction,\r\n TransactionBuilder,\r\n} from '@stellar/stellar-sdk';\r\nimport type { TransactionSigner } from '../types.js';\r\n\r\n/**\r\n * Sign a transaction's sender / fee-payer leg, either locally with a secret or\r\n * by delegating to an external {@link TransactionSigner} (Freighter-style).\r\n *\r\n * When `signer` is set, `secretOrAddress` is treated as a PUBLIC G-address: the\r\n * unsigned XDR is handed to the signer and the returned signed XDR is rebuilt\r\n * into a {@link Transaction}. Rebuilding from the signer's output (rather than\r\n * mutating the input) preserves any Soroban footprint/auth the signed envelope\r\n * carries, which matters for the pool legs.\r\n *\r\n * When `signer` is absent, `secretOrAddress` is a Stellar secret and the\r\n * transaction is signed in place with `Keypair.fromSecret` — behavior identical\r\n * to the pre-signer code path.\r\n *\r\n * This helper is ONLY used for the sender / fee-payer legs. The stealth-key\r\n * legs sign with the recovered stealth scalar and never pass through here — a\r\n * wallet cannot hold that scalar.\r\n *\r\n * @param tx - The unsigned transaction to sign.\r\n * @param secretOrAddress - A Stellar secret (local signing) or, when `signer`\r\n * is set, the G-address to sign with.\r\n * @param networkPassphrase - The network passphrase to sign/rebuild under.\r\n * @param signer - Optional external signer.\r\n * @returns The signed transaction.\r\n */\r\nexport async function signTx(\r\n tx: Transaction,\r\n secretOrAddress: string,\r\n networkPassphrase: string,\r\n signer?: TransactionSigner,\r\n): Promise<Transaction> {\r\n if (signer) {\r\n const signed = await signer(tx.toXDR(), {\r\n networkPassphrase,\r\n address: secretOrAddress,\r\n });\r\n return TransactionBuilder.fromXDR(signed, networkPassphrase) as Transaction;\r\n }\r\n tx.sign(Keypair.fromSecret(secretOrAddress));\r\n return tx;\r\n}\r\n","import {\r\n Account,\r\n Transaction,\r\n TransactionBuilder,\r\n Operation,\r\n SorobanDataBuilder,\r\n BASE_FEE,\r\n rpc,\r\n} from '@stellar/stellar-sdk';\r\nimport { EntryArchivedRestoringError } from '../errors.js';\r\n\r\n/**\r\n * How to sign a transaction leg for the restore flow — either the fee-payer\r\n * secret / external signer already used by the withdraw, expressed as a single\r\n * async callback. The helper stays agnostic to local-vs-Freighter signing.\r\n */\r\nexport type RestoreSigner = (tx: Transaction) => Promise<Transaction>;\r\n\r\n/**\r\n * How to submit a signed transaction — either directly to the RPC or fee-bumped\r\n * through the relayer, mirroring whatever the withdraw itself uses. Returns the\r\n * submitted transaction hash.\r\n */\r\nexport type RestoreSubmit = (tx: Transaction) => Promise<string>;\r\n\r\n/**\r\n * Optional progress reporter (the CLI wires this to a spinner/log line; the SDK\r\n * leaves it undefined).\r\n */\r\nexport type RestoreNotify = (message: string) => void;\r\n\r\n/**\r\n * Rebuild the invocation transaction (e.g. the withdraw) from a freshly-fetched\r\n * source account. Used ONLY on the restore branch: after the RestoreFootprint\r\n * consumes the source account's next sequence number, the invocation must be\r\n * rebuilt on the new sequence — reusing the original pre-restore transaction\r\n * would submit at an already-consumed sequence (`txBAD_SEQ`). The factory must\r\n * produce the exact same operation/fee/timeout as the original build so only the\r\n * sequence differs.\r\n */\r\nexport type RebuildInvocation = (account: Account) => Transaction;\r\n\r\n/**\r\n * Prepare a Soroban invocation transaction for submission, transparently\r\n * restoring an archived persistent footprint first when required.\r\n *\r\n * `server.prepareTransaction` only throws on a simulation ERROR — it never\r\n * consults `sim.restorePreamble`. When a recipient's persistent Balance/Nonce\r\n * entry has archived (Soroban state expiration), simulation returns\r\n * SUCCESS-with-restorePreamble; the bare prepare then assembles the withdraw\r\n * over the archived footprint, which submits but fails on-chain while\r\n * `get_balance`/`scan` still show the funds — an opaque brick.\r\n *\r\n * This helper reproduces `prepareTransaction`'s behavior for the normal path\r\n * (simulate → assemble the passed-in `tx`) but, when\r\n * {@link rpc.Api.isSimulationRestore} is true, first builds and submits a\r\n * RestoreFootprint transaction from `sim.restorePreamble`, waits for it to\r\n * succeed, then — because the restore consumes the fee-payer's next sequence\r\n * number — **re-fetches the source account and rebuilds the invocation on the\r\n * fresh sequence** via {@link RebuildInvocation} before re-simulating and\r\n * assembling. This avoids a `txBAD_SEQ` collision between the restore and the\r\n * withdraw. The non-archived path is behaviorally identical to the original\r\n * `prepareTransaction` call (the passed-in `tx` is assembled untouched).\r\n *\r\n * @param tx - The unsigned Soroban invocation transaction (e.g. the withdraw),\r\n * already built on the source account's current sequence. Used directly on the\r\n * non-archived path.\r\n * @param rebuildTx - Rebuilds the invocation from a freshly-fetched source\r\n * account; used only on the restore branch to obtain a non-colliding sequence.\r\n * @param server - The Soroban RPC server.\r\n * @param networkPassphrase - Network passphrase for building the restore tx.\r\n * @param signRestore - Signs the RestoreFootprint transaction (fee-payer leg).\r\n * @param submitRestore - Submits the signed RestoreFootprint transaction.\r\n * @param notify - Optional progress reporter.\r\n * @returns The assembled invocation transaction, ready to sign and submit.\r\n * @throws {EntryArchivedRestoringError} If the entry is archived and the\r\n * restore transaction could not be completed.\r\n */\r\nexport async function prepareWithRestore(\r\n tx: Transaction,\r\n rebuildTx: RebuildInvocation,\r\n server: rpc.Server,\r\n networkPassphrase: string,\r\n signRestore: RestoreSigner,\r\n submitRestore: RestoreSubmit,\r\n notify?: RestoreNotify,\r\n): Promise<Transaction> {\r\n const sim = await server.simulateTransaction(tx);\r\n\r\n if (rpc.Api.isSimulationError(sim)) {\r\n throw new Error(sim.error);\r\n }\r\n\r\n if (rpc.Api.isSimulationRestore(sim)) {\r\n notify?.('Stealth entry archived, restoring before withdraw…');\r\n await runRestore(\r\n sim.restorePreamble,\r\n tx.source,\r\n server,\r\n networkPassphrase,\r\n signRestore,\r\n submitRestore,\r\n );\r\n // The restore consumed the source's next sequence number. Re-fetch the\r\n // account and rebuild the invocation on the fresh sequence so the withdraw\r\n // does not collide with the just-submitted restore (txBAD_SEQ).\r\n let rebuilt: Transaction;\r\n try {\r\n const freshAccount = await server.getAccount(tx.source);\r\n rebuilt = rebuildTx(freshAccount);\r\n } catch (err) {\r\n throw new EntryArchivedRestoringError((err as Error).message);\r\n }\r\n // Re-simulate over the freshly restored footprint.\r\n const fresh = await server.simulateTransaction(rebuilt);\r\n if (rpc.Api.isSimulationError(fresh)) {\r\n throw new EntryArchivedRestoringError(fresh.error);\r\n }\r\n if (rpc.Api.isSimulationRestore(fresh)) {\r\n throw new EntryArchivedRestoringError(\r\n 'entry still archived after restore submitted',\r\n );\r\n }\r\n return rpc.assembleTransaction(rebuilt, fresh).build();\r\n }\r\n\r\n return rpc.assembleTransaction(tx, sim).build();\r\n}\r\n\r\n/**\r\n * Build, sign, submit and confirm a RestoreFootprint transaction from a\r\n * simulation's `restorePreamble`. Any failure is wrapped in\r\n * {@link EntryArchivedRestoringError} so the withdraw path surfaces a single,\r\n * actionable error type.\r\n */\r\nasync function runRestore(\r\n restorePreamble: { minResourceFee: string; transactionData: SorobanDataBuilder },\r\n source: string,\r\n server: rpc.Server,\r\n networkPassphrase: string,\r\n signRestore: RestoreSigner,\r\n submitRestore: RestoreSubmit,\r\n): Promise<void> {\r\n try {\r\n const account = await server.getAccount(source);\r\n const fee = (\r\n BigInt(restorePreamble.minResourceFee) + BigInt(BASE_FEE)\r\n ).toString();\r\n\r\n const restoreTx = new TransactionBuilder(account, {\r\n fee,\r\n networkPassphrase,\r\n })\r\n .setSorobanData(restorePreamble.transactionData.build())\r\n .addOperation(Operation.restoreFootprint({}))\r\n .setTimeout(30)\r\n .build();\r\n\r\n const signed = await signRestore(restoreTx);\r\n await submitRestore(signed);\r\n } catch (err) {\r\n if (err instanceof EntryArchivedRestoringError) throw err;\r\n throw new EntryArchivedRestoringError((err as Error).message);\r\n }\r\n}\r\n","import {\r\n decodeMetaAddress,\r\n deriveStealthAddressWithSecret,\r\n scanAnnouncements,\r\n recoverStealthPrivateKey,\r\n} from '@shade/crypto';\r\nimport {\r\n Keypair,\r\n TransactionBuilder,\r\n Contract,\r\n nativeToScVal,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { randomBytes } from '@noble/hashes/utils';\r\nimport {\r\n resolveTokenAddress,\r\n labelForToken,\r\n fetchAnnouncements,\r\n fetchAnnouncementCount,\r\n queryBalance,\r\n queryNonce,\r\n buildWithdrawMessage,\r\n resolveSendResult,\r\n networkNameForPassphrase,\r\n waitForTransaction,\r\n type RawAnnouncement,\r\n} from '../soroban.js';\r\nimport type {\r\n StealthKeys,\r\n SendReceipt,\r\n Payment,\r\n ClaimReceipt,\r\n ClaimOpts,\r\n} from '../types.js';\r\nimport type { DeliveryAdapter, AdapterSendParams } from './types.js';\r\nimport type { TransactionSigner } from '../types.js';\r\nimport {\r\n NoBalanceError,\r\n AnnouncementNotFoundError,\r\n FeePayerRequiredError,\r\n FeePayerAddressRequiredError,\r\n} from '../errors.js';\r\nimport { numberToStroops, formatStroops } from '../stroops.js';\r\nimport { type FundingSigner } from '../relayer.js';\r\nimport { RelayerPool, type RelayerSelection } from '../relayerPool.js';\r\nimport { signTx } from './sign.js';\r\nimport { prepareWithRestore } from './restore.js';\r\n\r\nconst POOL_PAGE_SIZE = 200;\r\n\r\n/**\r\n * The pool delivery adapter: deposit/scan/withdraw against the Soroban pool\r\n * contract. This is the original, private, multi-token path — the logic here is\r\n * the behavior previously inlined in `StealthClient`, extracted unchanged so the\r\n * client can treat it as one adapter among several.\r\n */\r\nexport class PoolAdapter implements DeliveryAdapter {\r\n readonly method = 'pool' as const;\r\n private readonly relayerSelection?: RelayerSelection;\r\n\r\n constructor(\r\n private readonly contractId: string,\r\n private readonly networkPassphrase: string,\r\n private readonly server: StellarSdk.rpc.Server,\r\n opts?: { relayerSelection?: RelayerSelection },\r\n ) {\r\n this.relayerSelection = opts?.relayerSelection;\r\n }\r\n\r\n /**\r\n * Derive a one-time stealth address and deposit into the pool contract,\r\n * recording the announcement atomically with the deposit.\r\n */\r\n async send(params: AdapterSendParams): Promise<SendReceipt> {\r\n const { metaAddress, amount, senderSecret, asset, signTransaction } = params;\r\n if (amount <= 0) throw new Error('Amount must be positive');\r\n\r\n const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);\r\n const senderPublicKey = signTransaction\r\n ? senderSecret\r\n : Keypair.fromSecret(senderSecret).publicKey();\r\n const tokenAddress = resolveTokenAddress(asset, this.networkPassphrase);\r\n const stroops = numberToStroops(amount);\r\n\r\n const ephemeralPrivKey = new Uint8Array(randomBytes(32));\r\n const stealth = deriveStealthAddressWithSecret(\r\n spendPubKey,\r\n viewPubKey,\r\n ephemeralPrivKey,\r\n );\r\n\r\n const contract = new Contract(this.contractId);\r\n const account = await this.server.getAccount(senderPublicKey);\r\n\r\n const depositTx = new TransactionBuilder(account, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'deposit',\r\n new StellarSdk.Address(senderPublicKey).toScVal(),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(stroops, { type: 'i128' }),\r\n nativeToScVal(Buffer.from(stealth.stealthPubKey)),\r\n nativeToScVal(Buffer.from(stealth.ephemeralPubKey)),\r\n nativeToScVal(stealth.viewTag, { type: 'u32' }),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(depositTx);\r\n const signed = await signTx(\r\n prepared,\r\n senderSecret,\r\n this.networkPassphrase,\r\n signTransaction,\r\n );\r\n const result = await this.server.sendTransaction(signed);\r\n const txHash = await resolveSendResult(this.server, result);\r\n\r\n return {\r\n stealthAddress: stealth.stealthAddress,\r\n txHash,\r\n };\r\n }\r\n\r\n /**\r\n * Scan pool announcements starting at the cursor (announcement index). The\r\n * cursor advances by the number of announcements returned; a cheap\r\n * `get_announcement_count` lets callers skip a full scan when nothing is new.\r\n */\r\n async scan(\r\n keys: StealthKeys,\r\n cursor?: string,\r\n ): Promise<{ payments: Payment[]; cursor?: string }> {\r\n const viewPrivKey = Buffer.from(keys.viewPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(keys.spendPubKey, 'hex');\r\n\r\n const start = cursor ? Number(cursor) : 0;\r\n\r\n const total = await fetchAnnouncementCount(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n if (total <= start) {\r\n return { payments: [], cursor: String(start) };\r\n }\r\n\r\n const announcements: RawAnnouncement[] = [];\r\n let offset = start;\r\n while (offset < total) {\r\n const page = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n offset,\r\n POOL_PAGE_SIZE,\r\n );\r\n if (page.length === 0) break;\r\n announcements.push(...page);\r\n offset += page.length;\r\n }\r\n\r\n const nextCursor = String(start + announcements.length);\r\n const payments = await this.matchAndPrice(\r\n announcements,\r\n viewPrivKey,\r\n spendPubKey,\r\n );\r\n return { payments, cursor: nextCursor };\r\n }\r\n\r\n private async matchAndPrice(\r\n announcements: RawAnnouncement[],\r\n viewPrivKey: Buffer,\r\n spendPubKey: Buffer,\r\n ): Promise<Payment[]> {\r\n if (announcements.length === 0) return [];\r\n\r\n const matches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map((a) => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const payments: Payment[] = [];\r\n for (const match of matches) {\r\n if (!match) continue;\r\n const ann = announcements.find((a) => a.stealthAddress === match.address);\r\n if (!ann) continue;\r\n\r\n const balance = await queryBalance(\r\n this.contractId,\r\n ann.stealthPubKey,\r\n ann.token,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n if (balance <= 0n) continue;\r\n\r\n payments.push({\r\n stealthAddress: ann.stealthAddress,\r\n ephemeralPubKey: Buffer.from(ann.ephemeralPubKey).toString('hex'),\r\n token: ann.token,\r\n asset: labelForToken(ann.token, this.networkPassphrase),\r\n amount: Number(balance) / 1e7,\r\n amountStroops: balance.toString(),\r\n method: 'pool',\r\n });\r\n }\r\n return payments;\r\n }\r\n\r\n /**\r\n * Claim (withdraw) a pool payment: recover the stealth key, sign a withdraw\r\n * message, and submit — directly or via a relayer fee-bump.\r\n */\r\n async claim(\r\n payment: Payment,\r\n destination: string,\r\n opts: ClaimOpts,\r\n ): Promise<ClaimReceipt> {\r\n // A pool claim always needs a fee payer. With an external signer the fee\r\n // payer is identified by its G-address (never a secret) — require it up\r\n // front so the SDK never calls Keypair.fromSecret on a public key.\r\n if (opts.signTransaction && !opts.feePayerAddress) {\r\n throw new FeePayerAddressRequiredError();\r\n }\r\n const receipt = await this.withdraw(payment.stealthAddress, destination, {\r\n keys: opts.keys,\r\n feePayer: opts.feePayer ?? '',\r\n relay: opts.relay,\r\n asset: opts.asset,\r\n amount: opts.amount,\r\n signTransaction: opts.signTransaction,\r\n feePayerAddress: opts.feePayerAddress,\r\n fundingAccount: opts.fundingAccount,\r\n fundingSigner: opts.fundingSigner,\r\n confirm: opts.confirm,\r\n });\r\n return { txHash: receipt.txHash, amount: receipt.amount, method: 'pool' };\r\n }\r\n\r\n /**\r\n * The original pool withdraw path, preserved for the client's `@deprecated`\r\n * `withdraw()` alias and reused by `claim()`.\r\n */\r\n async withdraw(\r\n stealthAddress: string,\r\n destination: string,\r\n opts: {\r\n keys: StealthKeys;\r\n feePayer: string;\r\n /** Relay URL(s); a list is health-probed and routed with failover. */\r\n relay?: string | string[];\r\n asset?: string;\r\n amount?: number;\r\n signTransaction?: TransactionSigner;\r\n feePayerAddress?: string;\r\n /** App funding account to debit against (credit-gated relayers). */\r\n fundingAccount?: string;\r\n /**\r\n * Signer proving control of `fundingAccount` — a credit-gated relayer\r\n * rejects `/relay` without a signed challenge (proof-of-control), so\r\n * `fundingAccount` alone is not enough to spend credit.\r\n */\r\n fundingSigner?: FundingSigner;\r\n /**\r\n * Relayed submissions only: poll the relayer-returned txHash until it is\r\n * actually on-chain before returning (SDK-TXHASH-TRUST), surfacing a\r\n * `TransactionTimeoutError` (with the hash) if it never lands. Default\r\n * `false`: trust the relayer's response, exactly as before. The direct\r\n * (non-relay) path already confirms via `resolveSendResult` regardless.\r\n */\r\n confirm?: boolean;\r\n },\r\n ): Promise<{ txHash: string; amount: number }> {\r\n if (!StrKey.isValidEd25519PublicKey(stealthAddress)) {\r\n throw new Error('Invalid stealth address');\r\n }\r\n if (!StrKey.isValidEd25519PublicKey(destination)) {\r\n throw new Error('Invalid destination address');\r\n }\r\n // With an external signer the fee payer is a G-address, not a secret.\r\n if (opts.signTransaction) {\r\n if (!opts.feePayerAddress) {\r\n throw new FeePayerAddressRequiredError();\r\n }\r\n } else if (!opts.feePayer) {\r\n throw new FeePayerRequiredError();\r\n }\r\n\r\n const viewPrivKey = Buffer.from(opts.keys.viewPrivKey, 'hex');\r\n const spendPrivKey = Buffer.from(opts.keys.spendPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(opts.keys.spendPubKey, 'hex');\r\n const tokenAddress = resolveTokenAddress(opts.asset, this.networkPassphrase);\r\n\r\n const total = await fetchAnnouncementCount(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n const announcements: RawAnnouncement[] = [];\r\n let offset = 0;\r\n while (offset < total) {\r\n const page = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n offset,\r\n POOL_PAGE_SIZE,\r\n );\r\n if (page.length === 0) break;\r\n announcements.push(...page);\r\n offset += page.length;\r\n }\r\n\r\n const allMatches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map((a) => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const matchedAnn = announcements.find((a) => {\r\n if (a.stealthAddress !== stealthAddress) return false;\r\n return allMatches.some((m) => m?.address === stealthAddress);\r\n });\r\n\r\n if (!matchedAnn) {\r\n throw new AnnouncementNotFoundError();\r\n }\r\n\r\n const stealthPrivKey = recoverStealthPrivateKey(\r\n spendPrivKey,\r\n viewPrivKey,\r\n matchedAnn.ephemeralPubKey,\r\n );\r\n\r\n const balance = await queryBalance(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) throw new NoBalanceError();\r\n\r\n let withdrawAmount: bigint;\r\n if (opts.amount !== undefined) {\r\n withdrawAmount = numberToStroops(opts.amount);\r\n if (withdrawAmount > balance) {\r\n throw new Error(\r\n `Requested ${opts.amount} but balance is ${formatStroops(balance)}`,\r\n );\r\n }\r\n } else {\r\n withdrawAmount = balance;\r\n }\r\n\r\n const currentNonce = await queryNonce(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n const nonce = currentNonce + 1n;\r\n\r\n const messageHash = buildWithdrawMessage(\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n withdrawAmount,\r\n destination,\r\n nonce,\r\n this.contractId,\r\n this.networkPassphrase,\r\n );\r\n\r\n const signature = stealthPrivKey.sign(messageHash);\r\n stealthPrivKey.zeroize();\r\n\r\n const feePayerPublicKey = opts.signTransaction\r\n ? opts.feePayerAddress!\r\n : Keypair.fromSecret(opts.feePayer).publicKey();\r\n const contract = new Contract(this.contractId);\r\n const feePayerAccount = await this.server.getAccount(feePayerPublicKey);\r\n\r\n // Build the withdraw invocation from a given source account. Reused so the\r\n // restore branch can rebuild on a fresh sequence after the RestoreFootprint\r\n // consumes the fee payer's next seq (otherwise the withdraw collides →\r\n // txBAD_SEQ). The non-archived path builds it exactly once.\r\n const buildWithdrawTx = (\r\n source: StellarSdk.Account,\r\n ): StellarSdk.Transaction =>\r\n new TransactionBuilder(source, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'withdraw',\r\n nativeToScVal(Buffer.from(matchedAnn.stealthPubKey)),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(withdrawAmount, { type: 'i128' }),\r\n new StellarSdk.Address(destination).toScVal(),\r\n nativeToScVal(nonce, { type: 'u64' }),\r\n nativeToScVal(Buffer.from(signature)),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const withdrawTx = buildWithdrawTx(feePayerAccount);\r\n\r\n // Sign the fee-payer leg of any Soroban tx (withdraw or restore).\r\n const signLeg = (tx: StellarSdk.Transaction): Promise<StellarSdk.Transaction> =>\r\n signTx(\r\n tx,\r\n opts.signTransaction ? feePayerPublicKey : opts.feePayer,\r\n this.networkPassphrase,\r\n opts.signTransaction,\r\n );\r\n\r\n // Submit a signed tx, fee-bumped through the relayer when one is configured,\r\n // otherwise directly to the RPC. Returns the transaction hash.\r\n //\r\n // The relayed path goes through the RelayerPool: a single URL is a\r\n // transparent pass-through (no probe, exactly the old RelayerClient path,\r\n // incl. bare `.../relay` URLs), while a list is health-probed and fails\r\n // over on relayer faults only (A3). `fundingAccount` + the signed-challenge\r\n // auth thread into `/relay` — a bare `{xdr}` POST would make a credit-gated\r\n // relayer reject every pool withdrawal 402. Confirm-polling runs OUTSIDE\r\n // the pool's attempt budget so a slow ledger close is never misread as a\r\n // dead relayer (which could resubmit).\r\n const relayerPool = RelayerPool.from(opts.relay, {\r\n network: networkNameForPassphrase(this.networkPassphrase),\r\n selection: this.relayerSelection,\r\n });\r\n const submit = async (\r\n signed: StellarSdk.Transaction,\r\n ): Promise<string> => {\r\n if (relayerPool) {\r\n const txHash = await relayerPool.withRelayer(\r\n async (client) =>\r\n (\r\n await client.relay(signed.toEnvelope().toXDR('base64'), {\r\n fundingAccount: opts.fundingAccount,\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n ).txHash,\r\n {\r\n fundingAccount: opts.fundingAccount,\r\n fundingSigner: opts.fundingSigner,\r\n rpcServer: this.server,\r\n },\r\n );\r\n if (opts.confirm) await waitForTransaction(this.server, txHash);\r\n return txHash;\r\n }\r\n const result = await this.server.sendTransaction(signed);\r\n return resolveSendResult(this.server, result);\r\n };\r\n\r\n // Restore an archived Balance/Nonce footprint before assembling the withdraw\r\n // (prepareTransaction alone ignores sim.restorePreamble — see restore.ts).\r\n const prepared = await prepareWithRestore(\r\n withdrawTx,\r\n buildWithdrawTx,\r\n this.server,\r\n this.networkPassphrase,\r\n signLeg,\r\n submit,\r\n );\r\n\r\n const signedWithdraw = await signLeg(prepared);\r\n const txHash = await submit(signedWithdraw);\r\n\r\n return { txHash, amount: Number(withdrawAmount) / 1e7 };\r\n }\r\n}\r\n","import {\r\n decodeMetaAddress,\r\n deriveStealthAddressWithSecret,\r\n recoverStealthPrivateKey,\r\n scalarMult,\r\n scalarMultBase,\r\n pointAdd,\r\n hashToScalar,\r\n encodePublicKey,\r\n type StealthScalar,\r\n} from '@shade/crypto';\r\nimport {\r\n Account,\r\n Keypair,\r\n TransactionBuilder,\r\n Transaction,\r\n Operation,\r\n Asset,\r\n Claimant,\r\n Memo,\r\n MuxedAccount,\r\n BASE_FEE,\r\n type OperationRecord,\r\n} from '@stellar/stellar-sdk';\r\nimport { randomBytes } from '@noble/hashes/utils';\r\nimport { HorizonClient } from '../horizon.js';\r\nimport type {\r\n HorizonOp,\r\n HorizonClaimant,\r\n HorizonPredicate,\r\n HorizonClaimableBalance,\r\n} from '../horizon.js';\r\nimport { RelayerClient } from '../relayer.js';\r\nimport type { IndexerClient, IndexerHealth } from '../indexer.js';\r\nimport {\r\n RelayerPool,\r\n normalizeRelayList,\r\n type RelayerSelection,\r\n} from '../relayerPool.js';\r\nimport {\r\n networkNameForPassphrase,\r\n waitForTransaction,\r\n type TransactionStatusSource,\r\n} from '../soroban.js';\r\nimport {\r\n MinimumAmountError,\r\n ClaimAmountError,\r\n ClaimAmountRequiresNoMergeError,\r\n InvalidAmountError,\r\n SponsoredClaimMismatchError,\r\n StealthAccountNotFoundError,\r\n DestinationTrustlineError,\r\n IndexerHttpError,\r\n IndexerNetworkError,\r\n} from '../errors.js';\r\nimport { numberToStroops, parseStroops, formatStroops } from '../stroops.js';\r\nimport type {\r\n StealthKeys,\r\n SendReceipt,\r\n Payment,\r\n ClaimReceipt,\r\n ClaimOpts,\r\n MethodScanMeta,\r\n ScanSegmentMeta,\r\n} from '../types.js';\r\nimport type { DeliveryAdapter, AdapterSendParams } from './types.js';\r\nimport { signTx } from './sign.js';\r\n\r\nconst HORIZON_PAGE_SIZE = 200;\r\n\r\n/** Indexer announcements page size (the service caps `limit` at 200). */\r\nconst INDEXER_PAGE_SIZE = 200;\r\n\r\n/**\r\n * Default cap (seconds) on the indexer's self-reported lag before the health\r\n * guard skips it: 6 hours. Deliberately lenient — the Horizon tail already\r\n * bounds correctness (a lagging indexer can never hide a payment), and\r\n * skipping a merely-slow indexer would force cold scans back toward the\r\n * full-history walk — so the cap only disqualifies operationally abandoned\r\n * indexers. `Number.POSITIVE_INFINITY` disables the cap.\r\n */\r\nconst DEFAULT_INDEXER_MAX_LAG_SECONDS = 21_600;\r\n\r\n/** Decoded key material + flags threaded through one scan invocation. */\r\ninterface ScanContext {\r\n viewPrivKey: Uint8Array;\r\n spendPubKey: Uint8Array;\r\n suppressClaimedNative: boolean;\r\n}\r\n\r\n/**\r\n * Mutable candidate/match counters for one scan segment, threaded through the\r\n * walks so {@link MethodScanMeta} can report per-segment diagnostics without\r\n * touching any walk/cursor semantics.\r\n */\r\ntype SegmentStats = Pick<ScanSegmentMeta, 'candidates' | 'matches'>;\r\n\r\n/**\r\n * The transaction fields the candidate matcher consumes — satisfied verbatim\r\n * by a Horizon transaction record AND by an indexer announcement (which MAY\r\n * carry `source_account` on newer feeds, in which case the token path binds\r\n * its claimable balance sponsor-precisely exactly like the Horizon walk;\r\n * older feeds omit it and fall back to the asset+amount binding).\r\n */\r\ninterface CandidateTx {\r\n hash: string;\r\n paging_token: string;\r\n memo_type: string;\r\n memo?: string;\r\n successful?: boolean;\r\n source_account?: string;\r\n}\r\n\r\n/**\r\n * Reserves the sender fronts on a token send: 1 XLM to open the stealth account\r\n * plus 0.5 XLM trustline headroom plus a little fee slack. The 0.5 XLM\r\n * claimable-balance reserve returns to the sender when the balance is claimed.\r\n */\r\nconst TOKEN_ACCOUNT_STARTING_BALANCE = '1.5001';\r\n\r\n/**\r\n * The minimum native balance (in stroops) a live stealth account must retain on\r\n * a partial claim: 2x the base reserve = 1.0 XLM.\r\n */\r\nconst ACCOUNT_RESERVE_STROOPS = 10_000_000n;\r\n\r\n/**\r\n * Fallback mirror of the relayer's `SPONSORED_RESERVE_ESTIMATE` ('1.0000000'\r\n * XLM): the reserve component a credit-gated relayer adds to the prepared tx's\r\n * fee when verifying the sponsor-claim proof-of-control signature. Unlike\r\n * `/relay` (which authorizes a fee CEILING), sponsor-claim verifies the EXACT\r\n * total `tx.fee + this` — any other signed amount is rejected 401. The relayer\r\n * advertises the live value via `/health` `sponsoredReserveEstimate`, which\r\n * the sponsored-claim path prefers; this constant applies only when the field\r\n * is absent, unparsable, or /health is unreachable.\r\n */\r\nconst SPONSORED_RESERVE_ESTIMATE_STROOPS = 10_000_000n;\r\n\r\nfunction isNativeAsset(asset?: string): boolean {\r\n return !asset || asset === 'native' || asset === 'XLM';\r\n}\r\n\r\n/** Parse a \"CODE:ISSUER\" asset string into a Stellar Asset. */\r\nfunction parseAsset(asset: string): Asset {\r\n if (isNativeAsset(asset)) return Asset.native();\r\n const [code, issuer] = asset.split(':');\r\n if (!code || !issuer) {\r\n throw new Error(`Invalid asset \"${asset}\" — expected CODE:ISSUER`);\r\n }\r\n return new Asset(code, issuer);\r\n}\r\n\r\n/** Render an Asset back to Horizon's \"CODE:ISSUER\" (or 'native') string form. */\r\nfunction assetToString(asset: Asset): string {\r\n return asset.isNative() ? 'native' : `${asset.getCode()}:${asset.getIssuer()}`;\r\n}\r\n\r\n/**\r\n * Normalize a destination to its underlying ed25519 account id. A muxed address\r\n * (`M...`) shares one underlying G-account across many virtual sub-accounts; a\r\n * send addressed to the muxed form of a stealth address must still match the\r\n * derived G-address. Non-muxed inputs (and unparseable ones) pass through\r\n * unchanged so a plain `G...` comparison is unaffected.\r\n */\r\nfunction normalizeDestination(address: string | undefined): string | undefined {\r\n if (!address) return address;\r\n if (!address.startsWith('M')) return address;\r\n try {\r\n return MuxedAccount.fromAddress(address, '0').baseAccount().accountId();\r\n } catch {\r\n return address;\r\n }\r\n}\r\n\r\n/**\r\n * Evaluate a Horizon claim predicate for a given claimant against the current\r\n * ledger time (seconds since epoch). Returns true when the claimant may claim\r\n * NOW. A missing predicate is treated as unconditional. `rel_before` cannot be\r\n * evaluated without the CB creation time, so it is treated conservatively as\r\n * currently satisfiable (never spuriously suppressing income).\r\n */\r\nfunction isPredicateSatisfiable(\r\n predicate: HorizonPredicate | undefined,\r\n nowSeconds: number,\r\n): boolean {\r\n if (!predicate) return true;\r\n if (predicate.unconditional) return true;\r\n if (predicate.not) {\r\n return !isPredicateSatisfiable(predicate.not, nowSeconds);\r\n }\r\n if (predicate.and) {\r\n return predicate.and.every((p) => isPredicateSatisfiable(p, nowSeconds));\r\n }\r\n if (predicate.or) {\r\n return predicate.or.some((p) => isPredicateSatisfiable(p, nowSeconds));\r\n }\r\n if (predicate.abs_before_epoch !== undefined) {\r\n return nowSeconds < Number(predicate.abs_before_epoch);\r\n }\r\n if (predicate.abs_before !== undefined) {\r\n const before = Math.floor(Date.parse(predicate.abs_before) / 1000);\r\n if (!Number.isNaN(before)) return nowSeconds < before;\r\n }\r\n // rel_before (or an unrecognized shape): cannot disprove satisfiability here,\r\n // so treat as claimable rather than dropping a genuine payment.\r\n return true;\r\n}\r\n\r\n/**\r\n * Recompute the receiver-side stealth address from the ephemeral key R.\r\n *\r\n * `S = k_view * R`, `s = SHA256(S) mod L`, `P = K_spend + s*G`. Encoding P as a\r\n * StrKey G-address gives the exact stealth address the sender created — matching\r\n * it against the transaction's destination IS the full DKSAP verification, so no\r\n * separate view tag is required for the account method.\r\n */\r\nexport function computeReceiverStealthAddress(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n): string {\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n const s = hashToScalar(S);\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n return encodePublicKey(P);\r\n}\r\n\r\n/**\r\n * The account delivery adapter: a direct classic Stellar payment that\r\n * creates/pays a one-time stealth account, with the ephemeral key R carried in\r\n * a 32-byte MemoHash. No view tag is needed — the destination match against the\r\n * DKSAP-derived address IS the full verification.\r\n *\r\n * Native XLM lands via CreateAccount/Payment; tokens land as a\r\n * CreateClaimableBalance the recipient later claims (adding a trustline first).\r\n */\r\nexport class AccountAdapter implements DeliveryAdapter {\r\n readonly method = 'account' as const;\r\n private readonly rpcServer?: TransactionStatusSource;\r\n private readonly relayerSelection?: RelayerSelection;\r\n private readonly indexer?: IndexerClient;\r\n private readonly indexerMaxLagSeconds: number;\r\n\r\n constructor(\r\n private readonly networkPassphrase: string,\r\n private readonly horizon: HorizonClient,\r\n private readonly relayer?: string | string[],\r\n opts?: {\r\n rpcServer?: TransactionStatusSource;\r\n relayerSelection?: RelayerSelection;\r\n /** Optional discovery accelerator consumed by {@link scan}. */\r\n indexer?: IndexerClient;\r\n /**\r\n * Cap on the indexer's self-reported lag before the health guard skips\r\n * it (default {@link DEFAULT_INDEXER_MAX_LAG_SECONDS}; see the rationale\r\n * there). `Number.POSITIVE_INFINITY` disables the cap.\r\n */\r\n indexerMaxLagSeconds?: number;\r\n },\r\n ) {\r\n this.rpcServer = opts?.rpcServer;\r\n this.relayerSelection = opts?.relayerSelection;\r\n this.indexer = opts?.indexer;\r\n this.indexerMaxLagSeconds =\r\n opts?.indexerMaxLagSeconds ?? DEFAULT_INDEXER_MAX_LAG_SECONDS;\r\n }\r\n\r\n /**\r\n * Send funds directly to a one-time stealth account. Native XLM uses a plain\r\n * CreateAccount/Payment; a non-native asset uses CreateAccount (to open the\r\n * stealth account) plus a CreateClaimableBalance carrying the token. Amount\r\n * MUST be strictly greater than 1 XLM for native sends.\r\n */\r\n async send(params: AdapterSendParams): Promise<SendReceipt> {\r\n const { asset } = params;\r\n if (!isNativeAsset(asset)) {\r\n return this.sendToken(params);\r\n }\r\n return this.sendNative(params);\r\n }\r\n\r\n /** Native XLM send: CreateAccount (falls back to Payment on retry). */\r\n private async sendNative(params: AdapterSendParams): Promise<SendReceipt> {\r\n const { metaAddress, amount, senderSecret, signTransaction } = params;\r\n if (amount <= 1) {\r\n throw new MinimumAmountError(amount);\r\n }\r\n\r\n const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);\r\n const ephemeralPrivKey = new Uint8Array(randomBytes(32));\r\n const stealth = deriveStealthAddressWithSecret(\r\n spendPubKey,\r\n viewPubKey,\r\n ephemeralPrivKey,\r\n );\r\n\r\n const memo = Memo.hash(Buffer.from(stealth.ephemeralPubKey));\r\n const startingBalance = formatStroops(numberToStroops(amount));\r\n const senderPublicKey = signTransaction\r\n ? senderSecret\r\n : Keypair.fromSecret(senderSecret).publicKey();\r\n\r\n const submit = async (useCreate: boolean): Promise<string> => {\r\n const account = await this.horizon.getAccount(senderPublicKey);\r\n if (!account) {\r\n throw new Error('Sender account not found on Horizon — is it funded?');\r\n }\r\n const source = new Account(account.id, account.sequence);\r\n\r\n const op = useCreate\r\n ? Operation.createAccount({\r\n destination: stealth.stealthAddress,\r\n startingBalance,\r\n })\r\n : Operation.payment({\r\n destination: stealth.stealthAddress,\r\n asset: Asset.native(),\r\n amount: startingBalance,\r\n });\r\n\r\n const tx = new TransactionBuilder(source, {\r\n fee: BASE_FEE,\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(op)\r\n .addMemo(memo)\r\n .setTimeout(30)\r\n .build();\r\n\r\n const signed = await signTx(\r\n tx,\r\n senderSecret,\r\n this.networkPassphrase,\r\n signTransaction,\r\n );\r\n const res = await this.horizon.submitTransaction(\r\n signed.toEnvelope().toXDR('base64'),\r\n );\r\n return res.hash;\r\n };\r\n\r\n let txHash: string;\r\n try {\r\n txHash = await submit(true);\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n if (msg.includes('op_already_exists')) {\r\n txHash = await submit(false);\r\n } else {\r\n throw err;\r\n }\r\n }\r\n\r\n return { stealthAddress: stealth.stealthAddress, txHash };\r\n }\r\n\r\n /**\r\n * Token send: one classic tx carrying two operations —\r\n * CreateAccount(stealth, 1.5001 XLM) to open the account with trustline\r\n * headroom, then CreateClaimableBalance(asset, amount, claimant: stealth,\r\n * unconditional). The 0.5 XLM claimable-balance reserve returns to the sender\r\n * when the recipient claims. The ephemeral R rides in the MemoHash exactly as\r\n * for native sends.\r\n *\r\n * Not idempotent on retry: unlike {@link sendNative} (which falls back to a\r\n * Payment on `op_already_exists`), a token send has no such fallback. Each\r\n * token send uses a fresh ephemeral — hence a fresh, never-before-created\r\n * stealth address — so a resubmit targets a new account rather than colliding,\r\n * making the retry path unnecessary here.\r\n */\r\n private async sendToken(params: AdapterSendParams): Promise<SendReceipt> {\r\n const { metaAddress, amount, senderSecret, asset } = params;\r\n if (!Number.isFinite(amount) || amount <= 0) {\r\n throw new InvalidAmountError(amount);\r\n }\r\n const stellarAsset = parseAsset(asset!);\r\n\r\n const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);\r\n const ephemeralPrivKey = new Uint8Array(randomBytes(32));\r\n const stealth = deriveStealthAddressWithSecret(\r\n spendPubKey,\r\n viewPubKey,\r\n ephemeralPrivKey,\r\n );\r\n\r\n const memo = Memo.hash(Buffer.from(stealth.ephemeralPubKey));\r\n const senderPublicKey = params.signTransaction\r\n ? senderSecret\r\n : Keypair.fromSecret(senderSecret).publicKey();\r\n const account = await this.horizon.getAccount(senderPublicKey);\r\n if (!account) {\r\n throw new Error('Sender account not found on Horizon — is it funded?');\r\n }\r\n const source = new Account(account.id, account.sequence);\r\n\r\n const claimant = new Claimant(\r\n stealth.stealthAddress,\r\n Claimant.predicateUnconditional(),\r\n );\r\n\r\n const tx = new TransactionBuilder(source, {\r\n fee: BASE_FEE,\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n Operation.createAccount({\r\n destination: stealth.stealthAddress,\r\n startingBalance: TOKEN_ACCOUNT_STARTING_BALANCE,\r\n }),\r\n )\r\n .addOperation(\r\n Operation.createClaimableBalance({\r\n asset: stellarAsset,\r\n amount: formatStroops(numberToStroops(amount)),\r\n claimants: [claimant],\r\n }),\r\n )\r\n .addMemo(memo)\r\n .setTimeout(30)\r\n .build();\r\n\r\n const signed = await signTx(\r\n tx,\r\n senderSecret,\r\n this.networkPassphrase,\r\n params.signTransaction,\r\n );\r\n const res = await this.horizon.submitTransaction(\r\n signed.toEnvelope().toXDR('base64'),\r\n );\r\n\r\n return { stealthAddress: stealth.stealthAddress, txHash: res.hash };\r\n }\r\n\r\n /**\r\n * Discover incoming direct payments over Horizon's ascending transaction\r\n * feed. For each tx with a hash memo, the memo decodes to a candidate R;\r\n * deriving the stealth address from (viewPrivKey, spendPubKey, R) and\r\n * finding an operation whose destination equals that address confirms the\r\n * payment is ours. Three op shapes are matched:\r\n * - `create_account` / `payment` -> a native XLM send.\r\n * - `create_claimable_balance` with our address as a claimant -> a token send;\r\n * the claimable balance id is resolved via Horizon's claimable-balances API.\r\n *\r\n * With an indexer configured (and passing the health guard) the walk is\r\n * segmented: a bounded Horizon pre-segment covers anything before the\r\n * indexer's coverage window, the covered span consumes pre-extracted\r\n * announcements with inlined operations (no per-tx round-trip), and a\r\n * Horizon tail ALWAYS runs from the last adopted position so indexer lag —\r\n * or an indexer fault mid-segment — can never hide a payment. A cold scan\r\n * fast-starts at the indexer's first covered position; payments predating\r\n * that coverage need `exhaustive: true`. Without an indexer the behavior is\r\n * exactly the original unbounded Horizon walk.\r\n *\r\n * Every path also returns `meta` — per-segment candidate/match counts plus\r\n * the indexer guard's verdict. Strictly observability: the numbers describe\r\n * how the scan ran, never which payments it finds.\r\n */\r\n async scan(\r\n keys: StealthKeys,\r\n cursor?: string,\r\n opts?: { suppressClaimedNative?: boolean; exhaustive?: boolean },\r\n ): Promise<{ payments: Payment[]; cursor?: string; meta: MethodScanMeta }> {\r\n const ctx: ScanContext = {\r\n viewPrivKey: new Uint8Array(Buffer.from(keys.viewPrivKey, 'hex')),\r\n spendPubKey: new Uint8Array(Buffer.from(keys.spendPubKey, 'hex')),\r\n suppressClaimedNative: opts?.suppressClaimedNative ?? false,\r\n };\r\n const payments: Payment[] = [];\r\n const meta: MethodScanMeta = { indexerUsed: false, segments: [] };\r\n\r\n const indexer = this.indexer;\r\n const coverage = indexer ? await this.indexerCoverage(indexer) : undefined;\r\n if (!indexer || !coverage || !coverage.usable) {\r\n // No indexer (or one that failed the health guard): the plain unbounded\r\n // Horizon walk, byte-identical to the pre-indexer scan.\r\n if (coverage && !coverage.usable) {\r\n meta.indexerSkipReason = coverage.reason;\r\n if (coverage.lagSeconds !== undefined) {\r\n meta.indexerLagSeconds = coverage.lagSeconds;\r\n }\r\n }\r\n const stats: SegmentStats = { candidates: 0, matches: 0 };\r\n const finalCursor = await this.walkHorizon(\r\n cursor,\r\n undefined,\r\n ctx,\r\n payments,\r\n stats,\r\n );\r\n meta.segments.push({ source: 'horizon', role: 'full', ...stats });\r\n return { payments, cursor: finalCursor, meta };\r\n }\r\n meta.indexerLagSeconds = coverage.lagSeconds;\r\n\r\n // Fast cold start: with no client cursor the scan begins at the indexer's\r\n // first covered position rather than genesis. Documented tradeoff:\r\n // payments predating indexer coverage need `exhaustive: true`.\r\n const begin =\r\n cursor ?? (opts?.exhaustive ? undefined : coverage.startCursor);\r\n\r\n // Pre-segment: a bounded Horizon walk over the span the indexer does NOT\r\n // cover, INCLUSIVE of the startCursor tx — coverage is the open interval\r\n // (startCursor, cursor], so the boundary tx comes from Horizon and only\r\n // from Horizon (/announcements serves strictly-greater tokens: no dup).\r\n if (begin === undefined || BigInt(begin) < BigInt(coverage.startCursor)) {\r\n const preStats: SegmentStats = { candidates: 0, matches: 0 };\r\n await this.walkHorizon(begin, coverage.startCursor, ctx, payments, preStats);\r\n meta.segments.push({ source: 'horizon', role: 'pre', ...preStats });\r\n }\r\n\r\n // Indexer segment: consume pre-extracted announcements from wherever the\r\n // covered span begins for this scan.\r\n let cur =\r\n begin !== undefined && BigInt(begin) > BigInt(coverage.startCursor)\r\n ? begin\r\n : coverage.startCursor;\r\n // Snapshots for the post-segment health re-check below: where the segment\r\n // started, and how many payments existed before it ran.\r\n const segmentStart = cur;\r\n const preSegmentPayments = payments.length;\r\n const indexerStats: SegmentStats = { candidates: 0, matches: 0 };\r\n try {\r\n for (;;) {\r\n const page = await indexer.getAnnouncements(cur, INDEXER_PAGE_SIZE);\r\n meta.indexerUsed = true;\r\n for (const record of page.records) {\r\n await this.collectCandidate(\r\n record,\r\n record.operations,\r\n ctx,\r\n payments,\r\n indexerStats,\r\n );\r\n }\r\n // Advance only AFTER the page's records are processed, so an\r\n // abandoned segment can never sit past unprocessed records. Adopt the\r\n // furthest well-formed position the page yields — its reported cursor\r\n // over the last processed record's token — so a malformed or stalled\r\n // feed cannot poison the Horizon tail cursor (defensive; a\r\n // contract-compliant cursor always advances past both).\r\n const prev = cur;\r\n const adopt = (candidate: unknown): void => {\r\n if (\r\n typeof candidate === 'string' &&\r\n /^\\d+$/.test(candidate) &&\r\n BigInt(candidate) > BigInt(cur)\r\n ) {\r\n cur = candidate;\r\n }\r\n };\r\n adopt(page.records[page.records.length - 1]?.paging_token);\r\n adopt(page.cursor);\r\n if (page.records.length < INDEXER_PAGE_SIZE) break;\r\n // (defensive) A full page that fails to advance would replay the same\r\n // records forever — abandon to the Horizon tail instead.\r\n if (cur === prev) break;\r\n }\r\n } catch (err) {\r\n // Indexer fault mid-segment: abandon it (cur = last adopted position)\r\n // and let the Horizon tail below cover the rest. Anything else (e.g. a\r\n // Horizon error inside the candidate matcher) propagates as before.\r\n if (\r\n !(err instanceof IndexerHttpError) &&\r\n !(err instanceof IndexerNetworkError)\r\n ) {\r\n throw err;\r\n }\r\n }\r\n // Pushed on the fault path too: whatever the abandoned segment processed\r\n // before the fault is real work worth reporting.\r\n meta.segments.push({ source: 'indexer', role: 'indexer', ...indexerStats });\r\n\r\n // Post-segment health re-check. The guard passed BEFORE the segment was\r\n // consumed, but /announcements pages have no gap awareness: a hole the\r\n // ingester recorded WHILE this scan was paging means served pages may\r\n // have silently skipped it. Only a still-'ok' answer lets the scan keep\r\n // the segment's payments and adopted positions; on anything else\r\n // (degraded, unreachable — including a mid-segment fault with a dead\r\n // indexer) both are discarded and the tail re-walks from where the\r\n // segment started, so a mid-scan hole can never advance the client\r\n // cursor past a payment. (The discarded payments are re-discovered by\r\n // that same tail — Horizon is the source of truth.)\r\n let tailFrom = cur;\r\n try {\r\n const post = await indexer.health();\r\n meta.postCheck = post.status === 'ok' ? 'ok' : 'unhealthy';\r\n } catch {\r\n meta.postCheck = 'unreachable';\r\n }\r\n if (meta.postCheck !== 'ok') {\r\n tailFrom = segmentStart;\r\n payments.length = preSegmentPayments;\r\n }\r\n\r\n // Horizon tail: ALWAYS runs — it covers indexer lag (and an abandoned\r\n // segment); when the indexer is at head it costs one short page.\r\n const tailStats: SegmentStats = { candidates: 0, matches: 0 };\r\n let finalCursor = await this.walkHorizon(\r\n tailFrom,\r\n undefined,\r\n ctx,\r\n payments,\r\n tailStats,\r\n );\r\n meta.segments.push({ source: 'horizon', role: 'tail', ...tailStats });\r\n\r\n // Clamp indexer-derived cursors to the chain head. When the tail saw\r\n // nothing, `finalCursor` is whatever position was adopted from\r\n // indexer-supplied data (its page cursors, or /health's startCursor on a\r\n // cold start). Persisting a far-future token would blind every future\r\n // scan — each would resume beyond the head and find nothing, forever, and\r\n // nothing would prompt a --full-rescan. So on the empty-tail path the\r\n // position is verified against the head Horizon itself reports and never\r\n // persisted past it. One extra request, only on that path.\r\n if (finalCursor !== undefined && finalCursor === tailFrom) {\r\n const head = await this.horizon.getLatestTransactionToken();\r\n if (head !== undefined && BigInt(head) < BigInt(finalCursor)) {\r\n meta.cursorClamped = true;\r\n finalCursor = head;\r\n }\r\n }\r\n return { payments, cursor: finalCursor, meta };\r\n }\r\n\r\n /**\r\n * Probe the configured indexer and classify whether it is usable for THIS\r\n * scan: `status === 'ok'`, same network as this adapter, a non-null\r\n * coverage interval, and self-reported lag within the configured cap. On\r\n * any guard failure the scan stays on the pure Horizon walk (Horizon is the\r\n * source of truth); the returned reason feeds {@link MethodScanMeta} so the\r\n * otherwise-silent fallback is observable. A null/absent `lagSeconds` is\r\n * NOT stale — lag cannot be measured then, and correctness is tail-bounded\r\n * anyway.\r\n */\r\n private async indexerCoverage(\r\n indexer: IndexerClient,\r\n ): Promise<\r\n | { usable: true; startCursor: string; lagSeconds: number | null }\r\n | {\r\n usable: false;\r\n reason: NonNullable<MethodScanMeta['indexerSkipReason']>;\r\n lagSeconds?: number | null;\r\n }\r\n > {\r\n let h: IndexerHealth;\r\n try {\r\n h = await indexer.health();\r\n } catch {\r\n return { usable: false, reason: 'unreachable' };\r\n }\r\n if (h.status !== 'ok') return { usable: false, reason: 'unhealthy' };\r\n if (h.network !== networkNameForPassphrase(this.networkPassphrase)) {\r\n return { usable: false, reason: 'network_mismatch' };\r\n }\r\n if (h.cursor == null || h.startCursor == null) {\r\n return { usable: false, reason: 'no_coverage' };\r\n }\r\n const lagSeconds = typeof h.lagSeconds === 'number' ? h.lagSeconds : null;\r\n if (lagSeconds !== null && lagSeconds > this.indexerMaxLagSeconds) {\r\n return { usable: false, reason: 'stale', lagSeconds };\r\n }\r\n return { usable: true, startCursor: h.startCursor, lagSeconds };\r\n }\r\n\r\n /**\r\n * Ascending Horizon transaction walk shared by every scan segment,\r\n * processing candidates from `from` (exclusive, Horizon cursor semantics).\r\n * Unbounded when `stopAtToken` is undefined. When bounded, txs with\r\n * `BigInt(paging_token) <= BigInt(stopAtToken)` are processed — INCLUSIVE\r\n * of the boundary tx, matching the indexer's open coverage interval\r\n * (startCursor, cursor] — and the walk returns `stopAtToken` at the first\r\n * tx beyond it. Otherwise returns the last seen paging token (the scan\r\n * cursor), or `from` when nothing new was seen. `stats` accumulates the\r\n * segment's candidate/match counts (observability only).\r\n */\r\n private async walkHorizon(\r\n from: string | undefined,\r\n stopAtToken: string | undefined,\r\n ctx: ScanContext,\r\n payments: Payment[],\r\n stats: SegmentStats,\r\n ): Promise<string | undefined> {\r\n let pageCursor = from;\r\n let lastToken = from;\r\n\r\n for (;;) {\r\n const txs = await this.horizon.getTransactions(pageCursor, HORIZON_PAGE_SIZE);\r\n if (txs.length === 0) break;\r\n\r\n for (const tx of txs) {\r\n if (\r\n stopAtToken !== undefined &&\r\n BigInt(tx.paging_token) > BigInt(stopAtToken)\r\n ) {\r\n return stopAtToken;\r\n }\r\n lastToken = tx.paging_token;\r\n await this.collectCandidate(\r\n tx,\r\n () => this.horizon.getTransactionOperations(tx.hash),\r\n ctx,\r\n payments,\r\n stats,\r\n );\r\n }\r\n\r\n if (txs.length < HORIZON_PAGE_SIZE) break;\r\n pageCursor = txs[txs.length - 1]!.paging_token;\r\n }\r\n\r\n return lastToken;\r\n }\r\n\r\n /**\r\n * Run one transaction through the candidate pipeline: verify the memo\r\n * shape, decode the ephemeral R, derive the receiver-side stealth address,\r\n * and — on an ownership match — collect the native and/or token payment\r\n * rows into `payments`.\r\n *\r\n * `ops` is either the inline operation records (indexer announcements carry\r\n * them verbatim — no per-tx round-trip) or a lazy fetch invoked only after\r\n * the candidate checks pass (the Horizon walk — preserving the pre-indexer\r\n * behavior of never fetching operations for non-candidate txs). The memo\r\n * checks run here even for indexer-served records, so a corrupt feed entry\r\n * degrades to \"not a candidate\" rather than a bogus derivation.\r\n *\r\n * `stats.candidates` counts every tx that passes the memo-shape checks —\r\n * BEFORE derivation, so Horizon- and indexer-served sources count\r\n * identically — and `stats.matches` counts every payment pushed.\r\n */\r\n private async collectCandidate(\r\n tx: CandidateTx,\r\n ops: HorizonOp[] | (() => Promise<HorizonOp[]>),\r\n ctx: ScanContext,\r\n payments: Payment[],\r\n stats: SegmentStats,\r\n ): Promise<void> {\r\n if (tx.memo_type !== 'hash' || !tx.memo) return;\r\n if (tx.successful === false) return;\r\n\r\n const ephemeralPubKey = new Uint8Array(Buffer.from(tx.memo, 'base64'));\r\n if (ephemeralPubKey.length !== 32) return;\r\n stats.candidates++;\r\n\r\n let derivedAddress: string;\r\n try {\r\n derivedAddress = computeReceiverStealthAddress(\r\n ctx.viewPrivKey,\r\n ctx.spendPubKey,\r\n ephemeralPubKey,\r\n );\r\n } catch {\r\n return;\r\n }\r\n\r\n const resolvedOps = typeof ops === 'function' ? await ops() : ops;\r\n const ephHex = Buffer.from(ephemeralPubKey).toString('hex');\r\n\r\n // A create_claimable_balance in THIS tx naming the derived address as a\r\n // claimant. Destinations are muxed-normalized so a send to the M-form of\r\n // the stealth address still matches.\r\n const cbMatch = resolvedOps.find(\r\n (op) =>\r\n op.type === 'create_claimable_balance' &&\r\n (op.claimants ?? []).some(\r\n (c) => normalizeDestination(c.destination) === derivedAddress,\r\n ),\r\n );\r\n\r\n // Native leg (create_account / payment) landing at the derived address.\r\n const nativeMatch = resolvedOps.find(\r\n (op) =>\r\n (op.type === 'create_account' &&\r\n normalizeDestination(op.account) === derivedAddress) ||\r\n (op.type === 'payment' &&\r\n normalizeDestination(op.to) === derivedAddress),\r\n );\r\n\r\n if (nativeMatch) {\r\n const payment = await this.buildNativePayment(\r\n nativeMatch,\r\n derivedAddress,\r\n ephHex,\r\n tx.hash,\r\n !!cbMatch,\r\n ctx.suppressClaimedNative,\r\n );\r\n if (payment) {\r\n payments.push(payment);\r\n stats.matches++;\r\n }\r\n }\r\n\r\n if (cbMatch) {\r\n const payment = await this.buildTokenPayment(\r\n cbMatch,\r\n derivedAddress,\r\n ephHex,\r\n tx.hash,\r\n tx.source_account,\r\n );\r\n if (payment) {\r\n payments.push(payment);\r\n stats.matches++;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Build the native income row for a matched create_account/payment leg, or\r\n * `null` to suppress it.\r\n *\r\n * Suppression is gated on whether the SAME tx also delivered a matching token\r\n * claimable balance (`hasTokenLeg`): the token path fronts a fixed reserve via\r\n * a create_account stub, which must NOT surface as a native payment — but this\r\n * is decided by the presence of the token leg, NOT by any magic starting\r\n * balance, so a genuine native send that merely happens to equal the reserve\r\n * constant is still discovered.\r\n *\r\n * On the balance path (`suppressClaimed`) the row reports the account's LIVE\r\n * native balance (what remains after any partial claim), and a fully-swept\r\n * (0) account is dropped. The discovery path reports the per-tx op amount so\r\n * two sends to the same address each surface independently.\r\n */\r\n private async buildNativePayment(\r\n nativeMatch: HorizonOp,\r\n derivedAddress: string,\r\n ephHex: string,\r\n txHash: string,\r\n hasTokenLeg: boolean,\r\n suppressClaimed: boolean,\r\n ): Promise<Payment | null> {\r\n if (hasTokenLeg) return null;\r\n\r\n const opAmountStr =\r\n nativeMatch.type === 'create_account'\r\n ? (nativeMatch.starting_balance ?? '0')\r\n : (nativeMatch.amount ?? '0');\r\n let stroops = parseStroops(opAmountStr);\r\n\r\n if (suppressClaimed) {\r\n // Report what REMAINS live (post partial-claim), dropping a swept account.\r\n const live = await this.horizon.getAccount(derivedAddress);\r\n if (live) {\r\n const nativeBal = live.balances.find((b) => b.asset_type === 'native');\r\n if (nativeBal !== undefined) stroops = parseStroops(nativeBal.balance);\r\n }\r\n }\r\n\r\n if (stroops <= 0n) return null;\r\n return {\r\n stealthAddress: derivedAddress,\r\n ephemeralPubKey: ephHex,\r\n token: 'native',\r\n amount: Number(formatStroops(stroops)),\r\n amountStroops: stroops.toString(),\r\n method: 'account',\r\n txHash,\r\n };\r\n }\r\n\r\n /**\r\n * Build the token income row for a matched create_claimable_balance leg, or\r\n * `null` when no genuine, currently-claimable CB binds to it.\r\n *\r\n * The candidate CBs (Horizon lists ALL CBs the derived address can claim) are\r\n * bound to THIS specific op — not resolved by first-claimant — so an attacker\r\n * who creates their own CreateClaimableBalance naming the public stealth\r\n * address cannot mask/misattribute the real payment. Binding matches the CB\r\n * whose sponsor is the tx source AND whose asset+amount equal this op's, and\r\n * whose claim predicate for the derived address is currently satisfiable.\r\n */\r\n private async buildTokenPayment(\r\n cbMatch: HorizonOp,\r\n derivedAddress: string,\r\n ephHex: string,\r\n txHash: string,\r\n txSource?: string,\r\n ): Promise<Payment | null> {\r\n const opAsset = cbMatch.asset;\r\n const opAmountStroops = cbMatch.amount\r\n ? parseStroops(cbMatch.amount)\r\n : undefined;\r\n\r\n const candidates = await this.horizon.getClaimableBalances(derivedAddress);\r\n const cb = this.bindClaimableBalance(candidates, derivedAddress, {\r\n txSource,\r\n opAsset,\r\n opAmountStroops,\r\n });\r\n if (!cb) return null;\r\n\r\n const stroops = parseStroops(cb.amount);\r\n return {\r\n stealthAddress: derivedAddress,\r\n ephemeralPubKey: ephHex,\r\n token: opAsset ?? cb.asset ?? 'unknown',\r\n asset: opAsset ?? cb.asset,\r\n claimableBalanceId: cb.id,\r\n amount: Number(formatStroops(stroops)),\r\n amountStroops: stroops.toString(),\r\n method: 'account',\r\n txHash,\r\n };\r\n }\r\n\r\n /**\r\n * Select the live claimable balance that genuinely corresponds to this tx's\r\n * create_claimable_balance op. Filters candidates to those whose claimant is\r\n * the derived address with a currently-satisfiable predicate, then binds by\r\n * sponsor === tx source AND asset === op asset AND amount === op amount. Only\r\n * when that precise binding is ambiguous or the tx source is unknown does it\r\n * fall back to an asset+amount match — never a bare first-claimant pick, so an\r\n * attacker CB cannot shadow the real one.\r\n */\r\n private bindClaimableBalance(\r\n candidates: HorizonClaimableBalance[],\r\n derivedAddress: string,\r\n expected: {\r\n txSource?: string;\r\n opAsset?: string;\r\n opAmountStroops?: bigint;\r\n },\r\n ): HorizonClaimableBalance | undefined {\r\n const nowSeconds = Math.floor(Date.now() / 1000);\r\n\r\n const claimableNow = candidates.filter((cb) =>\r\n (cb.claimants ?? []).some((c: HorizonClaimant) => {\r\n if (normalizeDestination(c.destination) !== derivedAddress) return false;\r\n return isPredicateSatisfiable(c.predicate, nowSeconds);\r\n }),\r\n );\r\n\r\n const assetAmountMatches = claimableNow.filter((cb) => {\r\n const assetOk =\r\n expected.opAsset === undefined || cb.asset === expected.opAsset;\r\n const amountOk =\r\n expected.opAmountStroops === undefined ||\r\n parseStroops(cb.amount) === expected.opAmountStroops;\r\n return assetOk && amountOk;\r\n });\r\n\r\n if (expected.txSource !== undefined) {\r\n const sponsorBound = assetAmountMatches.find(\r\n (cb) => cb.sponsor === expected.txSource,\r\n );\r\n if (sponsorBound) return sponsorBound;\r\n }\r\n\r\n // No sponsor-precise bind (unknown tx source, or Horizon omitted sponsor):\r\n // fall back to the asset+amount-matched candidate rather than first-claimant.\r\n return assetAmountMatches[0];\r\n }\r\n\r\n /**\r\n * Claim a direct-account payment. Branches on the payment shape: a claimable\r\n * balance (token send) runs the trustline + claim recipe; a plain XLM send\r\n * sweeps or partially pays out the stealth account.\r\n */\r\n async claim(\r\n payment: Payment,\r\n destination: string,\r\n opts: ClaimOpts,\r\n ): Promise<ClaimReceipt> {\r\n const isToken = !!payment.claimableBalanceId || !isNativeAsset(payment.asset);\r\n if (isToken) {\r\n return this.claimToken(payment, destination, opts);\r\n }\r\n return this.claimNative(payment, destination, opts);\r\n }\r\n\r\n /**\r\n * Claim a native XLM direct send. The stealth account is a real funded Stellar\r\n * account with a sequence number. Full sweep (default) uses AccountMerge; a\r\n * partial claim uses Payment. Signing uses the raw stealth scalar (verifies as\r\n * standard ed25519). Optionally fee-bumped via a relayer.\r\n *\r\n * Passing `opts.amount` without `merge: false` is rejected up front\r\n * ({@link ClaimAmountRequiresNoMergeError}): the default merge sweeps the\r\n * ENTIRE balance via AccountMerge, so silently ignoring `amount` would move\r\n * more funds than the caller asked for.\r\n */\r\n private async claimNative(\r\n payment: Payment,\r\n destination: string,\r\n opts: ClaimOpts,\r\n ): Promise<ClaimReceipt> {\r\n // Fund-safety guard BEFORE any I/O or signing: amount + effective merge\r\n // would sweep everything while looking like a partial claim.\r\n if (opts.amount !== undefined && opts.merge !== false) {\r\n throw new ClaimAmountRequiresNoMergeError('native-merge');\r\n }\r\n const stealthPrivKey = this.recoverKey(payment, opts);\r\n const stealthAddress = payment.stealthAddress;\r\n const account = await this.horizon.getAccount(stealthAddress);\r\n if (!account) {\r\n throw new StealthAccountNotFoundError();\r\n }\r\n\r\n const source = new Account(account.id, account.sequence);\r\n const merge = opts.merge !== false;\r\n // Normalized so `[]`/whitespace lists mean \"not relayed\" — this flag decides\r\n // whether the self-paid fee is subtracted from the receipt below.\r\n const relayed = !!(\r\n normalizeRelayList(opts.relay) ?? normalizeRelayList(this.relayer)\r\n );\r\n // All fee/balance/max-claimable arithmetic is done in EXACT bigint stroops\r\n // (never floats): above 2^53 stroops a double cannot represent every stroop,\r\n // so float math could move the wrong amount on-chain or mis-evaluate the\r\n // pre-check (SDK-FLOAT). Only the receipt's display `amount` (a public\r\n // `number` field) is rendered back through a float at the very edge.\r\n const feeStroops = BigInt(BASE_FEE);\r\n const nativeBal = account.balances.find((b) => b.asset_type === 'native');\r\n const balanceStroops = nativeBal ? parseStroops(nativeBal.balance) : 0n;\r\n\r\n const builder = new TransactionBuilder(source, {\r\n fee: BASE_FEE,\r\n networkPassphrase: this.networkPassphrase,\r\n });\r\n\r\n let amount: number;\r\n if (merge) {\r\n builder.addOperation(Operation.accountMerge({ destination }));\r\n // A full merge delivers the whole native balance. When the stealth\r\n // account self-pays the fee (not relayed), the destination receives the\r\n // balance minus that fee — subtract it so the receipt does not overstate\r\n // what actually arrives.\r\n const delivered = relayed ? balanceStroops : balanceStroops - feeStroops;\r\n amount = Number(formatStroops(delivered));\r\n } else {\r\n if (opts.amount === undefined) {\r\n throw new Error('Partial account claim requires opts.amount');\r\n }\r\n // The exact stroop count actually paid out. `numberToStroops` rejects\r\n // amounts a stroop cannot represent (sub-stroop precision, negatives)\r\n // instead of silently rounding them.\r\n const requestedStroops = numberToStroops(opts.amount);\r\n // The account must retain 2x the base reserve (1.0 XLM) and cover the fee\r\n // (self-paid when not relayed). Reject an over-large partial before\r\n // building so it fails with a typed error, not an on-chain op_underfunded\r\n // after the fee is burned.\r\n const maxClaimableStroops =\r\n balanceStroops - ACCOUNT_RESERVE_STROOPS - feeStroops;\r\n if (requestedStroops > maxClaimableStroops) {\r\n throw new ClaimAmountError(\r\n opts.amount,\r\n Number(formatStroops(maxClaimableStroops)),\r\n );\r\n }\r\n builder.addOperation(\r\n Operation.payment({\r\n destination,\r\n asset: Asset.native(),\r\n amount: formatStroops(requestedStroops),\r\n }),\r\n );\r\n amount = opts.amount;\r\n }\r\n\r\n const tx = builder.setTimeout(30).build();\r\n const sig = stealthPrivKey.sign(tx.hash());\r\n stealthPrivKey.zeroize();\r\n tx.addSignature(stealthAddress, Buffer.from(sig).toString('base64'));\r\n\r\n const txHash = await this.submit(tx.toEnvelope().toXDR('base64'), opts);\r\n return { txHash, amount, method: 'account' };\r\n }\r\n\r\n /**\r\n * Claim a token direct send delivered as a claimable balance. Requires the\r\n * destination to already trust the asset (probed first with an actionable\r\n * error otherwise).\r\n *\r\n * Self-funded path (stealth account exists): ChangeTrust(asset) ->\r\n * ClaimClaimableBalance(id) -> optional full exit\r\n * [Payment(asset, destination) -> ChangeTrust(limit '0') ->\r\n * AccountMerge(destination)].\r\n *\r\n * Sponsored path (`opts.sponsored`, or account stub missing): delegate to the\r\n * relayer's sponsor-claim pair — prepare returns XDR, we attach the stealth\r\n * signature and submit.\r\n */\r\n private async claimToken(\r\n payment: Payment,\r\n destination: string,\r\n opts: ClaimOpts,\r\n ): Promise<ClaimReceipt> {\r\n // Fund-safety guard: a token claim always claims (and pays out) the FULL\r\n // claimable balance — `opts.amount` cannot be honored, so reject it loudly\r\n // instead of silently moving a different amount.\r\n if (opts.amount !== undefined) {\r\n throw new ClaimAmountRequiresNoMergeError('token');\r\n }\r\n if (!payment.claimableBalanceId) {\r\n throw new Error('Token claim requires a claimableBalanceId on the payment');\r\n }\r\n const asset = payment.asset ?? payment.token;\r\n const stellarAsset = parseAsset(asset);\r\n const amount = payment.amount;\r\n // Exact 7-dp payout string derived from the precise stroop count, NOT the\r\n // lossy `payment.amount` double: above 2^53 stroops a number cannot represent\r\n // every stroop, so `amount.toFixed(7)` could pay one short (SDK-PREC-1).\r\n // When the exact stroop count is unavailable we fall back to the lossy\r\n // amount WITHOUT an extra Horizon round-trip (the caller already has the\r\n // amount in hand from the scan).\r\n const payoutAmount = this.resolveExactPayout(payment);\r\n\r\n await this.assertDestinationTrusts(destination, stellarAsset);\r\n\r\n const stealthAddress = payment.stealthAddress;\r\n const account = await this.horizon.getAccount(stealthAddress);\r\n const relays =\r\n normalizeRelayList(opts.relay) ?? normalizeRelayList(this.relayer);\r\n\r\n if (opts.sponsored || !account) {\r\n if (!relays) {\r\n throw new Error(\r\n 'Sponsored token claim requires a relayer URL (opts.relay or client relayer).',\r\n );\r\n }\r\n return this.claimTokenSponsored(\r\n payment,\r\n opts,\r\n relays,\r\n amount,\r\n destination,\r\n payoutAmount,\r\n );\r\n }\r\n\r\n const stealthPrivKey = this.recoverKey(payment, opts);\r\n const source = new Account(account.id, account.sequence);\r\n const merge = opts.merge !== false;\r\n\r\n const builder = new TransactionBuilder(source, {\r\n fee: BASE_FEE,\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(Operation.changeTrust({ asset: stellarAsset }))\r\n .addOperation(\r\n Operation.claimClaimableBalance({\r\n balanceId: payment.claimableBalanceId,\r\n }),\r\n );\r\n\r\n if (merge) {\r\n builder\r\n .addOperation(\r\n Operation.payment({\r\n destination,\r\n asset: stellarAsset,\r\n amount: payoutAmount,\r\n }),\r\n )\r\n .addOperation(Operation.changeTrust({ asset: stellarAsset, limit: '0' }))\r\n .addOperation(Operation.accountMerge({ destination }));\r\n }\r\n\r\n const tx = builder.setTimeout(30).build();\r\n const sig = stealthPrivKey.sign(tx.hash());\r\n stealthPrivKey.zeroize();\r\n tx.addSignature(stealthAddress, Buffer.from(sig).toString('base64'));\r\n\r\n const txHash = await this.submit(tx.toEnvelope().toXDR('base64'), opts);\r\n return { txHash, amount, method: 'account' };\r\n }\r\n\r\n /**\r\n * Sponsored claim: relayer prepares the XDR (BeginSponsoring -> [CreateAccount]\r\n * -> ChangeTrust -> EndSponsoring -> ClaimClaimableBalance -> Payment to the\r\n * destination), we co-sign with the stealth key, relayer submits and pays the\r\n * fee. The claimed token is delivered to `destination` in the same tx — the\r\n * stealth account never needs its own fee balance. The receipt's amount is the\r\n * amount that reached the destination.\r\n */\r\n private async claimTokenSponsored(\r\n payment: Payment,\r\n opts: ClaimOpts,\r\n relays: string[],\r\n amount: number,\r\n destination: string,\r\n payoutAmount: string,\r\n ): Promise<ClaimReceipt> {\r\n // ONE relayer is pinned up front for the whole flow: the prepared tx is\r\n // sourced by that relayer's own account, so prepare and submit MUST hit\r\n // the same URL — failing over between them is impossible by construction.\r\n const pool = new RelayerPool(relays, {\r\n network: networkNameForPassphrase(this.networkPassphrase),\r\n selection: this.relayerSelection,\r\n });\r\n const relay = await pool.select({\r\n fundingAccount: opts.fundingAccount,\r\n fundingSigner: opts.fundingSigner,\r\n rpcServer: this.rpcServer,\r\n });\r\n // Built per call so the client carries THIS call's funding signer and the\r\n // confirm-poll handle.\r\n const client = new RelayerClient(relay, undefined, {\r\n fundingSigner: opts.fundingSigner,\r\n rpcServer: this.rpcServer,\r\n });\r\n const asset = payment.asset ?? payment.token;\r\n\r\n const balanceId = payment.claimableBalanceId;\r\n if (!balanceId) {\r\n throw new Error('Sponsored token claim requires a claimableBalanceId');\r\n }\r\n\r\n const { xdr } = await client.sponsorClaimPrepare({\r\n stealthAddress: payment.stealthAddress,\r\n asset,\r\n balanceId,\r\n destination,\r\n amount: payoutAmount,\r\n });\r\n\r\n // CRITICAL: verify the relayer-prepared XDR against our OWN trusted inputs\r\n // BEFORE signing. A malicious relayer could otherwise redirect the payout\r\n // Payment or append an AccountMerge to steal the just-claimed token — the\r\n // relayer-side opsMatch protects the relayer, not us.\r\n const tx = this.verifySponsoredClaimXdr(xdr, {\r\n stealthAddress: payment.stealthAddress,\r\n asset,\r\n balanceId,\r\n destination,\r\n payoutAmount,\r\n });\r\n\r\n const stealthPrivKey = this.recoverKey(payment, opts);\r\n const sig = stealthPrivKey.sign(tx.hash());\r\n stealthPrivKey.zeroize();\r\n tx.addSignature(payment.stealthAddress, Buffer.from(sig).toString('base64'));\r\n\r\n // A gated relayer verifies the proof-of-control signature over the EXACT\r\n // total it debits — the prepared tx's fee plus the sponsored-reserve\r\n // estimate — recomputed server-side from the same tx, so this must match\r\n // byte-for-byte (see packages/relayer/src/routes/sponsorClaim.ts). Prefer\r\n // the estimate THIS pinned relayer advertises via /health so a\r\n // relayer-side change cannot silently break gated claims; the mirrored\r\n // constant covers relayers that do not advertise it (and a /health fault,\r\n // which must never break the claim itself).\r\n const reserveStroops =\r\n (await client.sponsoredReserveEstimateStroops()) ??\r\n SPONSORED_RESERVE_ESTIMATE_STROOPS;\r\n const authAmount = formatStroops(BigInt(tx.fee) + reserveStroops);\r\n\r\n const { txHash } = await client.sponsorClaimSubmit(\r\n tx.toEnvelope().toXDR('base64'),\r\n {\r\n stealthAddress: payment.stealthAddress,\r\n asset,\r\n balanceId,\r\n destination,\r\n amount: payoutAmount,\r\n fundingAccount: opts.fundingAccount,\r\n fundingSigner: opts.fundingSigner,\r\n authAmount,\r\n confirm: opts.confirm,\r\n },\r\n );\r\n return { txHash, amount, method: 'account' };\r\n }\r\n\r\n /**\r\n * Parse and verify a relayer-prepared sponsored-claim XDR against the client's\r\n * OWN trusted inputs BEFORE signing. This is the client-side security control:\r\n * the relayer-side `opsMatch` protects the relayer, not us, so a malicious\r\n * relayer could otherwise redirect the payout Payment or append an\r\n * AccountMerge to steal the just-claimed token.\r\n *\r\n * Verifies, throwing {@link SponsoredClaimMismatchError} on any mismatch:\r\n * - the tx is sourced by the relayer (never the stealth account);\r\n * - the tx carries no memo;\r\n * - every operation is one of the allowed sponsor-claim shapes, in the exact\r\n * order the relayer builds — BeginSponsoring(stealth) -> optional\r\n * CreateAccount(stealth, '0') -> ChangeTrust(asset, source stealth) ->\r\n * EndSponsoring(source stealth) -> ClaimClaimableBalance(balanceId, source\r\n * stealth) -> Payment(destination, asset, amount, source stealth);\r\n * - every value-moving op is sourced by the stealth account;\r\n * - the payout Payment's destination/asset/amount equal the caller's intent;\r\n * - no extra, missing, or reordered operations.\r\n *\r\n * Returns the parsed {@link Transaction} (ready to co-sign) on success.\r\n */\r\n private verifySponsoredClaimXdr(\r\n xdr: string,\r\n expected: {\r\n stealthAddress: string;\r\n asset: string;\r\n balanceId: string;\r\n destination: string;\r\n payoutAmount: string;\r\n },\r\n ): Transaction {\r\n let tx: Transaction;\r\n try {\r\n tx = new Transaction(xdr, this.networkPassphrase);\r\n } catch {\r\n throw new SponsoredClaimMismatchError('prepared XDR is not a valid transaction');\r\n }\r\n\r\n if (tx.memo && tx.memo.type !== 'none') {\r\n throw new SponsoredClaimMismatchError('unexpected memo on the prepared transaction');\r\n }\r\n\r\n const relayer = tx.source;\r\n const { stealthAddress, balanceId, destination, payoutAmount } = expected;\r\n const wantAsset = parseAsset(expected.asset);\r\n const wantAssetStr = wantAsset.isNative()\r\n ? 'native'\r\n : `${wantAsset.getCode()}:${wantAsset.getIssuer()}`;\r\n\r\n // Rebuild the exact op sequence the relayer must have produced. CreateAccount\r\n // is optional (only when the stealth account did not already exist), so we\r\n // build both a with-create and without-create expectation and require the\r\n // submitted ops to match one of them positionally.\r\n // Normalize a decimal amount string via its EXACT stroop count so '0' and\r\n // '0.0000000' (and '100' vs '100.0000000') compare equal WITHOUT laundering\r\n // through a lossy float — an amount above 2^53 stroops must still compare\r\n // exactly, so String(Number(value)) would be wrong here (SDK-PREC-1).\r\n const amt = (value: string): string => parseStroops(value).toString();\r\n\r\n const opStr = (op: OperationRecord): string => {\r\n const src = op.source ?? relayer;\r\n switch (op.type) {\r\n case 'beginSponsoringFutureReserves':\r\n return `begin|${src}|${(op as Operation.BeginSponsoringFutureReserves).sponsoredId}`;\r\n case 'createAccount': {\r\n const o = op as Operation.CreateAccount;\r\n return `create|${src}|${o.destination}|${amt(o.startingBalance)}`;\r\n }\r\n case 'changeTrust': {\r\n const o = op as Operation.ChangeTrust;\r\n return `trust|${src}|${assetToString(o.line as Asset)}`;\r\n }\r\n case 'endSponsoringFutureReserves':\r\n return `end|${src}`;\r\n case 'claimClaimableBalance':\r\n return `claim|${src}|${(op as Operation.ClaimClaimableBalance).balanceId}`;\r\n case 'payment': {\r\n const o = op as Operation.Payment;\r\n return `pay|${src}|${o.destination}|${assetToString(o.asset as Asset)}|${amt(o.amount)}`;\r\n }\r\n default:\r\n return `UNSUPPORTED:${op.type}|${src}`;\r\n }\r\n };\r\n\r\n const buildExpected = (withCreate: boolean): string[] => {\r\n const ops: string[] = [];\r\n ops.push(`begin|${relayer}|${stealthAddress}`);\r\n // CreateAccount inherits the tx (relayer) source in the relayer's build.\r\n if (withCreate) ops.push(`create|${relayer}|${stealthAddress}|${amt('0')}`);\r\n ops.push(`trust|${stealthAddress}|${wantAssetStr}`);\r\n ops.push(`end|${stealthAddress}`);\r\n ops.push(`claim|${stealthAddress}|${balanceId}`);\r\n ops.push(`pay|${stealthAddress}|${destination}|${wantAssetStr}|${amt(payoutAmount)}`);\r\n return ops;\r\n };\r\n\r\n const submitted = tx.operations.map(opStr);\r\n const withCreate = buildExpected(true).join('\\n');\r\n const withoutCreate = buildExpected(false).join('\\n');\r\n const actual = submitted.join('\\n');\r\n if (actual !== withCreate && actual !== withoutCreate) {\r\n throw new SponsoredClaimMismatchError(\r\n `operations do not match the expected sponsor-claim sequence (got: ${actual})`,\r\n );\r\n }\r\n\r\n return tx;\r\n }\r\n\r\n /**\r\n * Resolve the EXACT 7-dp payout string for a token claim from the precise\r\n * stroop count, never the lossy `payment.amount` double. Prefers the exact\r\n * `payment.amountStroops` string; when it is absent, falls back to the 7-dp\r\n * `payment.amount` double with NO extra Horizon read (the amount is already in\r\n * hand from the scan). Above 2^53 stroops the double in `payment.amount`\r\n * cannot represent every stroop, so an exact stroop count should always be\r\n * threaded through when available (SDK-PREC-1).\r\n */\r\n private resolveExactPayout(payment: Payment): string {\r\n if (payment.amountStroops) {\r\n return formatStroops(BigInt(payment.amountStroops));\r\n }\r\n return payment.amount.toFixed(7);\r\n }\r\n\r\n /** Recover the stealth scalar for signing from the payment's ephemeral R. */\r\n private recoverKey(payment: Payment, opts: ClaimOpts): StealthScalar {\r\n const viewPrivKey = new Uint8Array(Buffer.from(opts.keys.viewPrivKey, 'hex'));\r\n const spendPrivKey = new Uint8Array(\r\n Buffer.from(opts.keys.spendPrivKey, 'hex'),\r\n );\r\n const ephemeralPubKey = new Uint8Array(\r\n Buffer.from(payment.ephemeralPubKey, 'hex'),\r\n );\r\n return recoverStealthPrivateKey(spendPrivKey, viewPrivKey, ephemeralPubKey);\r\n }\r\n\r\n /** Fail with an actionable error unless the destination trusts the asset. */\r\n private async assertDestinationTrusts(\r\n destination: string,\r\n asset: Asset,\r\n ): Promise<void> {\r\n if (asset.isNative()) return;\r\n const dest = await this.horizon.getAccount(destination);\r\n if (!dest) {\r\n throw new DestinationTrustlineError(\r\n `Destination ${destination} not found on Horizon — fund it and add a ${asset.getCode()} trustline before claiming.`,\r\n );\r\n }\r\n const code = asset.getCode();\r\n const issuer = asset.getIssuer();\r\n const trusts = dest.balances.some(\r\n (b) =>\r\n (b as { asset_code?: string; asset_issuer?: string }).asset_code ===\r\n code &&\r\n (b as { asset_code?: string; asset_issuer?: string }).asset_issuer ===\r\n issuer,\r\n );\r\n if (!trusts) {\r\n throw new DestinationTrustlineError(\r\n `Destination ${destination} does not trust ${assetToString(asset)}. ` +\r\n `Add the trustline on the destination account before claiming.`,\r\n );\r\n }\r\n }\r\n\r\n /** Submit an XDR directly to Horizon, or via a relayer fee-bump when set. */\r\n private async submit(xdr: string, opts: ClaimOpts): Promise<string> {\r\n const relays =\r\n normalizeRelayList(opts.relay) ?? normalizeRelayList(this.relayer);\r\n if (relays) {\r\n // Built per call — a per-call opts.relay must win over the ctor relayer,\r\n // and the clients must carry THIS call's funding signer — mirroring the\r\n // pool withdraw path. A single URL is a transparent pass-through; a list\r\n // is health-probed with failover on relayer faults only (A3). The\r\n // passphrase binds the inner-tx hash into the proof-of-control signature\r\n // (REL-01); authAmount is auto-fetched from /health maxRelayFeeXlm.\r\n // Confirm-polling runs OUTSIDE the pool's attempt budget so a slow\r\n // ledger close is never misread as a dead relayer (which could resubmit).\r\n const pool = new RelayerPool(relays, {\r\n network: networkNameForPassphrase(this.networkPassphrase),\r\n selection: this.relayerSelection,\r\n });\r\n const txHash = await pool.withRelayer(\r\n async (client) =>\r\n (\r\n await client.relay(xdr, {\r\n fundingAccount: opts.fundingAccount,\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n ).txHash,\r\n {\r\n fundingAccount: opts.fundingAccount,\r\n fundingSigner: opts.fundingSigner,\r\n rpcServer: this.rpcServer,\r\n },\r\n );\r\n if (opts.confirm) {\r\n if (!this.rpcServer) {\r\n throw new Error(\r\n 'confirm: true requires an RPC handle: construct the AccountAdapter ' +\r\n 'with opts.rpcServer (an rpc.Server for the same network).',\r\n );\r\n }\r\n await waitForTransaction(this.rpcServer, txHash);\r\n }\r\n return txHash;\r\n }\r\n const res = await this.horizon.submitTransaction(xdr);\r\n return res.hash;\r\n }\r\n}\r\n","import { MethodNotAvailableError } from '../errors.js';\r\nimport type {\r\n StealthKeys,\r\n Payment,\r\n ClaimReceipt,\r\n ClaimOpts,\r\n SendReceipt,\r\n} from '../types.js';\r\nimport type { DeliveryAdapter, AdapterSendParams } from './types.js';\r\n\r\nconst SPP_MESSAGE =\r\n \"the 'spp' method is reserved for future Stellar Private Payments integration\";\r\n\r\n/**\r\n * Reserved adapter slot for Stellar Private Payments (SPP).\r\n *\r\n * SPP is the Nethermind ZK shielded-pool research prototype (testnet-only\r\n * today). This adapter intentionally implements the full {@link DeliveryAdapter}\r\n * surface but every method throws {@link MethodNotAvailableError}. The slot\r\n * exists so applications can opt into SPP later — by adding `'spp'` to\r\n * `ClientConfig.methods` — with ZERO API changes: the same `send`/`scan`/`claim`\r\n * calls simply start routing through a real SPP implementation once it lands.\r\n */\r\nexport class SppAdapter implements DeliveryAdapter {\r\n readonly method = 'spp' as const;\r\n\r\n /**\r\n * @throws {MethodNotAvailableError} Always — SPP is not yet implemented. The\r\n * declared return type is {@link SendReceipt} (never actually returned) so the\r\n * adapter's surface matches the {@link DeliveryAdapter} interface exactly.\r\n */\r\n async send(_params: AdapterSendParams): Promise<SendReceipt> {\r\n throw new MethodNotAvailableError(SPP_MESSAGE);\r\n }\r\n\r\n /** @throws {MethodNotAvailableError} Always — SPP is not yet implemented. */\r\n async scan(\r\n _keys: StealthKeys,\r\n _cursor?: string,\r\n ): Promise<{ payments: Payment[]; cursor?: string }> {\r\n throw new MethodNotAvailableError(SPP_MESSAGE);\r\n }\r\n\r\n /** @throws {MethodNotAvailableError} Always — SPP is not yet implemented. */\r\n async claim(\r\n _payment: Payment,\r\n _destination: string,\r\n _opts: ClaimOpts,\r\n ): Promise<ClaimReceipt> {\r\n throw new MethodNotAvailableError(SPP_MESSAGE);\r\n }\r\n}\r\n","import {\r\n generateMetaAddress,\r\n generateMnemonic,\r\n mnemonicToStealthKeys,\r\n} from '@shade/crypto';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { getNetworkConfig } from './soroban.js';\r\nimport { stealthKeysFromRaw } from './wallet.js';\r\nimport { HorizonClient } from './horizon.js';\r\nimport { IndexerClient } from './indexer.js';\r\nimport { PoolAdapter } from './methods/pool.js';\r\nimport { AccountAdapter } from './methods/account.js';\r\nimport { SppAdapter } from './methods/spp.js';\r\nimport { normalizeRelayList, type RelayerSelection } from './relayerPool.js';\r\nimport {\r\n MethodRequiredError,\r\n MethodNotEnabledError,\r\n MethodNotAvailableError,\r\n ContractIdRequiredError,\r\n} from './errors.js';\r\nimport type { DeliveryAdapter } from './methods/types.js';\r\nimport type {\r\n ClientConfig,\r\n StealthKeys,\r\n SendReceipt,\r\n SendOpts,\r\n Payment,\r\n Balance,\r\n WithdrawReceipt,\r\n WithdrawOpts,\r\n DeliveryMethod,\r\n ScanOpts,\r\n ScanResult,\r\n ScanCursor,\r\n ClaimOpts,\r\n ClaimReceipt,\r\n} from './types.js';\r\n\r\n/**\r\n * High-level client for stealth payments on Stellar.\r\n *\r\n * Wraps DKSAP cryptography behind pluggable delivery methods. Each method\r\n * (`'pool'`, `'account'`, and the reserved `'spp'`) is an adapter; the client\r\n * builds a registry from `config.methods` and routes send/scan/claim through it.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new StealthClient({\r\n * network: 'testnet',\r\n * contractId: 'C...', // your deployed pool contract (required for 'pool')\r\n * methods: ['pool', 'account'],\r\n * });\r\n *\r\n * const keys = StealthClient.keygen();\r\n *\r\n * // A method is REQUIRED on every send — no implicit default.\r\n * await client.send(keys.metaAddress, 100, 'SXXX...', { method: 'auto' });\r\n *\r\n * const { payments } = await client.scanWithCursor(keys);\r\n * await client.claim(payments[0], 'GDEST...', { keys });\r\n * ```\r\n */\r\nexport class StealthClient {\r\n private readonly contractId: string;\r\n private readonly networkPassphrase: string;\r\n private readonly server: StellarSdk.rpc.Server;\r\n private readonly enabledMethods: DeliveryMethod[];\r\n private readonly adapters: Map<DeliveryMethod, DeliveryAdapter>;\r\n private readonly relayer?: string | string[];\r\n private readonly relayerSelection?: RelayerSelection;\r\n\r\n constructor(config: ClientConfig) {\r\n this.contractId = config.contractId || '';\r\n const netConfig = getNetworkConfig(config.network);\r\n this.networkPassphrase = netConfig.networkPassphrase;\r\n this.server = netConfig.server;\r\n this.relayer = config.relayer;\r\n this.relayerSelection = config.relayerSelection;\r\n this.enabledMethods = config.methods && config.methods.length > 0\r\n ? config.methods\r\n : ['pool'];\r\n\r\n // The pool method cannot function without a contract id, and there are no\r\n // built-in defaults (pool deployments are per-operator), so a client with\r\n // pool enabled and no explicit contractId must fail loudly here instead of\r\n // surfacing an opaque Soroban error on the first pool call.\r\n if (this.enabledMethods.includes('pool') && !this.contractId) {\r\n throw new ContractIdRequiredError(config.network);\r\n }\r\n\r\n const horizonUrl = config.horizonUrl || netConfig.horizonUrl;\r\n const horizon = new HorizonClient(horizonUrl);\r\n // Optional account-method discovery accelerator; the scan health-guards it\r\n // and falls back to the pure Horizon walk on any fault.\r\n const indexer = config.indexerUrl\r\n ? new IndexerClient(config.indexerUrl)\r\n : undefined;\r\n\r\n this.adapters = new Map();\r\n for (const method of this.enabledMethods) {\r\n switch (method) {\r\n case 'pool':\r\n this.adapters.set(\r\n 'pool',\r\n new PoolAdapter(this.contractId, this.networkPassphrase, this.server, {\r\n relayerSelection: this.relayerSelection,\r\n }),\r\n );\r\n break;\r\n case 'account':\r\n this.adapters.set(\r\n 'account',\r\n new AccountAdapter(this.networkPassphrase, horizon, this.relayer, {\r\n // Confirm-poll handle for relayed claims (`confirm: true`): the\r\n // Soroban RPC's getTransaction resolves classic tx hashes too.\r\n rpcServer: this.server,\r\n relayerSelection: this.relayerSelection,\r\n indexer,\r\n indexerMaxLagSeconds: config.indexerMaxLagSeconds,\r\n }),\r\n );\r\n break;\r\n case 'spp':\r\n this.adapters.set('spp', new SppAdapter());\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Generate a new random stealth key pair.\r\n * No network connection needed.\r\n */\r\n static keygen(): StealthKeys {\r\n return stealthKeysFromRaw(generateMetaAddress());\r\n }\r\n\r\n /**\r\n * Generate stealth keys from a BIP-39 mnemonic.\r\n * Returns the mnemonic alongside the keys for backup.\r\n * No network connection needed.\r\n */\r\n static fromMnemonic(mnemonic?: string): StealthKeys & { mnemonic: string } {\r\n const phrase = mnemonic || generateMnemonic();\r\n return {\r\n mnemonic: phrase,\r\n ...stealthKeysFromRaw(mnemonicToStealthKeys(phrase)),\r\n };\r\n }\r\n\r\n /**\r\n * Resolve `'auto'` to a concrete method: native asset AND amount > 1 AND\r\n * 'account' enabled -> 'account'; otherwise 'pool'.\r\n */\r\n private resolveMethod(\r\n requested: DeliveryMethod | 'auto',\r\n amount: number,\r\n asset?: string,\r\n ): DeliveryMethod {\r\n if (requested === 'auto') {\r\n const isNative = !asset || asset === 'native' || asset === 'XLM';\r\n if (isNative && amount > 1 && this.adapters.has('account')) {\r\n return 'account';\r\n }\r\n return 'pool';\r\n }\r\n return requested;\r\n }\r\n\r\n private getAdapter(method: DeliveryMethod): DeliveryAdapter {\r\n const adapter = this.adapters.get(method);\r\n if (!adapter) throw new MethodNotEnabledError(method);\r\n return adapter;\r\n }\r\n\r\n /**\r\n * Send tokens to a stealth address via the chosen delivery method.\r\n *\r\n * A method is REQUIRED on every call (`opts.method`). Pass `'auto'` to let the\r\n * client resolve one; there is deliberately no implicit default.\r\n *\r\n * @param metaAddress - Recipient's meta-address (shade:stellar:... format)\r\n * @param amount - Amount in whole units (e.g. 100 = 100 XLM)\r\n * @param senderSecret - Sender's Stellar secret key\r\n * @param opts - Delivery method (required) and optional asset\r\n * @throws {MethodRequiredError} If no method is provided.\r\n * @throws {MethodNotEnabledError} If the resolved method is not enabled.\r\n */\r\n async send(\r\n metaAddress: string,\r\n amount: number,\r\n senderSecret: string,\r\n opts: SendOpts,\r\n ): Promise<SendReceipt> {\r\n // opts is required at the type level too, but keep the runtime guard for\r\n // plain-JS callers (and for `{}` casts) so misuse still fails loudly.\r\n if (!opts || !opts.method) {\r\n throw new MethodRequiredError();\r\n }\r\n const method = this.resolveMethod(opts.method, amount, opts.asset);\r\n const adapter = this.getAdapter(method);\r\n return adapter.send({\r\n metaAddress,\r\n amount,\r\n senderSecret,\r\n asset: opts.asset,\r\n signTransaction: opts.signTransaction,\r\n });\r\n }\r\n\r\n /**\r\n * Scan for stealth payments across every enabled delivery method.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async scan(keys: StealthKeys): Promise<Payment[]> {\r\n const { payments } = await this.scanWithCursor(keys);\r\n return payments;\r\n }\r\n\r\n /**\r\n * Cursor-aware scan across enabled (or explicitly requested) methods. Returns\r\n * the merged payments plus an updated per-method cursor to persist and pass to\r\n * the next scan for incremental discovery.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n * @param opts - Optional method filter and resume cursor\r\n */\r\n async scanWithCursor(\r\n keys: StealthKeys,\r\n opts?: ScanOpts,\r\n ): Promise<ScanResult> {\r\n return this.scanInternal(keys, opts, false);\r\n }\r\n\r\n /**\r\n * Shared scan implementation. When `suppressClaimed` is set (the balance\r\n * path), the account adapter drops fully-swept/merged native accounts (live\r\n * balance 0) so a spent stealth account is not reported as spendable — while\r\n * the plain discovery scan keeps returning still-claimable rows.\r\n */\r\n private async scanInternal(\r\n keys: StealthKeys,\r\n opts: ScanOpts | undefined,\r\n suppressClaimed: boolean,\r\n ): Promise<ScanResult> {\r\n const methods = (opts?.methods ?? this.enabledMethods).filter((m) =>\r\n this.adapters.has(m),\r\n );\r\n const cursor: ScanCursor = { ...(opts?.cursor ?? {}) };\r\n const payments: Payment[] = [];\r\n // Adapter-reported scan diagnostics, surfaced verbatim under the method's\r\n // key — only for methods that reported any (observability only).\r\n const meta: NonNullable<ScanResult['meta']> = {};\r\n\r\n for (const method of methods) {\r\n const adapter = this.getAdapter(method);\r\n const prev = cursor[method];\r\n const result = await adapter.scan(keys, prev, {\r\n suppressClaimedNative: suppressClaimed,\r\n exhaustive: opts?.exhaustive,\r\n });\r\n for (const p of result.payments) {\r\n payments.push({ ...p, method });\r\n }\r\n cursor[method] = result.cursor;\r\n if (result.meta) meta[method] = result.meta;\r\n }\r\n\r\n return { payments, cursor, meta };\r\n }\r\n\r\n /**\r\n * Get balances for all your stealth payments across enabled methods.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n * @param opts - Optional method filter and resume cursor (a cursor returned\r\n * by a previous {@link scanWithCursor}/{@link balanceWithCursor}). With no\r\n * opts the whole history is scanned, exactly as before. Passing the\r\n * persisted cursor turns the account phase from a full Horizon re-walk\r\n * into O(new transactions); use {@link balanceWithCursor} when you also\r\n * need the advanced cursor back to persist it.\r\n */\r\n async balance(keys: StealthKeys, opts?: ScanOpts): Promise<Balance[]> {\r\n const { payments } = await this.balanceWithCursor(keys, opts);\r\n return payments.map((p) => ({\r\n stealthAddress: p.stealthAddress,\r\n token: p.token,\r\n amount: p.amount,\r\n amountStroops: p.amountStroops,\r\n }));\r\n }\r\n\r\n /**\r\n * Cursor-aware balance check: like {@link balance}, but resumes the\r\n * underlying scan from `opts.cursor` and returns the full live payments\r\n * (ephemeral key, txHash, claimable-balance id) PLUS the advanced cursor so\r\n * callers can persist it for the next call — the exact counterpart of\r\n * {@link scanWithCursor} for the balance path.\r\n *\r\n * The rows are the balance view: claimed/fully-swept payments are dropped\r\n * and native rows report the LIVE remaining account balance (not the\r\n * original per-transaction amount). Callers that persist discovered\r\n * payments should merge these rows into their cache BEFORE persisting the\r\n * advanced cursor, since the next resumed scan will skip everything behind\r\n * it.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n * @param opts - Optional method filter and resume cursor\r\n */\r\n async balanceWithCursor(\r\n keys: StealthKeys,\r\n opts?: ScanOpts,\r\n ): Promise<ScanResult> {\r\n return this.scanInternal(keys, opts, true);\r\n }\r\n\r\n /**\r\n * Claim a detected payment to a destination, branching on the payment's\r\n * delivery method: `'pool'` uses the withdraw path, `'account'` sweeps or\r\n * partially pays out the stealth account.\r\n *\r\n * @param payment - A payment returned from {@link scan}/{@link scanWithCursor}.\r\n * @param destination - Destination Stellar G-address.\r\n * @param opts - Claim options (keys required; relay/merge/feePayer optional).\r\n */\r\n async claim(\r\n payment: Payment,\r\n destination: string,\r\n opts: ClaimOpts,\r\n ): Promise<ClaimReceipt> {\r\n const adapter = this.getAdapter(payment.method);\r\n // Normalized so an empty/whitespace per-call list falls back to the config\r\n // relayer instead of shadowing it (and `[]` means \"no relayer\", not a pool\r\n // of zero candidates).\r\n const relay =\r\n normalizeRelayList(opts.relay) ?? normalizeRelayList(this.relayer);\r\n return adapter.claim(payment, destination, { ...opts, relay });\r\n }\r\n\r\n /**\r\n * Withdraw tokens from the stealth pool.\r\n *\r\n * @deprecated Use {@link claim} with a pool payment instead. Retained for\r\n * backwards compatibility; behaves exactly like the original pool withdraw.\r\n *\r\n * @param stealthAddress - The stealth address to withdraw from\r\n * @param destination - Destination Stellar address (G...)\r\n * @param opts - Withdraw options (keys, feePayer, optional relay/asset/amount)\r\n */\r\n async withdraw(\r\n stealthAddress: string,\r\n destination: string,\r\n opts: WithdrawOpts,\r\n ): Promise<WithdrawReceipt> {\r\n const adapter = this.adapters.get('pool');\r\n if (!(adapter instanceof PoolAdapter)) {\r\n throw new MethodNotAvailableError(\r\n \"The 'pool' method must be enabled to use withdraw()\",\r\n );\r\n }\r\n const result = await adapter.withdraw(stealthAddress, destination, {\r\n keys: opts.keys,\r\n feePayer: opts.feePayer,\r\n relay: normalizeRelayList(opts.relay) ?? normalizeRelayList(this.relayer),\r\n asset: opts.asset,\r\n amount: opts.amount,\r\n fundingAccount: opts.fundingAccount,\r\n fundingSigner: opts.fundingSigner,\r\n confirm: opts.confirm,\r\n });\r\n return { txHash: result.txHash, amount: result.amount };\r\n }\r\n}\r\n","import { scalarMultBase } from '@shade/crypto';\r\nimport { WrongPasswordError, SessionIntegrityError } from './errors.js';\r\nimport type { StealthKeys, Payment, ScanCursor } from './types.js';\r\n\r\n/**\r\n * A minimal key/value storage interface. `window.localStorage` satisfies it\r\n * directly; cookie / IndexedDB / React-Native wrappers are the app's job. All\r\n * methods may be sync or async so async backends work transparently.\r\n */\r\nexport interface KVStorage {\r\n getItem(key: string): string | null | Promise<string | null>;\r\n setItem(key: string, value: string): void | Promise<void>;\r\n removeItem(key: string): void | Promise<void>;\r\n}\r\n\r\n/** Options for {@link StealthSession}. */\r\nexport interface StealthSessionOpts {\r\n /** The backing key/value store (e.g. `window.localStorage`). */\r\n storage: KVStorage;\r\n /** Storage-key namespace prefix. Default `'stealth'`. */\r\n namespace?: string;\r\n}\r\n\r\n/** Cached scan progress so returning users neither re-key nor rescan from zero. */\r\nexport interface ScanState {\r\n /** Per-method resume cursor. */\r\n cursor: ScanCursor;\r\n /** Discovered payments so far. */\r\n payments: Payment[];\r\n /** ISO timestamp of the last update. */\r\n updatedAt: string;\r\n}\r\n\r\nconst PBKDF2_ITERATIONS = 600_000;\r\nconst SALT_BYTES = 16;\r\nconst IV_BYTES = 12;\r\n\r\ninterface Envelope {\r\n version: 2;\r\n kdf: 'pbkdf2';\r\n iterations: number;\r\n spendPublicKey: string;\r\n viewPublicKey: string;\r\n encrypted: { data: string; salt: string; iv: string };\r\n}\r\n\r\ninterface ScanEnvelope {\r\n version: 2;\r\n kdf: 'pbkdf2';\r\n iterations: number;\r\n encrypted: { data: string; salt: string; iv: string };\r\n}\r\n\r\nfunction toBase64(bytes: Uint8Array): string {\r\n let binary = '';\r\n for (const b of bytes) binary += String.fromCharCode(b);\r\n return btoa(binary);\r\n}\r\n\r\nfunction fromBase64(b64: string): Uint8Array {\r\n const binary = atob(b64);\r\n const out = new Uint8Array(binary.length);\r\n for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);\r\n return out;\r\n}\r\n\r\n/** Decode a lowercase/uppercase hex string into bytes (returns null if malformed). */\r\nfunction fromHex(hex: string): Uint8Array | null {\r\n if (typeof hex !== 'string' || hex.length % 2 !== 0 || /[^0-9a-fA-F]/.test(hex)) {\r\n return null;\r\n }\r\n const out = new Uint8Array(hex.length / 2);\r\n for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\r\n return out;\r\n}\r\n\r\n/** Constant-time-ish byte-equality (length + per-byte, no early length leak concern here). */\r\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\r\n if (a.length !== b.length) return false;\r\n let diff = 0;\r\n for (let i = 0; i < a.length; i++) diff |= (a[i] ?? 0) ^ (b[i] ?? 0);\r\n return diff === 0;\r\n}\r\n\r\n/**\r\n * Verify a stored (cleartext) public key against the public key derived from the\r\n * decrypted private scalar. Throws {@link SessionIntegrityError} on any mismatch\r\n * or malformed material so a tampered pubkey cannot silently break scanning.\r\n */\r\nfunction assertPubKeyMatchesPriv(\r\n which: 'spend' | 'view',\r\n storedPubHex: string,\r\n privHex: string,\r\n): void {\r\n const priv = fromHex(privHex);\r\n const storedPub = fromHex(storedPubHex);\r\n if (!priv || !storedPub) throw new SessionIntegrityError(which);\r\n let derived: Uint8Array;\r\n try {\r\n derived = scalarMultBase(priv);\r\n } catch {\r\n throw new SessionIntegrityError(which);\r\n }\r\n if (!bytesEqual(derived, storedPub)) throw new SessionIntegrityError(which);\r\n}\r\n\r\nconst subtle = (): SubtleCrypto => {\r\n const c = globalThis.crypto?.subtle;\r\n if (!c) {\r\n throw new Error(\r\n 'WebCrypto SubtleCrypto is unavailable — StealthSession needs a browser or Node 18+.',\r\n );\r\n }\r\n return c;\r\n};\r\n\r\nasync function deriveAesKey(\r\n password: string,\r\n salt: Uint8Array,\r\n iterations: number,\r\n): Promise<CryptoKey> {\r\n const material = await subtle().importKey(\r\n 'raw',\r\n new TextEncoder().encode(password),\r\n 'PBKDF2',\r\n false,\r\n ['deriveKey'],\r\n );\r\n return subtle().deriveKey(\r\n { name: 'PBKDF2', salt: salt as BufferSource, iterations, hash: 'SHA-256' },\r\n material,\r\n { name: 'AES-GCM', length: 256 },\r\n false,\r\n ['encrypt', 'decrypt'],\r\n );\r\n}\r\n\r\nasync function encryptJson(\r\n value: unknown,\r\n password: string,\r\n): Promise<{ data: string; salt: string; iv: string }> {\r\n const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));\r\n const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES));\r\n const key = await deriveAesKey(password, salt, PBKDF2_ITERATIONS);\r\n const plaintext = new TextEncoder().encode(JSON.stringify(value));\r\n const cipher = new Uint8Array(\r\n await subtle().encrypt(\r\n { name: 'AES-GCM', iv: iv as BufferSource },\r\n key,\r\n plaintext as BufferSource,\r\n ),\r\n );\r\n return {\r\n data: toBase64(cipher),\r\n salt: toBase64(salt),\r\n iv: toBase64(iv),\r\n };\r\n}\r\n\r\nasync function decryptJson<T>(\r\n encrypted: { data: string; salt: string; iv: string },\r\n password: string,\r\n iterations: number,\r\n): Promise<T> {\r\n const salt = fromBase64(encrypted.salt);\r\n const iv = fromBase64(encrypted.iv);\r\n const key = await deriveAesKey(password, salt, iterations);\r\n let plaintext: ArrayBuffer;\r\n try {\r\n plaintext = await subtle().decrypt(\r\n { name: 'AES-GCM', iv: iv as BufferSource },\r\n key,\r\n fromBase64(encrypted.data) as BufferSource,\r\n );\r\n } catch {\r\n throw new WrongPasswordError();\r\n }\r\n return JSON.parse(new TextDecoder().decode(plaintext)) as T;\r\n}\r\n\r\n/**\r\n * Storage-agnostic, encrypted web session for stealth keys and scan state.\r\n *\r\n * Keys and scan history are encrypted with AES-256-GCM under a PBKDF2-SHA256\r\n * (600k iterations) key derived from the user's password, using only\r\n * `globalThis.crypto.subtle` — no new dependencies, works in browsers and Node\r\n * 18+. This is intentionally separate from the CLI keystore (which stays on\r\n * Node's scrypt).\r\n *\r\n * @example\r\n * ```typescript\r\n * const session = new StealthSession({ storage: window.localStorage });\r\n * await session.saveKeys(keys, password);\r\n * // ... later / new page load ...\r\n * await session.unlock(password);\r\n * const keys = session.keys;\r\n * ```\r\n */\r\nexport class StealthSession {\r\n private readonly storage: KVStorage;\r\n private readonly namespace: string;\r\n private unlockedKeys: StealthKeys | null = null;\r\n private password: string | null = null;\r\n\r\n constructor(opts: StealthSessionOpts) {\r\n this.storage = opts.storage;\r\n this.namespace = opts.namespace ?? 'stealth';\r\n }\r\n\r\n private get keysKey(): string {\r\n return `${this.namespace}:keys`;\r\n }\r\n\r\n private get scanKey(): string {\r\n return `${this.namespace}:scan-state`;\r\n }\r\n\r\n /**\r\n * Encrypt and persist the stealth keys under the given password. The public\r\n * keys are stored in the clear (they are shareable); only the private key\r\n * material is encrypted.\r\n */\r\n async saveKeys(keys: StealthKeys, password: string): Promise<void> {\r\n const encrypted = await encryptJson(\r\n {\r\n metaAddress: keys.metaAddress,\r\n spendPrivKey: keys.spendPrivKey,\r\n viewPrivKey: keys.viewPrivKey,\r\n },\r\n password,\r\n );\r\n const envelope: Envelope = {\r\n version: 2,\r\n kdf: 'pbkdf2',\r\n iterations: PBKDF2_ITERATIONS,\r\n spendPublicKey: keys.spendPubKey,\r\n viewPublicKey: keys.viewPubKey,\r\n encrypted,\r\n };\r\n await this.storage.setItem(this.keysKey, JSON.stringify(envelope));\r\n this.unlockedKeys = keys;\r\n this.password = password;\r\n }\r\n\r\n /**\r\n * Decrypt the stored keys into memory using the password.\r\n *\r\n * @throws {WrongPasswordError} If the password fails the AES-GCM auth check.\r\n * @throws If no keys are stored.\r\n */\r\n async unlock(password: string): Promise<StealthKeys> {\r\n const raw = await this.storage.getItem(this.keysKey);\r\n if (!raw) {\r\n throw new Error('No stored keys — call saveKeys() first.');\r\n }\r\n const envelope = JSON.parse(raw) as Envelope;\r\n const secret = await decryptJson<{\r\n metaAddress: string;\r\n spendPrivKey: string;\r\n viewPrivKey: string;\r\n }>(envelope.encrypted, password, envelope.iterations);\r\n\r\n // Integrity: the private scalars are AES-GCM protected, but the cleartext\r\n // public keys are not. Re-derive both public keys from the decrypted scalars\r\n // and assert they match the stored pubkeys, so a storage-write attacker\r\n // cannot swap in a wrong pubkey and silently break scanning.\r\n assertPubKeyMatchesPriv('spend', envelope.spendPublicKey, secret.spendPrivKey);\r\n assertPubKeyMatchesPriv('view', envelope.viewPublicKey, secret.viewPrivKey);\r\n\r\n const keys: StealthKeys = {\r\n metaAddress: secret.metaAddress,\r\n spendPubKey: envelope.spendPublicKey,\r\n spendPrivKey: secret.spendPrivKey,\r\n viewPubKey: envelope.viewPublicKey,\r\n viewPrivKey: secret.viewPrivKey,\r\n };\r\n this.unlockedKeys = keys;\r\n this.password = password;\r\n return keys;\r\n }\r\n\r\n /** The in-memory keys after {@link unlock}/{@link saveKeys}. */\r\n get keys(): StealthKeys {\r\n if (!this.unlockedKeys) {\r\n throw new Error('Session is locked — call unlock() first.');\r\n }\r\n return this.unlockedKeys;\r\n }\r\n\r\n /** Wipe in-memory key material (storage is untouched). */\r\n lock(): void {\r\n this.unlockedKeys = null;\r\n this.password = null;\r\n }\r\n\r\n /** Whether keys are present in storage (does not require unlock). */\r\n async hasKeys(): Promise<boolean> {\r\n return (await this.storage.getItem(this.keysKey)) !== null;\r\n }\r\n\r\n /** Remove all session data (keys + scan state) and lock in memory. */\r\n async clear(): Promise<void> {\r\n await this.storage.removeItem(this.keysKey);\r\n await this.storage.removeItem(this.scanKey);\r\n this.lock();\r\n }\r\n\r\n /**\r\n * Load the encrypted scan-state cache. Requires an unlocked session (the same\r\n * derived key protects it, since payment history is private). Returns null\r\n * when nothing is cached.\r\n */\r\n async loadScanState(): Promise<ScanState | null> {\r\n if (!this.password) {\r\n throw new Error('Session is locked — call unlock() before loadScanState().');\r\n }\r\n const raw = await this.storage.getItem(this.scanKey);\r\n if (!raw) return null;\r\n const envelope = JSON.parse(raw) as ScanEnvelope;\r\n return decryptJson<ScanState>(\r\n envelope.encrypted,\r\n this.password,\r\n envelope.iterations,\r\n );\r\n }\r\n\r\n /**\r\n * Encrypt and persist the scan-state cache under the session password.\r\n * Requires an unlocked session.\r\n */\r\n async saveScanState(state: ScanState): Promise<void> {\r\n if (!this.password) {\r\n throw new Error('Session is locked — call unlock() before saveScanState().');\r\n }\r\n const encrypted = await encryptJson(state, this.password);\r\n const envelope: ScanEnvelope = {\r\n version: 2,\r\n kdf: 'pbkdf2',\r\n iterations: PBKDF2_ITERATIONS,\r\n encrypted,\r\n };\r\n await this.storage.setItem(this.scanKey, JSON.stringify(envelope));\r\n }\r\n}\r\n"]}
|