@veridex/sdk 1.1.1 → 1.1.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/chains/stellar/index.ts","../../../src/chains/stellar/StellarPasskeySigner.ts","../../../src/utils.ts","../../../src/chains/stellar/types.ts","../../../src/chains/stellar/SmartAccount.ts","../../../src/chains/stellar/VeridexStellarWalletModule.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK — Stellar chain module\n *\n * Provides:\n * - `StellarPasskeySigner`: SEP-43-compatible passkey signer\n * - `VeridexStellarWalletModule`: Stellar-Wallets-Kit `ModuleInterface`\n * - `deriveSmartAccountId`: deterministic Soroban smart-account derivation\n */\n\nexport { StellarPasskeySigner } from './StellarPasskeySigner.js';\nexport type { StellarPasskeySignerOptions } from './StellarPasskeySigner.js';\n\nexport {\n VeridexStellarWalletModule,\n VERIDEX_PASSKEY_ID,\n StellarNetworks,\n} from './VeridexStellarWalletModule.js';\nexport type { VeridexStellarWalletModuleOptions } from './VeridexStellarWalletModule.js';\n\nexport { deriveSmartAccountId } from './SmartAccount.js';\n\nexport {\n StellarModuleType,\n} from './types.js';\nexport type {\n StellarWalletModuleInterface,\n StellarKitError,\n VeridexStellarConfig,\n PasskeyAuthAssertion,\n} from './types.js';\n","/**\n * Veridex Protocol SDK — Stellar Passkey Signer\n *\n * Bridges Veridex's WebAuthn `PasskeyManager` to the SEP-43 signing surface\n * expected by Soroban smart accounts (and the Stellar-Wallets-Kit\n * `ModuleInterface`).\n *\n * Design:\n * - The signer treats every SEP-43 signing call (transaction / auth entry\n * / message) as a request to produce a WebAuthn assertion over the\n * SHA-256 of a canonical preimage.\n * - For a transaction we hash `network_id || tagged_tx_envelope` per the\n * XDR-hash spec; for an auth entry we hash the\n * `HashIdPreimageSorobanAuthorization`; for a message we hash the bytes\n * directly.\n * - The returned `signedTxXdr` / `signedAuthEntry` strings are\n * base64-encoded JSON containers carrying the assertion. The downstream\n * Soroban smart-account contract (`__check_auth`) is responsible for\n * parsing the container, verifying secp256r1, and authorizing.\n *\n * This separation lets `@veridex/sdk` ship without a hard dependency on\n * `@stellar/stellar-sdk`. Consumers who want full XDR-aware signing can\n * subclass and override `hashTransactionXdr` / `hashAuthEntry`.\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport { PasskeyManager } from '../../core/PasskeyManager.js';\nimport type { PasskeyCredential } from '../../core/PasskeyManager.js';\nimport { base64URLDecode } from '../../utils.js';\nimport {\n StellarNetworks,\n type PasskeyAuthAssertion,\n type VeridexStellarConfig,\n} from './types.js';\nimport { deriveSmartAccountId } from './SmartAccount.js';\n\nexport interface StellarPasskeySignerOptions {\n passkey: PasskeyManager;\n credential?: PasskeyCredential;\n config?: VeridexStellarConfig;\n}\n\nexport class StellarPasskeySigner {\n private readonly passkey: PasskeyManager;\n private credential?: PasskeyCredential;\n private readonly network: StellarNetworks;\n private readonly smartAccountContractId?: string;\n\n constructor(opts: StellarPasskeySignerOptions) {\n this.passkey = opts.passkey;\n this.credential = opts.credential;\n this.network = opts.config?.network ?? StellarNetworks.TESTNET;\n this.smartAccountContractId = opts.config?.smartAccountContractId;\n }\n\n /**\n * Returns the Soroban smart-account address (C-address-derivable hex)\n * associated with the active passkey. If a fixed contract id was\n * configured we return it verbatim; otherwise we derive deterministically.\n */\n async getAddress(skipRequestAccess = false): Promise<{ address: string }> {\n if (this.smartAccountContractId) {\n return { address: this.smartAccountContractId };\n }\n const cred = await this.ensureCredential(skipRequestAccess);\n const id = deriveSmartAccountId(cred.keyHash, this.network);\n return { address: id };\n }\n\n /**\n * Produce a SEP-43 `signedTxXdr` for the given transaction envelope XDR.\n *\n * Because we do not bundle `@stellar/stellar-sdk` we hash the XDR's\n * binary form prefixed with the network passphrase. Consumers that need\n * canonical Stellar transaction hashes should preprocess `xdr` to the\n * spec-compliant preimage before calling, or override this method.\n */\n async signTransaction(\n xdr: string,\n opts?: { networkPassphrase?: string; address?: string },\n ): Promise<{ signedTxXdr: string; signerAddress: string }> {\n const cred = await this.ensureCredential(true);\n const passphrase = opts?.networkPassphrase ?? this.network;\n const challenge = this.hashTransactionXdr(xdr, passphrase);\n const assertion = await this.signChallenge(challenge, cred);\n const container = this.encodeAssertionContainer('tx', xdr, assertion);\n const { address } = await this.getAddress(true);\n return { signedTxXdr: container, signerAddress: opts?.address ?? address };\n }\n\n /**\n * Sign a Soroban `HashIdPreimageSorobanAuthorization` XDR. The auth\n * entry payload is hashed and wrapped identically to a transaction.\n */\n async signAuthEntry(\n authEntry: string,\n opts?: { networkPassphrase?: string; address?: string },\n ): Promise<{ signedAuthEntry: string; signerAddress: string }> {\n const cred = await this.ensureCredential(true);\n const passphrase = opts?.networkPassphrase ?? this.network;\n const challenge = this.hashAuthEntry(authEntry, passphrase);\n const assertion = await this.signChallenge(challenge, cred);\n const container = this.encodeAssertionContainer('auth', authEntry, assertion);\n const { address } = await this.getAddress(true);\n return { signedAuthEntry: container, signerAddress: opts?.address ?? address };\n }\n\n /**\n * Sign an arbitrary message per SEP-43 `signMessage`.\n */\n async signMessage(\n message: string,\n opts?: { networkPassphrase?: string; address?: string },\n ): Promise<{ signedMessage: string; signerAddress: string }> {\n const cred = await this.ensureCredential(true);\n const challenge = sha256(new TextEncoder().encode(message));\n const assertion = await this.signChallenge(challenge, cred);\n const container = this.encodeAssertionContainer('msg', message, assertion);\n const { address } = await this.getAddress(true);\n return { signedMessage: container, signerAddress: opts?.address ?? address };\n }\n\n // ------------------------------------------------------------------\n // Internals\n // ------------------------------------------------------------------\n\n protected hashTransactionXdr(xdr: string, networkPassphrase: string): Uint8Array {\n const passphraseHash = sha256(new TextEncoder().encode(networkPassphrase));\n const xdrBytes = this.decodeBase64(xdr);\n const buf = new Uint8Array(passphraseHash.length + xdrBytes.length);\n buf.set(passphraseHash, 0);\n buf.set(xdrBytes, passphraseHash.length);\n return sha256(buf);\n }\n\n protected hashAuthEntry(authEntry: string, networkPassphrase: string): Uint8Array {\n return this.hashTransactionXdr(authEntry, networkPassphrase);\n }\n\n private async signChallenge(\n challenge: Uint8Array,\n credential: PasskeyCredential,\n ): Promise<PasskeyAuthAssertion> {\n const sig = await this.passkey.sign(challenge);\n return {\n keyHash: credential.keyHash,\n authenticatorData: sig.authenticatorData,\n clientDataJSON: sig.clientDataJSON,\n challengeIndex: sig.challengeIndex,\n typeIndex: sig.typeIndex,\n signatureR: '0x' + sig.r.toString(16).padStart(64, '0'),\n signatureS: '0x' + sig.s.toString(16).padStart(64, '0'),\n };\n }\n\n private async ensureCredential(skipRequestAccess: boolean): Promise<PasskeyCredential> {\n if (this.credential) return this.credential;\n if (skipRequestAccess) {\n throw new Error(\n 'StellarPasskeySigner: no credential cached. Call passkey.authenticate() ' +\n 'first or pass `credential` to the constructor.',\n );\n }\n const { credential } = await this.passkey.authenticate();\n this.credential = credential;\n return credential;\n }\n\n private encodeAssertionContainer(\n kind: 'tx' | 'auth' | 'msg',\n payload: string,\n assertion: PasskeyAuthAssertion,\n ): string {\n const container = {\n v: 1,\n kind,\n payload,\n assertion,\n };\n const json = JSON.stringify(container);\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(json, 'utf8').toString('base64');\n }\n // Browser fallback.\n return btoa(unescape(encodeURIComponent(json)));\n }\n\n private decodeBase64(input: string): Uint8Array {\n try {\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(input, 'base64'));\n }\n const binary = atob(input);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n // Fall back to base64url if standard base64 fails.\n return base64URLDecode(input);\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Utility Functions\n */\n\nimport { ethers } from 'ethers';\nimport type { ChainConfig } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from './constants.js';\n\n// ============================================================================\n// Base64URL Encoding/Decoding (WebAuthn compatible)\n// ============================================================================\n\n/**\n * Base64URL encode a buffer\n */\nexport function base64URLEncode(buffer: Uint8Array): string {\n // Convert Uint8Array to base64 using browser APIs\n const bytes = Array.from(buffer);\n const binary = String.fromCharCode(...bytes);\n const base64 = btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Base64URL decode a string\n */\nexport function base64URLDecode(str: string): Uint8Array {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Use browser's atob for base64 decoding\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ============================================================================\n// Signature Utilities\n// ============================================================================\n\n/**\n * Parse DER-encoded ECDSA signature to r and s values\n */\nexport function parseDERSignature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {\n let offset = 0;\n\n if (signature[offset++] !== 0x30) {\n throw new Error('Invalid signature format');\n }\n\n // Skip total length\n offset++;\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const rLength = signature[offset++];\n if (rLength === undefined) {\n throw new Error('Invalid signature format: missing r length');\n }\n let r = signature.slice(offset, offset + rLength);\n offset += rLength;\n\n // Remove leading zero if present (for positive number representation)\n if (r[0] === 0x00 && r.length > 32) {\n r = r.slice(1);\n }\n // Pad to 32 bytes if needed\n if (r.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(r, 32 - r.length);\n r = padded;\n }\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const sLength = signature[offset++];\n if (sLength === undefined) {\n throw new Error('Invalid signature format: missing s length');\n }\n let s = signature.slice(offset, offset + sLength);\n\n // Remove leading zero if present\n if (s[0] === 0x00 && s.length > 32) {\n s = s.slice(1);\n }\n // Pad to 32 bytes if needed\n if (s.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(s, 32 - s.length);\n s = padded;\n }\n\n return { r, s };\n}\n\n/**\n * Encode signature for Solidity verification\n */\nexport function encodeSignatureForSolidity(r: bigint, s: bigint): string {\n return ethers.solidityPacked(['uint256', 'uint256'], [r, s]);\n}\n\n// ============================================================================\n// Key Hash Utilities\n// ============================================================================\n\n/**\n * Compute key hash from public key coordinates\n */\nexport function computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n return ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n}\n\n// ============================================================================\n// Chain Utilities\n// ============================================================================\n\n/**\n * Get chain config by name\n */\nexport function getChainConfig(chainName: string, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return chains[chainName];\n}\n\n/**\n * Get chain config by Wormhole chain ID\n */\nexport function getChainByWormholeId(wormholeChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.wormholeChainId === wormholeChainId);\n}\n\n/**\n * Get chain config by EVM chain ID\n */\nexport function getChainByEvmId(evmChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.chainId === evmChainId);\n}\n\n/**\n * Check if a chain is EVM-compatible\n */\nexport function isEvmChain(wormholeChainId: number): boolean {\n // Non-EVM chains\n const nonEvmChains = new Set([1, 8, 15, 21, 22]); // Solana, Algorand, NEAR, Sui, Aptos\n return !nonEvmChains.has(wormholeChainId);\n}\n\n/**\n * Get all supported chains\n */\nexport function getSupportedChains(testnet = true): ChainConfig[] {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains);\n}\n\n// ============================================================================\n// Explorer URL Utilities\n// ============================================================================\n\n/**\n * Get transaction explorer URL\n */\nexport function getTxExplorerUrl(chain: ChainConfig, txHash: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n\n // Non-EVM chains have different URL patterns\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/tx/${txHash}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/txn/${txHash}?network=testnet`;\n default:\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n}\n\n/**\n * Get address explorer URL\n */\nexport function getAddressExplorerUrl(chain: ChainConfig, address: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/address/${address}`;\n }\n\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/address/${address}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/account/${address}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/account/${address}?network=testnet`;\n default:\n return `${chain.explorerUrl}/address/${address}`;\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validate an EVM address\n */\nexport function isValidEvmAddress(address: string): boolean {\n return ethers.isAddress(address);\n}\n\n/**\n * Validate a bytes32 hex string\n */\nexport function isValidBytes32(hex: string): boolean {\n const clean = hex.replace('0x', '');\n return /^[0-9a-fA-F]{64}$/.test(clean);\n}\n\n/**\n * Validate a Wormhole chain ID\n */\nexport function isValidWormholeChainId(chainId: number): boolean {\n // Valid Wormhole chain IDs range from 1 to ~10007 (testnets)\n return chainId >= 1 && chainId <= 50000;\n}\n\n// ============================================================================\n// Retry Utilities\n// ============================================================================\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n onRetry?: (attempt: number, error: Error) => void;\n } = {}\n): Promise<T> {\n const {\n maxRetries = 5,\n initialDelayMs = 1000,\n maxDelayMs = 30000,\n backoffMultiplier = 2,\n onRetry,\n } = options;\n\n let lastError: Error | undefined;\n let delay = initialDelayMs;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt < maxRetries) {\n onRetry?.(attempt, lastError);\n await sleep(delay);\n delay = Math.min(delay * backoffMultiplier, maxDelayMs);\n }\n }\n }\n\n throw lastError ?? new Error('Retry failed');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","/**\n * Veridex Protocol SDK — Stellar chain types\n *\n * Local mirror of the subset of the Stellar-Wallets-Kit `ModuleInterface`\n * contract we implement. We mirror it (rather than importing from\n * `@creit.tech/stellar-wallets-kit`) so `@veridex/sdk` does not gain a hard\n * peer dependency on the kit. Consumers who already depend on the kit can\n * cast our module to the upstream type — the shapes are structurally\n * identical.\n *\n * Upstream reference: `@creit.tech/stellar-wallets-kit` →\n * src/types/mod.ts → `ModuleInterface`\n */\n\nexport enum StellarNetworks {\n PUBLIC = 'Public Global Stellar Network ; September 2015',\n TESTNET = 'Test SDF Network ; September 2015',\n FUTURENET = 'Test SDF Future Network ; October 2022',\n SANDBOX = 'Local Sandbox Stellar Network ; September 2022',\n STANDALONE = 'Standalone Network ; February 2017',\n}\n\nexport enum StellarModuleType {\n HW_WALLET = 'HW_WALLET',\n HOT_WALLET = 'HOT_WALLET',\n BRIDGE_WALLET = 'BRIDGE_WALLET',\n AIR_GAPED_WALLET = 'AIR_GAPED_WALLET',\n}\n\nexport interface StellarKitError {\n code: number;\n message: string;\n ext?: string;\n}\n\n/**\n * Stellar-Wallets-Kit `ModuleInterface` mirror.\n * Only the methods we implement are documented; signature-compatible with\n * the upstream contract.\n */\nexport interface StellarWalletModuleInterface {\n moduleType: StellarModuleType;\n productId: string;\n productName: string;\n productUrl: string;\n productIcon: string;\n\n isAvailable(): Promise<boolean>;\n isPlatformWrapper?(): Promise<boolean>;\n\n getAddress(params?: {\n path?: string;\n skipRequestAccess?: boolean;\n }): Promise<{ address: string }>;\n\n signTransaction(\n xdr: string,\n opts?: {\n networkPassphrase?: string;\n address?: string;\n path?: string;\n },\n ): Promise<{ signedTxXdr: string; signerAddress?: string }>;\n\n signAuthEntry(\n authEntry: string,\n opts?: {\n networkPassphrase?: string;\n address?: string;\n path?: string;\n },\n ): Promise<{ signedAuthEntry: string; signerAddress?: string }>;\n\n signMessage(\n message: string,\n opts?: {\n networkPassphrase?: string;\n address?: string;\n path?: string;\n },\n ): Promise<{ signedMessage: string; signerAddress?: string }>;\n}\n\n/**\n * Veridex-specific configuration for the Stellar passkey signer.\n */\nexport interface VeridexStellarConfig {\n /** Stellar network passphrase. Defaults to TESTNET. */\n network?: StellarNetworks;\n /**\n * Soroban RPC URL (used to resolve the smart-account address or submit\n * transactions when `signAndSubmitTransaction` is invoked).\n */\n rpcUrl?: string;\n /**\n * Optional pre-deployed smart-account contract id (C-address). If\n * provided, `getAddress()` returns this directly. Otherwise the address\n * is derived deterministically from the passkey `keyHash`.\n */\n smartAccountContractId?: string;\n /**\n * Override the deterministic smart-account factory contract. Used for\n * address derivation when `smartAccountContractId` is not set.\n */\n smartAccountFactory?: string;\n}\n\n/**\n * A signed WebAuthn assertion ready to be embedded in a Soroban auth entry.\n *\n * The shape matches what a Soroban smart-account's `__check_auth` entrypoint\n * needs to verify a secp256r1 passkey signature:\n * - `keyHash` identifies which registered passkey signed\n * - `authenticatorData` + `clientDataJSON` are the WebAuthn assertion\n * - `r`, `s` are the secp256r1 signature components\n */\nexport interface PasskeyAuthAssertion {\n keyHash: string;\n authenticatorData: string;\n clientDataJSON: string;\n challengeIndex: number;\n typeIndex: number;\n signatureR: string;\n signatureS: string;\n}\n","/**\n * Veridex Protocol SDK — Soroban smart-account address derivation\n *\n * The Veridex Stellar adapter binds a WebAuthn passkey to a Soroban smart\n * account whose `__check_auth` entry verifies secp256r1 signatures against\n * the passkey's `keyHash`.\n *\n * For the credibility-artifact stage we expose deterministic address\n * derivation only — actual deployment is handled by a separate Soroban\n * factory contract (see `contracts/stellar/` once added). This keeps the\n * SDK chain-agnostic and avoids pulling in the heavy `@stellar/stellar-sdk`\n * runtime.\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\n\n/**\n * Deterministically derive a Soroban contract id (C-address) from a passkey\n * `keyHash`. This mirrors the SEP-0011 Stellar contract-id derivation\n * scheme: contract_id = sha256(networkPassphrase || keyHash || salt).\n *\n * NOTE: This returns a stable 32-byte identifier encoded as hex. To produce\n * a canonical `C...` strkey representation the consumer must encode it with\n * `StrKey.encodeContract` from `@stellar/stellar-sdk`. We deliberately keep\n * the encoding out of `@veridex/sdk` to avoid a hard dependency.\n *\n * @param keyHash - The Veridex passkey keyHash (hex, with or without 0x).\n * @param networkPassphrase - Stellar network passphrase (e.g. testnet).\n * @param salt - Optional 32-byte salt (hex). Defaults to all-zeros.\n * @returns The 32-byte contract id encoded as a 0x-prefixed hex string.\n */\nexport function deriveSmartAccountId(\n keyHash: string,\n networkPassphrase: string,\n salt?: string,\n): string {\n const cleanHash = keyHash.startsWith('0x') ? keyHash.slice(2) : keyHash;\n if (cleanHash.length !== 64) {\n throw new Error(\n `deriveSmartAccountId: keyHash must be 32 bytes (64 hex chars), got ${cleanHash.length}`,\n );\n }\n\n const cleanSalt = salt\n ? (salt.startsWith('0x') ? salt.slice(2) : salt)\n : '0'.repeat(64);\n if (cleanSalt.length !== 64) {\n throw new Error(\n `deriveSmartAccountId: salt must be 32 bytes (64 hex chars), got ${cleanSalt.length}`,\n );\n }\n\n const encoder = new TextEncoder();\n const passphraseBytes = encoder.encode(networkPassphrase);\n const keyHashBytes = hexToBytes(cleanHash);\n const saltBytes = hexToBytes(cleanSalt);\n\n const buffer = new Uint8Array(\n passphraseBytes.length + keyHashBytes.length + saltBytes.length,\n );\n buffer.set(passphraseBytes, 0);\n buffer.set(keyHashBytes, passphraseBytes.length);\n buffer.set(saltBytes, passphraseBytes.length + keyHashBytes.length);\n\n const digest = sha256(buffer);\n return '0x' + bytesToHex(digest);\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const out = new Uint8Array(hex.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += bytes[i].toString(16).padStart(2, '0');\n }\n return hex;\n}\n","/**\n * Veridex Protocol SDK — Stellar-Wallets-Kit ModuleInterface implementation\n *\n * Drop-in module for `@creit.tech/stellar-wallets-kit` that exposes\n * Veridex's passkey-backed Soroban smart account as a wallet option.\n *\n * Usage (downstream app):\n * ```ts\n * import { StellarWalletsKit, allowAllModules } from '@creit.tech/stellar-wallets-kit';\n * import { PasskeyManager } from '@veridex/sdk/passkey';\n * import { VeridexStellarWalletModule } from '@veridex/sdk/chains/stellar';\n *\n * const passkey = new PasskeyManager({ rpName: 'My Dapp' });\n * const veridexModule = new VeridexStellarWalletModule({ passkey });\n *\n * const kit = new StellarWalletsKit({\n * network: WalletNetwork.TESTNET,\n * selectedWalletId: VERIDEX_PASSKEY_ID,\n * modules: [...allowAllModules(), veridexModule],\n * });\n * ```\n */\n\nimport { browserSupportsWebAuthn } from '@simplewebauthn/browser';\nimport { PasskeyManager } from '../../core/PasskeyManager.js';\nimport type { PasskeyCredential } from '../../core/PasskeyManager.js';\nimport { StellarPasskeySigner } from './StellarPasskeySigner.js';\nimport {\n StellarModuleType,\n StellarNetworks,\n type StellarWalletModuleInterface,\n type VeridexStellarConfig,\n} from './types.js';\n\nexport const VERIDEX_PASSKEY_ID = 'veridex-passkey';\n\nexport interface VeridexStellarWalletModuleOptions {\n passkey: PasskeyManager;\n credential?: PasskeyCredential;\n config?: VeridexStellarConfig;\n productName?: string;\n productUrl?: string;\n productIcon?: string;\n}\n\nexport class VeridexStellarWalletModule implements StellarWalletModuleInterface {\n readonly moduleType: StellarModuleType = StellarModuleType.HOT_WALLET;\n readonly productId: string = VERIDEX_PASSKEY_ID;\n readonly productName: string;\n readonly productUrl: string;\n readonly productIcon: string;\n\n private readonly signer: StellarPasskeySigner;\n\n constructor(opts: VeridexStellarWalletModuleOptions) {\n this.signer = new StellarPasskeySigner({\n passkey: opts.passkey,\n credential: opts.credential,\n config: opts.config,\n });\n this.productName = opts.productName ?? 'Veridex Passkey';\n this.productUrl = opts.productUrl ?? 'https://veridex.network';\n this.productIcon =\n opts.productIcon ??\n 'https://veridex.network/icons/passkey-256.png';\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n return browserSupportsWebAuthn();\n } catch {\n return false;\n }\n }\n\n async isPlatformWrapper(): Promise<boolean> {\n return false;\n }\n\n async getAddress(params?: {\n path?: string;\n skipRequestAccess?: boolean;\n }): Promise<{ address: string }> {\n return this.signer.getAddress(params?.skipRequestAccess);\n }\n\n async signTransaction(\n xdr: string,\n opts?: { networkPassphrase?: string; address?: string; path?: string },\n ): Promise<{ signedTxXdr: string; signerAddress?: string }> {\n return this.signer.signTransaction(xdr, {\n networkPassphrase: opts?.networkPassphrase,\n address: opts?.address,\n });\n }\n\n async signAuthEntry(\n authEntry: string,\n opts?: { networkPassphrase?: string; address?: string; path?: string },\n ): Promise<{ signedAuthEntry: string; signerAddress?: string }> {\n return this.signer.signAuthEntry(authEntry, {\n networkPassphrase: opts?.networkPassphrase,\n address: opts?.address,\n });\n }\n\n async signMessage(\n message: string,\n opts?: { networkPassphrase?: string; address?: string; path?: string },\n ): Promise<{ signedMessage: string; signerAddress?: string }> {\n return this.signer.signMessage(message, {\n networkPassphrase: opts?.networkPassphrase,\n address: opts?.address,\n });\n }\n}\n\nexport { StellarNetworks };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACyBA,IAAAA,iBAAuB;;;ACrBvB,oBAAuB;AAsBhB,SAAS,gBAAgB,KAAyB;AACvD,QAAM,SAAS,IAAI,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACvD,QAAM,SAAS,SAAS,IAAI,QAAQ,IAAK,OAAO,SAAS,KAAM,CAAC;AAEhE,QAAM,SAAS,KAAK,MAAM;AAC1B,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,SAAO;AACT;;;ACtBO,IAAK,kBAAL,kBAAKC,qBAAL;AACH,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,aAAU;AACV,EAAAA,iBAAA,eAAY;AACZ,EAAAA,iBAAA,aAAU;AACV,EAAAA,iBAAA,gBAAa;AALL,SAAAA;AAAA,GAAA;AAQL,IAAK,oBAAL,kBAAKC,uBAAL;AACH,EAAAA,mBAAA,eAAY;AACZ,EAAAA,mBAAA,gBAAa;AACb,EAAAA,mBAAA,mBAAgB;AAChB,EAAAA,mBAAA,sBAAmB;AAJX,SAAAA;AAAA,GAAA;;;ACRZ,oBAAuB;AAiBhB,SAAS,qBACZ,SACA,mBACA,MACM;AACN,QAAM,YAAY,QAAQ,WAAW,IAAI,IAAI,QAAQ,MAAM,CAAC,IAAI;AAChE,MAAI,UAAU,WAAW,IAAI;AACzB,UAAM,IAAI;AAAA,MACN,sEAAsE,UAAU,MAAM;AAAA,IAC1F;AAAA,EACJ;AAEA,QAAM,YAAY,OACX,KAAK,WAAW,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI,OACzC,IAAI,OAAO,EAAE;AACnB,MAAI,UAAU,WAAW,IAAI;AACzB,UAAM,IAAI;AAAA,MACN,mEAAmE,UAAU,MAAM;AAAA,IACvF;AAAA,EACJ;AAEA,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,kBAAkB,QAAQ,OAAO,iBAAiB;AACxD,QAAM,eAAe,WAAW,SAAS;AACzC,QAAM,YAAY,WAAW,SAAS;AAEtC,QAAM,SAAS,IAAI;AAAA,IACf,gBAAgB,SAAS,aAAa,SAAS,UAAU;AAAA,EAC7D;AACA,SAAO,IAAI,iBAAiB,CAAC;AAC7B,SAAO,IAAI,cAAc,gBAAgB,MAAM;AAC/C,SAAO,IAAI,WAAW,gBAAgB,SAAS,aAAa,MAAM;AAElE,QAAM,aAAS,sBAAO,MAAM;AAC5B,SAAO,OAAO,WAAW,MAAM;AACnC;AAEA,SAAS,WAAW,KAAyB;AACzC,QAAM,MAAM,IAAI,WAAW,IAAI,SAAS,CAAC;AACzC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACjC,QAAI,CAAC,IAAI,SAAS,IAAI,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE;AAAA,EACrD;AACA,SAAO;AACX;AAEA,SAAS,WAAW,OAA2B;AAC3C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,WAAO,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAAA,EAChD;AACA,SAAO;AACX;;;AHxCO,IAAM,uBAAN,MAA2B;AAAA,EACb;AAAA,EACT;AAAA,EACS;AAAA,EACA;AAAA,EAEjB,YAAY,MAAmC;AAC3C,SAAK,UAAU,KAAK;AACpB,SAAK,aAAa,KAAK;AACvB,SAAK,UAAU,KAAK,QAAQ;AAC5B,SAAK,yBAAyB,KAAK,QAAQ;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,oBAAoB,OAAqC;AACtE,QAAI,KAAK,wBAAwB;AAC7B,aAAO,EAAE,SAAS,KAAK,uBAAuB;AAAA,IAClD;AACA,UAAM,OAAO,MAAM,KAAK,iBAAiB,iBAAiB;AAC1D,UAAM,KAAK,qBAAqB,KAAK,SAAS,KAAK,OAAO;AAC1D,WAAO,EAAE,SAAS,GAAG;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACF,KACA,MACuD;AACvD,UAAM,OAAO,MAAM,KAAK,iBAAiB,IAAI;AAC7C,UAAM,aAAa,MAAM,qBAAqB,KAAK;AACnD,UAAM,YAAY,KAAK,mBAAmB,KAAK,UAAU;AACzD,UAAM,YAAY,MAAM,KAAK,cAAc,WAAW,IAAI;AAC1D,UAAM,YAAY,KAAK,yBAAyB,MAAM,KAAK,SAAS;AACpE,UAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,WAAW,IAAI;AAC9C,WAAO,EAAE,aAAa,WAAW,eAAe,MAAM,WAAW,QAAQ;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cACF,WACA,MAC2D;AAC3D,UAAM,OAAO,MAAM,KAAK,iBAAiB,IAAI;AAC7C,UAAM,aAAa,MAAM,qBAAqB,KAAK;AACnD,UAAM,YAAY,KAAK,cAAc,WAAW,UAAU;AAC1D,UAAM,YAAY,MAAM,KAAK,cAAc,WAAW,IAAI;AAC1D,UAAM,YAAY,KAAK,yBAAyB,QAAQ,WAAW,SAAS;AAC5E,UAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,WAAW,IAAI;AAC9C,WAAO,EAAE,iBAAiB,WAAW,eAAe,MAAM,WAAW,QAAQ;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACF,SACA,MACyD;AACzD,UAAM,OAAO,MAAM,KAAK,iBAAiB,IAAI;AAC7C,UAAM,gBAAY,uBAAO,IAAI,YAAY,EAAE,OAAO,OAAO,CAAC;AAC1D,UAAM,YAAY,MAAM,KAAK,cAAc,WAAW,IAAI;AAC1D,UAAM,YAAY,KAAK,yBAAyB,OAAO,SAAS,SAAS;AACzE,UAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,WAAW,IAAI;AAC9C,WAAO,EAAE,eAAe,WAAW,eAAe,MAAM,WAAW,QAAQ;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA,EAMU,mBAAmB,KAAa,mBAAuC;AAC7E,UAAM,qBAAiB,uBAAO,IAAI,YAAY,EAAE,OAAO,iBAAiB,CAAC;AACzE,UAAM,WAAW,KAAK,aAAa,GAAG;AACtC,UAAM,MAAM,IAAI,WAAW,eAAe,SAAS,SAAS,MAAM;AAClE,QAAI,IAAI,gBAAgB,CAAC;AACzB,QAAI,IAAI,UAAU,eAAe,MAAM;AACvC,eAAO,uBAAO,GAAG;AAAA,EACrB;AAAA,EAEU,cAAc,WAAmB,mBAAuC;AAC9E,WAAO,KAAK,mBAAmB,WAAW,iBAAiB;AAAA,EAC/D;AAAA,EAEA,MAAc,cACV,WACA,YAC6B;AAC7B,UAAM,MAAM,MAAM,KAAK,QAAQ,KAAK,SAAS;AAC7C,WAAO;AAAA,MACH,SAAS,WAAW;AAAA,MACpB,mBAAmB,IAAI;AAAA,MACvB,gBAAgB,IAAI;AAAA,MACpB,gBAAgB,IAAI;AAAA,MACpB,WAAW,IAAI;AAAA,MACf,YAAY,OAAO,IAAI,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACtD,YAAY,OAAO,IAAI,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,IAC1D;AAAA,EACJ;AAAA,EAEA,MAAc,iBAAiB,mBAAwD;AACnF,QAAI,KAAK,WAAY,QAAO,KAAK;AACjC,QAAI,mBAAmB;AACnB,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AACA,UAAM,EAAE,WAAW,IAAI,MAAM,KAAK,QAAQ,aAAa;AACvD,SAAK,aAAa;AAClB,WAAO;AAAA,EACX;AAAA,EAEQ,yBACJ,MACA,SACA,WACM;AACN,UAAM,YAAY;AAAA,MACd,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AACA,UAAM,OAAO,KAAK,UAAU,SAAS;AACrC,QAAI,OAAO,WAAW,aAAa;AAC/B,aAAO,OAAO,KAAK,MAAM,MAAM,EAAE,SAAS,QAAQ;AAAA,IACtD;AAEA,WAAO,KAAK,SAAS,mBAAmB,IAAI,CAAC,CAAC;AAAA,EAClD;AAAA,EAEQ,aAAa,OAA2B;AAC5C,QAAI;AACA,UAAI,OAAO,WAAW,aAAa;AAC/B,eAAO,IAAI,WAAW,OAAO,KAAK,OAAO,QAAQ,CAAC;AAAA,MACtD;AACA,YAAM,SAAS,KAAK,KAAK;AACzB,YAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAK,OAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AACtE,aAAO;AAAA,IACX,QAAQ;AAEJ,aAAO,gBAAgB,KAAK;AAAA,IAChC;AAAA,EACJ;AACJ;;;AIlLA,qBAAwC;AAWjC,IAAM,qBAAqB;AAW3B,IAAM,6BAAN,MAAyE;AAAA,EACnE;AAAA,EACA,YAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EAEQ;AAAA,EAEjB,YAAY,MAAyC;AACjD,SAAK,SAAS,IAAI,qBAAqB;AAAA,MACnC,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACjB,CAAC;AACD,SAAK,cAAc,KAAK,eAAe;AACvC,SAAK,aAAa,KAAK,cAAc;AACrC,SAAK,cACD,KAAK,eACL;AAAA,EACR;AAAA,EAEA,MAAM,cAAgC;AAClC,QAAI;AACA,iBAAO,wCAAwB;AAAA,IACnC,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAsC;AACxC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,WAAW,QAGgB;AAC7B,WAAO,KAAK,OAAO,WAAW,QAAQ,iBAAiB;AAAA,EAC3D;AAAA,EAEA,MAAM,gBACF,KACA,MACwD;AACxD,WAAO,KAAK,OAAO,gBAAgB,KAAK;AAAA,MACpC,mBAAmB,MAAM;AAAA,MACzB,SAAS,MAAM;AAAA,IACnB,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,cACF,WACA,MAC4D;AAC5D,WAAO,KAAK,OAAO,cAAc,WAAW;AAAA,MACxC,mBAAmB,MAAM;AAAA,MACzB,SAAS,MAAM;AAAA,IACnB,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,YACF,SACA,MAC0D;AAC1D,WAAO,KAAK,OAAO,YAAY,SAAS;AAAA,MACpC,mBAAmB,MAAM;AAAA,MACzB,SAAS,MAAM;AAAA,IACnB,CAAC;AAAA,EACL;AACJ;","names":["import_sha256","StellarNetworks","StellarModuleType"]}
@@ -0,0 +1,260 @@
1
+ import {
2
+ base64URLDecode
3
+ } from "../../chunk-EFIXFA6V.mjs";
4
+ import "../../chunk-RD6ZYUVG.mjs";
5
+
6
+ // src/chains/stellar/StellarPasskeySigner.ts
7
+ import { sha256 as sha2562 } from "@noble/hashes/sha256";
8
+
9
+ // src/chains/stellar/types.ts
10
+ var StellarNetworks = /* @__PURE__ */ ((StellarNetworks2) => {
11
+ StellarNetworks2["PUBLIC"] = "Public Global Stellar Network ; September 2015";
12
+ StellarNetworks2["TESTNET"] = "Test SDF Network ; September 2015";
13
+ StellarNetworks2["FUTURENET"] = "Test SDF Future Network ; October 2022";
14
+ StellarNetworks2["SANDBOX"] = "Local Sandbox Stellar Network ; September 2022";
15
+ StellarNetworks2["STANDALONE"] = "Standalone Network ; February 2017";
16
+ return StellarNetworks2;
17
+ })(StellarNetworks || {});
18
+ var StellarModuleType = /* @__PURE__ */ ((StellarModuleType2) => {
19
+ StellarModuleType2["HW_WALLET"] = "HW_WALLET";
20
+ StellarModuleType2["HOT_WALLET"] = "HOT_WALLET";
21
+ StellarModuleType2["BRIDGE_WALLET"] = "BRIDGE_WALLET";
22
+ StellarModuleType2["AIR_GAPED_WALLET"] = "AIR_GAPED_WALLET";
23
+ return StellarModuleType2;
24
+ })(StellarModuleType || {});
25
+
26
+ // src/chains/stellar/SmartAccount.ts
27
+ import { sha256 } from "@noble/hashes/sha256";
28
+ function deriveSmartAccountId(keyHash, networkPassphrase, salt) {
29
+ const cleanHash = keyHash.startsWith("0x") ? keyHash.slice(2) : keyHash;
30
+ if (cleanHash.length !== 64) {
31
+ throw new Error(
32
+ `deriveSmartAccountId: keyHash must be 32 bytes (64 hex chars), got ${cleanHash.length}`
33
+ );
34
+ }
35
+ const cleanSalt = salt ? salt.startsWith("0x") ? salt.slice(2) : salt : "0".repeat(64);
36
+ if (cleanSalt.length !== 64) {
37
+ throw new Error(
38
+ `deriveSmartAccountId: salt must be 32 bytes (64 hex chars), got ${cleanSalt.length}`
39
+ );
40
+ }
41
+ const encoder = new TextEncoder();
42
+ const passphraseBytes = encoder.encode(networkPassphrase);
43
+ const keyHashBytes = hexToBytes(cleanHash);
44
+ const saltBytes = hexToBytes(cleanSalt);
45
+ const buffer = new Uint8Array(
46
+ passphraseBytes.length + keyHashBytes.length + saltBytes.length
47
+ );
48
+ buffer.set(passphraseBytes, 0);
49
+ buffer.set(keyHashBytes, passphraseBytes.length);
50
+ buffer.set(saltBytes, passphraseBytes.length + keyHashBytes.length);
51
+ const digest = sha256(buffer);
52
+ return "0x" + bytesToHex(digest);
53
+ }
54
+ function hexToBytes(hex) {
55
+ const out = new Uint8Array(hex.length / 2);
56
+ for (let i = 0; i < out.length; i++) {
57
+ out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
58
+ }
59
+ return out;
60
+ }
61
+ function bytesToHex(bytes) {
62
+ let hex = "";
63
+ for (let i = 0; i < bytes.length; i++) {
64
+ hex += bytes[i].toString(16).padStart(2, "0");
65
+ }
66
+ return hex;
67
+ }
68
+
69
+ // src/chains/stellar/StellarPasskeySigner.ts
70
+ var StellarPasskeySigner = class {
71
+ passkey;
72
+ credential;
73
+ network;
74
+ smartAccountContractId;
75
+ constructor(opts) {
76
+ this.passkey = opts.passkey;
77
+ this.credential = opts.credential;
78
+ this.network = opts.config?.network ?? "Test SDF Network ; September 2015" /* TESTNET */;
79
+ this.smartAccountContractId = opts.config?.smartAccountContractId;
80
+ }
81
+ /**
82
+ * Returns the Soroban smart-account address (C-address-derivable hex)
83
+ * associated with the active passkey. If a fixed contract id was
84
+ * configured we return it verbatim; otherwise we derive deterministically.
85
+ */
86
+ async getAddress(skipRequestAccess = false) {
87
+ if (this.smartAccountContractId) {
88
+ return { address: this.smartAccountContractId };
89
+ }
90
+ const cred = await this.ensureCredential(skipRequestAccess);
91
+ const id = deriveSmartAccountId(cred.keyHash, this.network);
92
+ return { address: id };
93
+ }
94
+ /**
95
+ * Produce a SEP-43 `signedTxXdr` for the given transaction envelope XDR.
96
+ *
97
+ * Because we do not bundle `@stellar/stellar-sdk` we hash the XDR's
98
+ * binary form prefixed with the network passphrase. Consumers that need
99
+ * canonical Stellar transaction hashes should preprocess `xdr` to the
100
+ * spec-compliant preimage before calling, or override this method.
101
+ */
102
+ async signTransaction(xdr, opts) {
103
+ const cred = await this.ensureCredential(true);
104
+ const passphrase = opts?.networkPassphrase ?? this.network;
105
+ const challenge = this.hashTransactionXdr(xdr, passphrase);
106
+ const assertion = await this.signChallenge(challenge, cred);
107
+ const container = this.encodeAssertionContainer("tx", xdr, assertion);
108
+ const { address } = await this.getAddress(true);
109
+ return { signedTxXdr: container, signerAddress: opts?.address ?? address };
110
+ }
111
+ /**
112
+ * Sign a Soroban `HashIdPreimageSorobanAuthorization` XDR. The auth
113
+ * entry payload is hashed and wrapped identically to a transaction.
114
+ */
115
+ async signAuthEntry(authEntry, opts) {
116
+ const cred = await this.ensureCredential(true);
117
+ const passphrase = opts?.networkPassphrase ?? this.network;
118
+ const challenge = this.hashAuthEntry(authEntry, passphrase);
119
+ const assertion = await this.signChallenge(challenge, cred);
120
+ const container = this.encodeAssertionContainer("auth", authEntry, assertion);
121
+ const { address } = await this.getAddress(true);
122
+ return { signedAuthEntry: container, signerAddress: opts?.address ?? address };
123
+ }
124
+ /**
125
+ * Sign an arbitrary message per SEP-43 `signMessage`.
126
+ */
127
+ async signMessage(message, opts) {
128
+ const cred = await this.ensureCredential(true);
129
+ const challenge = sha2562(new TextEncoder().encode(message));
130
+ const assertion = await this.signChallenge(challenge, cred);
131
+ const container = this.encodeAssertionContainer("msg", message, assertion);
132
+ const { address } = await this.getAddress(true);
133
+ return { signedMessage: container, signerAddress: opts?.address ?? address };
134
+ }
135
+ // ------------------------------------------------------------------
136
+ // Internals
137
+ // ------------------------------------------------------------------
138
+ hashTransactionXdr(xdr, networkPassphrase) {
139
+ const passphraseHash = sha2562(new TextEncoder().encode(networkPassphrase));
140
+ const xdrBytes = this.decodeBase64(xdr);
141
+ const buf = new Uint8Array(passphraseHash.length + xdrBytes.length);
142
+ buf.set(passphraseHash, 0);
143
+ buf.set(xdrBytes, passphraseHash.length);
144
+ return sha2562(buf);
145
+ }
146
+ hashAuthEntry(authEntry, networkPassphrase) {
147
+ return this.hashTransactionXdr(authEntry, networkPassphrase);
148
+ }
149
+ async signChallenge(challenge, credential) {
150
+ const sig = await this.passkey.sign(challenge);
151
+ return {
152
+ keyHash: credential.keyHash,
153
+ authenticatorData: sig.authenticatorData,
154
+ clientDataJSON: sig.clientDataJSON,
155
+ challengeIndex: sig.challengeIndex,
156
+ typeIndex: sig.typeIndex,
157
+ signatureR: "0x" + sig.r.toString(16).padStart(64, "0"),
158
+ signatureS: "0x" + sig.s.toString(16).padStart(64, "0")
159
+ };
160
+ }
161
+ async ensureCredential(skipRequestAccess) {
162
+ if (this.credential) return this.credential;
163
+ if (skipRequestAccess) {
164
+ throw new Error(
165
+ "StellarPasskeySigner: no credential cached. Call passkey.authenticate() first or pass `credential` to the constructor."
166
+ );
167
+ }
168
+ const { credential } = await this.passkey.authenticate();
169
+ this.credential = credential;
170
+ return credential;
171
+ }
172
+ encodeAssertionContainer(kind, payload, assertion) {
173
+ const container = {
174
+ v: 1,
175
+ kind,
176
+ payload,
177
+ assertion
178
+ };
179
+ const json = JSON.stringify(container);
180
+ if (typeof Buffer !== "undefined") {
181
+ return Buffer.from(json, "utf8").toString("base64");
182
+ }
183
+ return btoa(unescape(encodeURIComponent(json)));
184
+ }
185
+ decodeBase64(input) {
186
+ try {
187
+ if (typeof Buffer !== "undefined") {
188
+ return new Uint8Array(Buffer.from(input, "base64"));
189
+ }
190
+ const binary = atob(input);
191
+ const bytes = new Uint8Array(binary.length);
192
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
193
+ return bytes;
194
+ } catch {
195
+ return base64URLDecode(input);
196
+ }
197
+ }
198
+ };
199
+
200
+ // src/chains/stellar/VeridexStellarWalletModule.ts
201
+ import { browserSupportsWebAuthn } from "@simplewebauthn/browser";
202
+ var VERIDEX_PASSKEY_ID = "veridex-passkey";
203
+ var VeridexStellarWalletModule = class {
204
+ moduleType = "HOT_WALLET" /* HOT_WALLET */;
205
+ productId = VERIDEX_PASSKEY_ID;
206
+ productName;
207
+ productUrl;
208
+ productIcon;
209
+ signer;
210
+ constructor(opts) {
211
+ this.signer = new StellarPasskeySigner({
212
+ passkey: opts.passkey,
213
+ credential: opts.credential,
214
+ config: opts.config
215
+ });
216
+ this.productName = opts.productName ?? "Veridex Passkey";
217
+ this.productUrl = opts.productUrl ?? "https://veridex.network";
218
+ this.productIcon = opts.productIcon ?? "https://veridex.network/icons/passkey-256.png";
219
+ }
220
+ async isAvailable() {
221
+ try {
222
+ return browserSupportsWebAuthn();
223
+ } catch {
224
+ return false;
225
+ }
226
+ }
227
+ async isPlatformWrapper() {
228
+ return false;
229
+ }
230
+ async getAddress(params) {
231
+ return this.signer.getAddress(params?.skipRequestAccess);
232
+ }
233
+ async signTransaction(xdr, opts) {
234
+ return this.signer.signTransaction(xdr, {
235
+ networkPassphrase: opts?.networkPassphrase,
236
+ address: opts?.address
237
+ });
238
+ }
239
+ async signAuthEntry(authEntry, opts) {
240
+ return this.signer.signAuthEntry(authEntry, {
241
+ networkPassphrase: opts?.networkPassphrase,
242
+ address: opts?.address
243
+ });
244
+ }
245
+ async signMessage(message, opts) {
246
+ return this.signer.signMessage(message, {
247
+ networkPassphrase: opts?.networkPassphrase,
248
+ address: opts?.address
249
+ });
250
+ }
251
+ };
252
+ export {
253
+ StellarModuleType,
254
+ StellarNetworks,
255
+ StellarPasskeySigner,
256
+ VERIDEX_PASSKEY_ID,
257
+ VeridexStellarWalletModule,
258
+ deriveSmartAccountId
259
+ };
260
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/chains/stellar/StellarPasskeySigner.ts","../../../src/chains/stellar/types.ts","../../../src/chains/stellar/SmartAccount.ts","../../../src/chains/stellar/VeridexStellarWalletModule.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK — Stellar Passkey Signer\n *\n * Bridges Veridex's WebAuthn `PasskeyManager` to the SEP-43 signing surface\n * expected by Soroban smart accounts (and the Stellar-Wallets-Kit\n * `ModuleInterface`).\n *\n * Design:\n * - The signer treats every SEP-43 signing call (transaction / auth entry\n * / message) as a request to produce a WebAuthn assertion over the\n * SHA-256 of a canonical preimage.\n * - For a transaction we hash `network_id || tagged_tx_envelope` per the\n * XDR-hash spec; for an auth entry we hash the\n * `HashIdPreimageSorobanAuthorization`; for a message we hash the bytes\n * directly.\n * - The returned `signedTxXdr` / `signedAuthEntry` strings are\n * base64-encoded JSON containers carrying the assertion. The downstream\n * Soroban smart-account contract (`__check_auth`) is responsible for\n * parsing the container, verifying secp256r1, and authorizing.\n *\n * This separation lets `@veridex/sdk` ship without a hard dependency on\n * `@stellar/stellar-sdk`. Consumers who want full XDR-aware signing can\n * subclass and override `hashTransactionXdr` / `hashAuthEntry`.\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport { PasskeyManager } from '../../core/PasskeyManager.js';\nimport type { PasskeyCredential } from '../../core/PasskeyManager.js';\nimport { base64URLDecode } from '../../utils.js';\nimport {\n StellarNetworks,\n type PasskeyAuthAssertion,\n type VeridexStellarConfig,\n} from './types.js';\nimport { deriveSmartAccountId } from './SmartAccount.js';\n\nexport interface StellarPasskeySignerOptions {\n passkey: PasskeyManager;\n credential?: PasskeyCredential;\n config?: VeridexStellarConfig;\n}\n\nexport class StellarPasskeySigner {\n private readonly passkey: PasskeyManager;\n private credential?: PasskeyCredential;\n private readonly network: StellarNetworks;\n private readonly smartAccountContractId?: string;\n\n constructor(opts: StellarPasskeySignerOptions) {\n this.passkey = opts.passkey;\n this.credential = opts.credential;\n this.network = opts.config?.network ?? StellarNetworks.TESTNET;\n this.smartAccountContractId = opts.config?.smartAccountContractId;\n }\n\n /**\n * Returns the Soroban smart-account address (C-address-derivable hex)\n * associated with the active passkey. If a fixed contract id was\n * configured we return it verbatim; otherwise we derive deterministically.\n */\n async getAddress(skipRequestAccess = false): Promise<{ address: string }> {\n if (this.smartAccountContractId) {\n return { address: this.smartAccountContractId };\n }\n const cred = await this.ensureCredential(skipRequestAccess);\n const id = deriveSmartAccountId(cred.keyHash, this.network);\n return { address: id };\n }\n\n /**\n * Produce a SEP-43 `signedTxXdr` for the given transaction envelope XDR.\n *\n * Because we do not bundle `@stellar/stellar-sdk` we hash the XDR's\n * binary form prefixed with the network passphrase. Consumers that need\n * canonical Stellar transaction hashes should preprocess `xdr` to the\n * spec-compliant preimage before calling, or override this method.\n */\n async signTransaction(\n xdr: string,\n opts?: { networkPassphrase?: string; address?: string },\n ): Promise<{ signedTxXdr: string; signerAddress: string }> {\n const cred = await this.ensureCredential(true);\n const passphrase = opts?.networkPassphrase ?? this.network;\n const challenge = this.hashTransactionXdr(xdr, passphrase);\n const assertion = await this.signChallenge(challenge, cred);\n const container = this.encodeAssertionContainer('tx', xdr, assertion);\n const { address } = await this.getAddress(true);\n return { signedTxXdr: container, signerAddress: opts?.address ?? address };\n }\n\n /**\n * Sign a Soroban `HashIdPreimageSorobanAuthorization` XDR. The auth\n * entry payload is hashed and wrapped identically to a transaction.\n */\n async signAuthEntry(\n authEntry: string,\n opts?: { networkPassphrase?: string; address?: string },\n ): Promise<{ signedAuthEntry: string; signerAddress: string }> {\n const cred = await this.ensureCredential(true);\n const passphrase = opts?.networkPassphrase ?? this.network;\n const challenge = this.hashAuthEntry(authEntry, passphrase);\n const assertion = await this.signChallenge(challenge, cred);\n const container = this.encodeAssertionContainer('auth', authEntry, assertion);\n const { address } = await this.getAddress(true);\n return { signedAuthEntry: container, signerAddress: opts?.address ?? address };\n }\n\n /**\n * Sign an arbitrary message per SEP-43 `signMessage`.\n */\n async signMessage(\n message: string,\n opts?: { networkPassphrase?: string; address?: string },\n ): Promise<{ signedMessage: string; signerAddress: string }> {\n const cred = await this.ensureCredential(true);\n const challenge = sha256(new TextEncoder().encode(message));\n const assertion = await this.signChallenge(challenge, cred);\n const container = this.encodeAssertionContainer('msg', message, assertion);\n const { address } = await this.getAddress(true);\n return { signedMessage: container, signerAddress: opts?.address ?? address };\n }\n\n // ------------------------------------------------------------------\n // Internals\n // ------------------------------------------------------------------\n\n protected hashTransactionXdr(xdr: string, networkPassphrase: string): Uint8Array {\n const passphraseHash = sha256(new TextEncoder().encode(networkPassphrase));\n const xdrBytes = this.decodeBase64(xdr);\n const buf = new Uint8Array(passphraseHash.length + xdrBytes.length);\n buf.set(passphraseHash, 0);\n buf.set(xdrBytes, passphraseHash.length);\n return sha256(buf);\n }\n\n protected hashAuthEntry(authEntry: string, networkPassphrase: string): Uint8Array {\n return this.hashTransactionXdr(authEntry, networkPassphrase);\n }\n\n private async signChallenge(\n challenge: Uint8Array,\n credential: PasskeyCredential,\n ): Promise<PasskeyAuthAssertion> {\n const sig = await this.passkey.sign(challenge);\n return {\n keyHash: credential.keyHash,\n authenticatorData: sig.authenticatorData,\n clientDataJSON: sig.clientDataJSON,\n challengeIndex: sig.challengeIndex,\n typeIndex: sig.typeIndex,\n signatureR: '0x' + sig.r.toString(16).padStart(64, '0'),\n signatureS: '0x' + sig.s.toString(16).padStart(64, '0'),\n };\n }\n\n private async ensureCredential(skipRequestAccess: boolean): Promise<PasskeyCredential> {\n if (this.credential) return this.credential;\n if (skipRequestAccess) {\n throw new Error(\n 'StellarPasskeySigner: no credential cached. Call passkey.authenticate() ' +\n 'first or pass `credential` to the constructor.',\n );\n }\n const { credential } = await this.passkey.authenticate();\n this.credential = credential;\n return credential;\n }\n\n private encodeAssertionContainer(\n kind: 'tx' | 'auth' | 'msg',\n payload: string,\n assertion: PasskeyAuthAssertion,\n ): string {\n const container = {\n v: 1,\n kind,\n payload,\n assertion,\n };\n const json = JSON.stringify(container);\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(json, 'utf8').toString('base64');\n }\n // Browser fallback.\n return btoa(unescape(encodeURIComponent(json)));\n }\n\n private decodeBase64(input: string): Uint8Array {\n try {\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(input, 'base64'));\n }\n const binary = atob(input);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n // Fall back to base64url if standard base64 fails.\n return base64URLDecode(input);\n }\n }\n}\n","/**\n * Veridex Protocol SDK — Stellar chain types\n *\n * Local mirror of the subset of the Stellar-Wallets-Kit `ModuleInterface`\n * contract we implement. We mirror it (rather than importing from\n * `@creit.tech/stellar-wallets-kit`) so `@veridex/sdk` does not gain a hard\n * peer dependency on the kit. Consumers who already depend on the kit can\n * cast our module to the upstream type — the shapes are structurally\n * identical.\n *\n * Upstream reference: `@creit.tech/stellar-wallets-kit` →\n * src/types/mod.ts → `ModuleInterface`\n */\n\nexport enum StellarNetworks {\n PUBLIC = 'Public Global Stellar Network ; September 2015',\n TESTNET = 'Test SDF Network ; September 2015',\n FUTURENET = 'Test SDF Future Network ; October 2022',\n SANDBOX = 'Local Sandbox Stellar Network ; September 2022',\n STANDALONE = 'Standalone Network ; February 2017',\n}\n\nexport enum StellarModuleType {\n HW_WALLET = 'HW_WALLET',\n HOT_WALLET = 'HOT_WALLET',\n BRIDGE_WALLET = 'BRIDGE_WALLET',\n AIR_GAPED_WALLET = 'AIR_GAPED_WALLET',\n}\n\nexport interface StellarKitError {\n code: number;\n message: string;\n ext?: string;\n}\n\n/**\n * Stellar-Wallets-Kit `ModuleInterface` mirror.\n * Only the methods we implement are documented; signature-compatible with\n * the upstream contract.\n */\nexport interface StellarWalletModuleInterface {\n moduleType: StellarModuleType;\n productId: string;\n productName: string;\n productUrl: string;\n productIcon: string;\n\n isAvailable(): Promise<boolean>;\n isPlatformWrapper?(): Promise<boolean>;\n\n getAddress(params?: {\n path?: string;\n skipRequestAccess?: boolean;\n }): Promise<{ address: string }>;\n\n signTransaction(\n xdr: string,\n opts?: {\n networkPassphrase?: string;\n address?: string;\n path?: string;\n },\n ): Promise<{ signedTxXdr: string; signerAddress?: string }>;\n\n signAuthEntry(\n authEntry: string,\n opts?: {\n networkPassphrase?: string;\n address?: string;\n path?: string;\n },\n ): Promise<{ signedAuthEntry: string; signerAddress?: string }>;\n\n signMessage(\n message: string,\n opts?: {\n networkPassphrase?: string;\n address?: string;\n path?: string;\n },\n ): Promise<{ signedMessage: string; signerAddress?: string }>;\n}\n\n/**\n * Veridex-specific configuration for the Stellar passkey signer.\n */\nexport interface VeridexStellarConfig {\n /** Stellar network passphrase. Defaults to TESTNET. */\n network?: StellarNetworks;\n /**\n * Soroban RPC URL (used to resolve the smart-account address or submit\n * transactions when `signAndSubmitTransaction` is invoked).\n */\n rpcUrl?: string;\n /**\n * Optional pre-deployed smart-account contract id (C-address). If\n * provided, `getAddress()` returns this directly. Otherwise the address\n * is derived deterministically from the passkey `keyHash`.\n */\n smartAccountContractId?: string;\n /**\n * Override the deterministic smart-account factory contract. Used for\n * address derivation when `smartAccountContractId` is not set.\n */\n smartAccountFactory?: string;\n}\n\n/**\n * A signed WebAuthn assertion ready to be embedded in a Soroban auth entry.\n *\n * The shape matches what a Soroban smart-account's `__check_auth` entrypoint\n * needs to verify a secp256r1 passkey signature:\n * - `keyHash` identifies which registered passkey signed\n * - `authenticatorData` + `clientDataJSON` are the WebAuthn assertion\n * - `r`, `s` are the secp256r1 signature components\n */\nexport interface PasskeyAuthAssertion {\n keyHash: string;\n authenticatorData: string;\n clientDataJSON: string;\n challengeIndex: number;\n typeIndex: number;\n signatureR: string;\n signatureS: string;\n}\n","/**\n * Veridex Protocol SDK — Soroban smart-account address derivation\n *\n * The Veridex Stellar adapter binds a WebAuthn passkey to a Soroban smart\n * account whose `__check_auth` entry verifies secp256r1 signatures against\n * the passkey's `keyHash`.\n *\n * For the credibility-artifact stage we expose deterministic address\n * derivation only — actual deployment is handled by a separate Soroban\n * factory contract (see `contracts/stellar/` once added). This keeps the\n * SDK chain-agnostic and avoids pulling in the heavy `@stellar/stellar-sdk`\n * runtime.\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\n\n/**\n * Deterministically derive a Soroban contract id (C-address) from a passkey\n * `keyHash`. This mirrors the SEP-0011 Stellar contract-id derivation\n * scheme: contract_id = sha256(networkPassphrase || keyHash || salt).\n *\n * NOTE: This returns a stable 32-byte identifier encoded as hex. To produce\n * a canonical `C...` strkey representation the consumer must encode it with\n * `StrKey.encodeContract` from `@stellar/stellar-sdk`. We deliberately keep\n * the encoding out of `@veridex/sdk` to avoid a hard dependency.\n *\n * @param keyHash - The Veridex passkey keyHash (hex, with or without 0x).\n * @param networkPassphrase - Stellar network passphrase (e.g. testnet).\n * @param salt - Optional 32-byte salt (hex). Defaults to all-zeros.\n * @returns The 32-byte contract id encoded as a 0x-prefixed hex string.\n */\nexport function deriveSmartAccountId(\n keyHash: string,\n networkPassphrase: string,\n salt?: string,\n): string {\n const cleanHash = keyHash.startsWith('0x') ? keyHash.slice(2) : keyHash;\n if (cleanHash.length !== 64) {\n throw new Error(\n `deriveSmartAccountId: keyHash must be 32 bytes (64 hex chars), got ${cleanHash.length}`,\n );\n }\n\n const cleanSalt = salt\n ? (salt.startsWith('0x') ? salt.slice(2) : salt)\n : '0'.repeat(64);\n if (cleanSalt.length !== 64) {\n throw new Error(\n `deriveSmartAccountId: salt must be 32 bytes (64 hex chars), got ${cleanSalt.length}`,\n );\n }\n\n const encoder = new TextEncoder();\n const passphraseBytes = encoder.encode(networkPassphrase);\n const keyHashBytes = hexToBytes(cleanHash);\n const saltBytes = hexToBytes(cleanSalt);\n\n const buffer = new Uint8Array(\n passphraseBytes.length + keyHashBytes.length + saltBytes.length,\n );\n buffer.set(passphraseBytes, 0);\n buffer.set(keyHashBytes, passphraseBytes.length);\n buffer.set(saltBytes, passphraseBytes.length + keyHashBytes.length);\n\n const digest = sha256(buffer);\n return '0x' + bytesToHex(digest);\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const out = new Uint8Array(hex.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += bytes[i].toString(16).padStart(2, '0');\n }\n return hex;\n}\n","/**\n * Veridex Protocol SDK — Stellar-Wallets-Kit ModuleInterface implementation\n *\n * Drop-in module for `@creit.tech/stellar-wallets-kit` that exposes\n * Veridex's passkey-backed Soroban smart account as a wallet option.\n *\n * Usage (downstream app):\n * ```ts\n * import { StellarWalletsKit, allowAllModules } from '@creit.tech/stellar-wallets-kit';\n * import { PasskeyManager } from '@veridex/sdk/passkey';\n * import { VeridexStellarWalletModule } from '@veridex/sdk/chains/stellar';\n *\n * const passkey = new PasskeyManager({ rpName: 'My Dapp' });\n * const veridexModule = new VeridexStellarWalletModule({ passkey });\n *\n * const kit = new StellarWalletsKit({\n * network: WalletNetwork.TESTNET,\n * selectedWalletId: VERIDEX_PASSKEY_ID,\n * modules: [...allowAllModules(), veridexModule],\n * });\n * ```\n */\n\nimport { browserSupportsWebAuthn } from '@simplewebauthn/browser';\nimport { PasskeyManager } from '../../core/PasskeyManager.js';\nimport type { PasskeyCredential } from '../../core/PasskeyManager.js';\nimport { StellarPasskeySigner } from './StellarPasskeySigner.js';\nimport {\n StellarModuleType,\n StellarNetworks,\n type StellarWalletModuleInterface,\n type VeridexStellarConfig,\n} from './types.js';\n\nexport const VERIDEX_PASSKEY_ID = 'veridex-passkey';\n\nexport interface VeridexStellarWalletModuleOptions {\n passkey: PasskeyManager;\n credential?: PasskeyCredential;\n config?: VeridexStellarConfig;\n productName?: string;\n productUrl?: string;\n productIcon?: string;\n}\n\nexport class VeridexStellarWalletModule implements StellarWalletModuleInterface {\n readonly moduleType: StellarModuleType = StellarModuleType.HOT_WALLET;\n readonly productId: string = VERIDEX_PASSKEY_ID;\n readonly productName: string;\n readonly productUrl: string;\n readonly productIcon: string;\n\n private readonly signer: StellarPasskeySigner;\n\n constructor(opts: VeridexStellarWalletModuleOptions) {\n this.signer = new StellarPasskeySigner({\n passkey: opts.passkey,\n credential: opts.credential,\n config: opts.config,\n });\n this.productName = opts.productName ?? 'Veridex Passkey';\n this.productUrl = opts.productUrl ?? 'https://veridex.network';\n this.productIcon =\n opts.productIcon ??\n 'https://veridex.network/icons/passkey-256.png';\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n return browserSupportsWebAuthn();\n } catch {\n return false;\n }\n }\n\n async isPlatformWrapper(): Promise<boolean> {\n return false;\n }\n\n async getAddress(params?: {\n path?: string;\n skipRequestAccess?: boolean;\n }): Promise<{ address: string }> {\n return this.signer.getAddress(params?.skipRequestAccess);\n }\n\n async signTransaction(\n xdr: string,\n opts?: { networkPassphrase?: string; address?: string; path?: string },\n ): Promise<{ signedTxXdr: string; signerAddress?: string }> {\n return this.signer.signTransaction(xdr, {\n networkPassphrase: opts?.networkPassphrase,\n address: opts?.address,\n });\n }\n\n async signAuthEntry(\n authEntry: string,\n opts?: { networkPassphrase?: string; address?: string; path?: string },\n ): Promise<{ signedAuthEntry: string; signerAddress?: string }> {\n return this.signer.signAuthEntry(authEntry, {\n networkPassphrase: opts?.networkPassphrase,\n address: opts?.address,\n });\n }\n\n async signMessage(\n message: string,\n opts?: { networkPassphrase?: string; address?: string; path?: string },\n ): Promise<{ signedMessage: string; signerAddress?: string }> {\n return this.signer.signMessage(message, {\n networkPassphrase: opts?.networkPassphrase,\n address: opts?.address,\n });\n }\n}\n\nexport { StellarNetworks };\n"],"mappings":"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","names":["sha256","StellarNetworks","StellarModuleType","sha256"]}
@@ -1,5 +1,5 @@
1
1
  import { SuiClient as SuiClient$1 } from '@mysten/sui/client';
2
- import { a as SessionKey } from '../../types-DWx-5jmz.mjs';
2
+ import { a as SessionKey } from '../../types-C564CfsE.mjs';
3
3
  import { C as ChainClient, a as ChainConfig, T as TransferParams, E as ExecuteParams, B as BridgeParams, W as WebAuthnSignature, D as DispatchResult, V as VaultCreationResult, x as RegisterSessionParams, y as RevokeSessionParams, S as SessionValidationResult } from '../../types-DP2CQT8p.mjs';
4
4
 
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  EVMClient
3
- } from "./chunk-YBN2VC6E.mjs";
3
+ } from "./chunk-DZUNCSI5.mjs";
4
4
 
5
5
  // src/chains/avalanche/AvalancheClient.ts
6
6
  import { ethers } from "ethers";
@@ -213,4 +213,4 @@ var AvalancheClient = class extends EVMClient {
213
213
  export {
214
214
  AvalancheClient
215
215
  };
216
- //# sourceMappingURL=chunk-PEGOXMBU.mjs.map
216
+ //# sourceMappingURL=chunk-AFHWA4CZ.mjs.map
@@ -20,7 +20,9 @@ var ERC20_ABI = [
20
20
  var HUB_ABI = [
21
21
  "function dispatch(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) signature, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) payable returns (uint64 sequence)",
22
22
  "function userNonces(bytes32 userKeyHash) view returns (uint256)",
23
- "function getMessageFee() view returns (uint256)",
23
+ // Hub exposes the Wormhole core bridge address; message fee is read from the
24
+ // bridge directly (getMessageFee() was removed from the Hub).
25
+ "function wormhole() view returns (address)",
24
26
  "function getVaultAddress(bytes32 userKeyHash) view returns (address)",
25
27
  "function vaultExists(bytes32 userKeyHash) view returns (bool)",
26
28
  "function createVault(bytes32 userKeyHash) returns (address)",
@@ -77,6 +79,8 @@ var EVMClient = class {
77
79
  hubContract;
78
80
  factoryContract = null;
79
81
  cachedImplementation = null;
82
+ cachedWormholeAddress = null;
83
+ cachedMessageFee = null;
80
84
  constructor(config) {
81
85
  this.config = {
82
86
  name: config.name ?? `EVM Chain ${config.chainId}`,
@@ -249,8 +253,24 @@ var EVMClient = class {
249
253
  return Number(count);
250
254
  }
251
255
  async getMessageFee() {
252
- const fee = await this.hubContract.getMessageFee();
253
- return BigInt(fee.toString());
256
+ const now = Date.now();
257
+ if (this.cachedMessageFee && this.cachedMessageFee.expiresAt > now) {
258
+ return this.cachedMessageFee.value;
259
+ }
260
+ let wormholeAddress = this.config.contracts.wormholeCoreBridge ?? this.cachedWormholeAddress;
261
+ if (!wormholeAddress) {
262
+ wormholeAddress = await this.hubContract.wormhole();
263
+ this.cachedWormholeAddress = wormholeAddress;
264
+ }
265
+ const wormhole = new ethers.Contract(
266
+ wormholeAddress,
267
+ ["function messageFee() view returns (uint256)"],
268
+ this.provider
269
+ );
270
+ const fee = await wormhole.messageFee();
271
+ const value = BigInt(fee.toString());
272
+ this.cachedMessageFee = { value, expiresAt: now + 3e4 };
273
+ return value;
254
274
  }
255
275
  async buildTransferPayload(params) {
256
276
  return encodeTransferAction(
@@ -349,13 +369,41 @@ var EVMClient = class {
349
369
  actionPayload,
350
370
  nonce: Number(nonce)
351
371
  };
352
- const response = await fetch(`${relayerUrl}/api/v1/submit`, {
353
- method: "POST",
354
- headers: {
355
- "Content-Type": "application/json"
356
- },
357
- body: JSON.stringify(request)
358
- });
372
+ const MAX_ATTEMPTS = 3;
373
+ const baseDelayMs = 1e3;
374
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
375
+ let response;
376
+ let lastError;
377
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
378
+ try {
379
+ response = await fetch(`${relayerUrl}/api/v1/submit`, {
380
+ method: "POST",
381
+ headers: {
382
+ "Content-Type": "application/json"
383
+ },
384
+ body: JSON.stringify(request)
385
+ });
386
+ const retryable = response.status >= 500 || response.status === 408 || response.status === 429;
387
+ if (!retryable) {
388
+ break;
389
+ }
390
+ if (attempt === MAX_ATTEMPTS) break;
391
+ const retryAfter = response.headers.get("retry-after");
392
+ const explicitDelay = retryAfter ? parseInt(retryAfter, 10) * 1e3 : 0;
393
+ const backoff = explicitDelay > 0 ? explicitDelay : baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 200);
394
+ await sleep(backoff);
395
+ } catch (err) {
396
+ lastError = err;
397
+ if (attempt === MAX_ATTEMPTS) break;
398
+ const backoff = baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 200);
399
+ await sleep(backoff);
400
+ }
401
+ }
402
+ if (!response) {
403
+ throw new Error(
404
+ `Relayer submission failed after ${MAX_ATTEMPTS} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`
405
+ );
406
+ }
359
407
  if (!response.ok) {
360
408
  const error = await response.json().catch(() => ({ error: response.statusText }));
361
409
  throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);
@@ -1186,7 +1234,7 @@ var EVMClient = class {
1186
1234
  async executeTransactionProposal(proposalId, signer) {
1187
1235
  const s = signer;
1188
1236
  const hub = this.hubContract.connect(s);
1189
- const fee = await this.hubContract.getMessageFee();
1237
+ const fee = await this.getMessageFee();
1190
1238
  const tx = await hub.executeTransactionProposal(proposalId, { value: fee });
1191
1239
  const receipt = await tx.wait();
1192
1240
  const sequence = this._extractSequenceFromReceipt(receipt);
@@ -1246,4 +1294,4 @@ var EVMClient = class {
1246
1294
  export {
1247
1295
  EVMClient
1248
1296
  };
1249
- //# sourceMappingURL=chunk-YBN2VC6E.mjs.map
1297
+ //# sourceMappingURL=chunk-DZUNCSI5.mjs.map