@buildonspark/spark-sdk 0.1.25 → 0.1.26

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/spark-wallet.ts","../src/graphql/client.ts","../src/graphql/mutations/CompleteCoopExit.ts","../src/graphql/mutations/CompleteLeavesSwap.ts","../src/graphql/mutations/GetChallenge.ts","../src/graphql/mutations/RequestCoopExit.ts","../src/graphql/mutations/RequestLightningReceive.ts","../src/graphql/mutations/RequestLightningSend.ts","../src/graphql/mutations/RequestSwapLeaves.ts","../src/graphql/mutations/VerifyChallenge.ts","../src/graphql/queries/CoopExitFeeEstimate.ts","../src/graphql/queries/LeavesSwapFeeEstimate.ts","../src/graphql/queries/LightningSendFeeEstimate.ts","../src/graphql/queries/UserRequest.ts","../src/services/coop-exit.ts","../src/services/transfer.ts","../src/services/lightning.ts","../src/services/tree-creation.ts","../src/tests/utils/test-faucet.ts"],"sourcesContent":["import { createLrc20ConnectionManager } from \"@buildonspark/lrc20-sdk/grpc\";\nimport { ILrc20ConnectionManager } from \"@buildonspark/lrc20-sdk/grpc/types\";\nimport { isNode, mapCurrencyAmount } from \"@lightsparkdev/core\";\nimport {\n bytesToHex,\n bytesToNumberBE,\n equalBytes,\n hexToBytes,\n} from \"@noble/curves/abstract/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { validateMnemonic } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english\";\nimport { Address, OutScript, Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport { Mutex } from \"async-mutex\";\nimport { decode } from \"light-bolt11-decoder\";\nimport { uuidv7 } from \"uuidv7\";\nimport {\n ConfigurationError,\n NetworkError,\n RPCError,\n ValidationError,\n} from \"./errors/types.js\";\n\nimport SspClient from \"./graphql/client.js\";\nimport {\n BitcoinNetwork,\n CoopExitFeeEstimatesOutput,\n CoopExitRequest,\n ExitSpeed,\n LeavesSwapFeeEstimateOutput,\n LeavesSwapRequest,\n LightningReceiveRequest,\n LightningSendFeeEstimateInput,\n LightningSendRequest,\n UserLeafInput,\n} from \"./graphql/objects/index.js\";\nimport {\n DepositAddressQueryResult,\n OutputWithPreviousTransactionData,\n QueryTransfersResponse,\n SubscribeToEventsResponse,\n TokenTransactionWithStatus,\n Transfer,\n TransferStatus,\n TransferType,\n TreeNode,\n} from \"./proto/spark.js\";\nimport { WalletConfigService } from \"./services/config.js\";\nimport { ConnectionManager } from \"./services/connection.js\";\nimport { CoopExitService } from \"./services/coop-exit.js\";\nimport { DepositService } from \"./services/deposit.js\";\nimport { LightningService } from \"./services/lightning.js\";\nimport { TokenTransactionService } from \"./services/token-transactions.js\";\nimport { LeafKeyTweak, TransferService } from \"./services/transfer.js\";\nimport {\n DepositAddressTree,\n TreeCreationService,\n} from \"./services/tree-creation.js\";\nimport {\n ConfigOptions,\n ELECTRS_CREDENTIALS,\n} from \"./services/wallet-config.js\";\nimport {\n applyAdaptorToSignature,\n generateAdaptorFromSignature,\n generateSignatureFromExistingAdaptor,\n} from \"./utils/adaptor-signature.js\";\nimport {\n computeTaprootKeyNoScript,\n getP2WPKHAddressFromPublicKey,\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxFromRawTxHex,\n getTxId,\n} from \"./utils/bitcoin.js\";\nimport {\n getNetwork,\n LRC_WALLET_NETWORK,\n LRC_WALLET_NETWORK_TYPE,\n Network,\n} from \"./utils/network.js\";\nimport {\n calculateAvailableTokenAmount,\n checkIfSelectedOutputsAreAvailable,\n} from \"./utils/token-transactions.js\";\nimport { getNextTransactionSequence } from \"./utils/transaction.js\";\n\nimport { LRCWallet } from \"@buildonspark/lrc20-sdk\";\nimport { EventEmitter } from \"eventemitter3\";\nimport {\n decodeSparkAddress,\n encodeSparkAddress,\n SparkAddressFormat,\n} from \"./address/index.js\";\nimport { isReactNative } from \"./constants.js\";\nimport { SparkSigner } from \"./signer/signer.js\";\nimport { BitcoinFaucet } from \"./tests/utils/test-faucet.js\";\nimport {\n mapTransferToWalletTransfer,\n mapTreeNodeToWalletLeaf,\n WalletLeaf,\n WalletTransfer,\n} from \"./types/sdk-types.js\";\nimport { getCrypto } from \"./utils/crypto.js\";\nimport { getMasterHDKeyFromSeed } from \"./utils/index.js\";\nimport type { Tracer } from \"@opentelemetry/api\";\n\nconst crypto = getCrypto();\n\nexport type CreateLightningInvoiceParams = {\n amountSats: number;\n memo?: string;\n expirySeconds?: number;\n};\n\nexport type PayLightningInvoiceParams = {\n invoice: string;\n maxFeeSats: number;\n};\n\nexport type TransferParams = {\n amountSats: number;\n receiverSparkAddress: string;\n};\n\ntype DepositParams = {\n signingPubKey: Uint8Array;\n verifyingKey: Uint8Array;\n depositTx: Transaction;\n vout: number;\n};\n\nexport type TokenInfo = {\n tokenPublicKey: string;\n tokenName: string;\n tokenSymbol: string;\n tokenDecimals: number;\n maxSupply: bigint;\n};\n\nexport type InitWalletResponse = {\n mnemonic?: string | undefined;\n};\nexport interface SparkWalletProps {\n mnemonicOrSeed?: Uint8Array | string;\n accountNumber?: number;\n signer?: SparkSigner;\n options?: ConfigOptions;\n}\n\nexport interface SparkWalletEvents {\n /** Emitted when an incoming transfer is successfully claimed. Includes the transfer ID and new total balance. */\n \"transfer:claimed\": (transferId: string, updatedBalance: number) => void;\n /** Emitted when a deposit is marked as available. Includes the deposit ID and new total balance. */\n \"deposit:confirmed\": (depositId: string, updatedBalance: number) => void;\n /** Emitted when the stream is connected */\n \"stream:connected\": () => void;\n /** Emitted when the stream disconnects and fails to reconnect after max attempts */\n \"stream:disconnected\": (reason: string) => void;\n /** Emitted when attempting to reconnect the stream */\n \"stream:reconnecting\": (\n attempt: number,\n maxAttempts: number,\n delayMs: number,\n error: string,\n ) => void;\n}\n\n/**\n * The SparkWallet class is the primary interface for interacting with the Spark network.\n * It provides methods for creating and managing wallets, handling deposits, executing transfers,\n * and interacting with the Lightning Network.\n */\nexport class SparkWallet extends EventEmitter {\n private tracer: Tracer | null = null;\n\n protected config: WalletConfigService;\n\n protected connectionManager: ConnectionManager;\n protected lrc20ConnectionManager: ILrc20ConnectionManager;\n protected lrc20Wallet: LRCWallet | undefined;\n\n private depositService: DepositService;\n protected transferService: TransferService;\n private treeCreationService: TreeCreationService;\n private lightningService: LightningService;\n private coopExitService: CoopExitService;\n private tokenTransactionService: TokenTransactionService;\n\n private claimTransferMutex = new Mutex();\n private leavesMutex = new Mutex();\n private optimizationInProgress = false;\n private sspClient: SspClient | null = null;\n\n private mutexes: Map<string, Mutex> = new Map();\n\n private pendingWithdrawnOutputIds: string[] = [];\n\n private sparkAddress: SparkAddressFormat | undefined;\n\n private streamController: AbortController | null = null;\n\n protected leaves: TreeNode[] = [];\n protected tokenOutputs: Map<string, OutputWithPreviousTransactionData[]> =\n new Map();\n\n // Add this property near the top of the class with other private properties\n private claimTransfersInterval: NodeJS.Timeout | null = null;\n\n protected wrapWithOtelSpan<T>(\n name: string,\n fn: (...args: any[]) => Promise<T>,\n ): (...args: any[]) => Promise<T> {\n return async (...args: any[]): Promise<T> => {\n if (!this.tracer) {\n throw new Error(\"Tracer not initialized\");\n }\n\n return await this.tracer.startActiveSpan(name, async (span) => {\n const traceId = span.spanContext().traceId;\n try {\n return await fn(...args);\n } catch (error) {\n if (error instanceof Error) {\n error.message += ` [traceId: ${traceId}]`;\n } else if (typeof error === \"object\" && error !== null) {\n (error as any).traceId = traceId;\n }\n throw error;\n } finally {\n span.end();\n }\n });\n };\n }\n\n protected async initializeTracer(tracerName: string) {\n const { trace, propagation, context } = await import(\"@opentelemetry/api\");\n const { W3CTraceContextPropagator } = await import(\"@opentelemetry/core\");\n const { AsyncLocalStorageContextManager } = await import(\n \"@opentelemetry/context-async-hooks\"\n );\n const { BasicTracerProvider } = await import(\n \"@opentelemetry/sdk-trace-base\"\n );\n\n trace.setGlobalTracerProvider(new BasicTracerProvider());\n propagation.setGlobalPropagator(new W3CTraceContextPropagator());\n context.setGlobalContextManager(new AsyncLocalStorageContextManager());\n\n this.tracer = trace.getTracer(tracerName);\n }\n\n private wrapSparkWalletWithTracing() {\n this.getIdentityPublicKey = this.wrapWithOtelSpan(\n \"SparkWallet.getIdentityPublicKey\",\n this.getIdentityPublicKey.bind(this),\n );\n this.getSparkAddress = this.wrapWithOtelSpan(\n \"SparkWallet.getSparkAddress\",\n this.getSparkAddress.bind(this),\n );\n this.getSwapFeeEstimate = this.wrapWithOtelSpan(\n \"SparkWallet.getSwapFeeEstimate\",\n this.getSwapFeeEstimate.bind(this),\n );\n this.getTransfers = this.wrapWithOtelSpan(\n \"SparkWallet.getTransfers\",\n this.getTransfers.bind(this),\n );\n this.getTokenInfo = this.wrapWithOtelSpan(\n \"SparkWallet.getTokenInfo\",\n this.getTokenInfo.bind(this),\n );\n this.getBalance = this.wrapWithOtelSpan(\n \"SparkWallet.getBalance\",\n this.getBalance.bind(this),\n );\n this.getSingleUseDepositAddress = this.wrapWithOtelSpan(\n \"SparkWallet.getSingleUseDepositAddress\",\n this.getSingleUseDepositAddress.bind(this),\n );\n this.getUnusedDepositAddresses = this.wrapWithOtelSpan(\n \"SparkWallet.getUnusedDepositAddresses\",\n this.getUnusedDepositAddresses.bind(this),\n );\n this.claimDeposit = this.wrapWithOtelSpan(\n \"SparkWallet.claimDeposit\",\n this.claimDeposit.bind(this),\n );\n this.advancedDeposit = this.wrapWithOtelSpan(\n \"SparkWallet.advancedDeposit\",\n this.advancedDeposit.bind(this),\n );\n this.transfer = this.wrapWithOtelSpan(\n \"SparkWallet.transfer\",\n this.transfer.bind(this),\n );\n this.createLightningInvoice = this.wrapWithOtelSpan(\n \"SparkWallet.createLightningInvoice\",\n this.createLightningInvoice.bind(this),\n );\n this.payLightningInvoice = this.wrapWithOtelSpan(\n \"SparkWallet.payLightningInvoice\",\n this.payLightningInvoice.bind(this),\n );\n this.getLightningSendFeeEstimate = this.wrapWithOtelSpan(\n \"SparkWallet.getLightningSendFeeEstimate\",\n this.getLightningSendFeeEstimate.bind(this),\n );\n this.withdraw = this.wrapWithOtelSpan(\n \"SparkWallet.withdraw\",\n this.withdraw.bind(this),\n );\n this.getWithdrawalFeeEstimate = this.wrapWithOtelSpan(\n \"SparkWallet.getWithdrawalFeeEstimate\",\n this.getWithdrawalFeeEstimate.bind(this),\n );\n }\n\n protected constructor(options?: ConfigOptions, signer?: SparkSigner) {\n super();\n\n this.config = new WalletConfigService(options, signer);\n this.connectionManager = new ConnectionManager(this.config);\n this.lrc20ConnectionManager = createLrc20ConnectionManager(\n this.config.getLrc20Address(),\n );\n this.depositService = new DepositService(\n this.config,\n this.connectionManager,\n );\n this.transferService = new TransferService(\n this.config,\n this.connectionManager,\n );\n this.treeCreationService = new TreeCreationService(\n this.config,\n this.connectionManager,\n );\n this.tokenTransactionService = new TokenTransactionService(\n this.config,\n this.connectionManager,\n );\n this.lightningService = new LightningService(\n this.config,\n this.connectionManager,\n );\n this.coopExitService = new CoopExitService(\n this.config,\n this.connectionManager,\n );\n }\n\n public static async initialize({\n mnemonicOrSeed,\n accountNumber,\n signer,\n options,\n }: SparkWalletProps) {\n const wallet = new SparkWallet(options, signer);\n const initResponse = await wallet.initWallet(mnemonicOrSeed, accountNumber);\n if (isNode) {\n await wallet.initializeTracer(\"spark-sdk\");\n wallet.wrapSparkWalletWithTracing();\n }\n return {\n wallet,\n ...initResponse,\n };\n }\n\n private async initializeWallet() {\n this.sspClient = new SspClient(this.config);\n await this.connectionManager.createClients();\n\n if (isReactNative) {\n this.startPeriodicClaimTransfers();\n } else {\n this.setupBackgroundStream();\n }\n\n await this.syncWallet();\n }\n\n private async handleStreamEvent({ event }: SubscribeToEventsResponse) {\n try {\n if (\n event?.$case === \"transfer\" &&\n event.transfer.transfer &&\n event.transfer.transfer.type !== TransferType.COUNTER_SWAP\n ) {\n const { senderIdentityPublicKey, receiverIdentityPublicKey } =\n event.transfer.transfer;\n\n // Don't claim if this is a self transfer, that's handled elsewhere\n if (\n event.transfer.transfer &&\n !equalBytes(senderIdentityPublicKey, receiverIdentityPublicKey)\n ) {\n await this.claimTransfer(event.transfer.transfer, true);\n }\n } else if (event?.$case === \"deposit\" && event.deposit.deposit) {\n const deposit = event.deposit.deposit;\n const signingKey = await this.config.signer.generatePublicKey(\n sha256(deposit.id),\n );\n\n const newLeaf = await this.transferService.extendTimelock(\n deposit,\n signingKey,\n );\n await this.transferLeavesToSelf(newLeaf.nodes, signingKey);\n this.emit(\n \"deposit:confirmed\",\n deposit.id,\n (await this.getBalance()).balance,\n );\n }\n } catch (error) {\n console.error(\"Error processing event\", error);\n }\n }\n\n protected async setupBackgroundStream() {\n const MAX_RETRIES = 10;\n const INITIAL_DELAY = 1000;\n const MAX_DELAY = 60000;\n\n this.streamController = new AbortController();\n\n const delay = (ms: number, signal?: AbortSignal): Promise<boolean> => {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n if (signal) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n resolve(true);\n }, ms);\n\n function onAbort() {\n clearTimeout(timer);\n resolve(false);\n signal?.removeEventListener(\"abort\", onAbort);\n }\n\n if (signal) {\n signal.addEventListener(\"abort\", onAbort);\n }\n });\n };\n\n let retryCount = 0;\n while (retryCount <= MAX_RETRIES) {\n try {\n const address = this.config.getCoordinatorAddress();\n\n const sparkClient =\n await this.connectionManager.createSparkStreamClient(address);\n const channel = await this.connectionManager.getStreamChannel(address);\n\n const stream = sparkClient.subscribe_to_events(\n {\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n },\n {\n signal: this.streamController?.signal,\n },\n );\n\n // In Node.js, long-lived gRPC streams keep the underlying socket \"ref'd\",\n // which prevents the process from exiting. To avoid that (e.g. in CLI tools),\n // we manually unref the socket so Node can shut down when nothing else is active.\n //\n // The gRPC client doesn’t expose the socket directly, so we dig through\n // internal fields to find it. This is a bit of a hack and may break if the\n // internals change.\n //\n // Since the socket isn’t always immediately available, we retry with setTimeout\n // until it shows up.\n const maybeUnref = () => {\n const internalChannel = (channel as any).internalChannel;\n if (\n internalChannel?.currentPicker?.subchannel?.child?.transport\n ?.session?.socket\n ) {\n internalChannel.currentPicker.subchannel.child.transport.session.socket.unref();\n } else {\n setTimeout(maybeUnref, 100);\n }\n };\n\n // Only need to unref in Node environments.\n // In the browser and React Native, the runtime handles shutdown when the tab/app closes.\n if (isNode) {\n maybeUnref();\n }\n\n const claimedTransfersIds = await this.claimTransfers();\n\n try {\n for await (const data of stream) {\n if (data.event?.$case === \"connected\") {\n console.log(\"connected\");\n this.emit(\"stream:connected\");\n retryCount = 0;\n }\n\n if (\n data.event?.$case === \"transfer\" &&\n data.event.transfer.transfer &&\n claimedTransfersIds.includes(data.event.transfer.transfer.id)\n ) {\n continue;\n }\n await this.handleStreamEvent(data);\n }\n } catch (error) {\n throw error;\n }\n } catch (error) {\n if (this.streamController?.signal.aborted) {\n break;\n }\n\n const backoffDelay = Math.min(\n INITIAL_DELAY * Math.pow(2, retryCount),\n MAX_DELAY,\n );\n\n if (retryCount < MAX_RETRIES) {\n retryCount++;\n this.emit(\n \"stream:reconnecting\",\n retryCount,\n MAX_RETRIES,\n backoffDelay,\n error instanceof Error ? error.message : String(error),\n );\n try {\n const completed = await delay(\n backoffDelay,\n this.streamController?.signal,\n );\n if (!completed) {\n break;\n }\n } catch (error) {\n if (this.streamController?.signal.aborted) {\n break;\n }\n }\n } else {\n this.emit(\"stream:disconnected\", \"Max reconnection attempts reached\");\n break;\n }\n }\n }\n }\n\n private async getLeaves(): Promise<TreeNode[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n const leaves = await sparkClient.query_nodes({\n source: {\n $case: \"ownerIdentityPubkey\",\n ownerIdentityPubkey: await this.config.signer.getIdentityPublicKey(),\n },\n includeParents: false,\n });\n\n return Object.entries(leaves.nodes)\n .filter(([_, node]) => node.status === \"AVAILABLE\")\n .map(([_, node]) => node);\n }\n\n private async selectLeaves(targetAmount: number): Promise<TreeNode[]> {\n if (targetAmount <= 0) {\n throw new ValidationError(\"Target amount must be positive\", {\n field: \"targetAmount\",\n value: targetAmount,\n });\n }\n\n const leaves = await this.getLeaves();\n if (leaves.length === 0) {\n throw new ValidationError(\"No owned leaves found\", {\n field: \"leaves\",\n });\n }\n\n leaves.sort((a, b) => b.value - a.value);\n\n let amount = 0;\n let nodes: TreeNode[] = [];\n for (const leaf of leaves) {\n if (targetAmount - amount >= leaf.value) {\n amount += leaf.value;\n nodes.push(leaf);\n }\n }\n\n if (amount !== targetAmount) {\n await this.requestLeavesSwap({ targetAmount });\n\n amount = 0;\n nodes = [];\n const newLeaves = await this.getLeaves();\n newLeaves.sort((a, b) => b.value - a.value);\n for (const leaf of newLeaves) {\n if (targetAmount - amount >= leaf.value) {\n amount += leaf.value;\n nodes.push(leaf);\n }\n }\n }\n\n if (nodes.reduce((acc, leaf) => acc + leaf.value, 0) !== targetAmount) {\n throw new Error(\n `Failed to select leaves for target amount ${targetAmount}`,\n );\n }\n\n return nodes;\n }\n\n private async selectLeavesForSwap(targetAmount: number) {\n if (targetAmount == 0) {\n throw new Error(\"Target amount needs to > 0\");\n }\n const leaves = await this.getLeaves();\n leaves.sort((a, b) => a.value - b.value);\n\n let amount = 0;\n const nodes: TreeNode[] = [];\n for (const leaf of leaves) {\n if (amount < targetAmount) {\n amount += leaf.value;\n nodes.push(leaf);\n }\n }\n\n if (amount < targetAmount) {\n throw new Error(\"Not enough leaves to swap for the target amount\");\n }\n\n return nodes;\n }\n\n private areLeavesInefficient() {\n const totalAmount = this.getInternalBalance();\n\n if (this.leaves.length <= 1) {\n return false;\n }\n\n const nextLowerPowerOfTwo = 31 - Math.clz32(totalAmount);\n\n let remainingAmount = totalAmount;\n let optimalLeavesLength = 0;\n\n for (let i = nextLowerPowerOfTwo; i >= 0; i--) {\n const denomination = 2 ** i;\n while (remainingAmount >= denomination) {\n remainingAmount -= denomination;\n optimalLeavesLength++;\n }\n }\n\n return this.leaves.length > optimalLeavesLength * 5;\n }\n\n private async optimizeLeaves() {\n if (this.optimizationInProgress || !this.areLeavesInefficient()) {\n return;\n }\n\n await this.withLeaves(async () => {\n this.optimizationInProgress = true;\n try {\n if (this.leaves.length > 0) {\n await this.requestLeavesSwap({ leaves: this.leaves });\n }\n this.leaves = await this.getLeaves();\n } finally {\n this.optimizationInProgress = false;\n }\n });\n }\n\n private async syncWallet() {\n await this.syncTokenOutputs();\n this.leaves = await this.getLeaves();\n await this.config.signer.restoreSigningKeysFromLeafs(this.leaves);\n await this.checkRefreshTimelockNodes();\n await this.checkExtendTimeLockNodes();\n this.optimizeLeaves().catch((e) => {\n console.error(\"Failed to optimize leaves\", e);\n });\n }\n\n private async withLeaves<T>(operation: () => Promise<T>): Promise<T> {\n const release = await this.leavesMutex.acquire();\n try {\n return await operation();\n } finally {\n release();\n }\n }\n\n /**\n * Gets the identity public key of the wallet.\n *\n * @returns {Promise<string>} The identity public key as a hex string.\n */\n public async getIdentityPublicKey(): Promise<string> {\n return bytesToHex(await this.config.signer.getIdentityPublicKey());\n }\n\n /**\n * Gets the Spark address of the wallet.\n *\n * @returns {Promise<string>} The Spark address as a hex string.\n */\n public async getSparkAddress(): Promise<SparkAddressFormat> {\n if (!this.sparkAddress) {\n this.sparkAddress = encodeSparkAddress({\n identityPublicKey: bytesToHex(\n await this.config.signer.getIdentityPublicKey(),\n ),\n network: this.config.getNetworkType(),\n });\n }\n\n return this.sparkAddress;\n }\n\n /**\n * Initializes the wallet using either a mnemonic phrase or a raw seed.\n * initWallet will also claim any pending incoming lightning payment, spark transfer,\n * or bitcoin deposit.\n *\n * @param {Uint8Array | string} [mnemonicOrSeed] - (Optional) Either:\n * - A BIP-39 mnemonic phrase as string\n * - A raw seed as Uint8Array or hex string\n * If not provided, generates a new mnemonic and uses it to create a new wallet\n *\n * @returns {Promise<Object>} Object containing:\n * - mnemonic: The mnemonic if one was generated (undefined for raw seed)\n * - balance: The wallet's initial balance in satoshis\n * - tokenBalance: Map of token balances\n * @private\n */\n protected async initWallet(\n mnemonicOrSeed?: Uint8Array | string,\n accountNumber?: number,\n ): Promise<InitWalletResponse | undefined> {\n if (accountNumber === 0 || accountNumber === 1) {\n // Reserved values for the case where no account number is provided\n throw new ValidationError(\n \"If an account number is provided, it must not be be 0 or 1\",\n {\n field: \"accountNumber\",\n value: accountNumber,\n expected: \"values that do not equal 0 or 1\",\n },\n );\n }\n let mnemonic: string | undefined;\n if (!mnemonicOrSeed) {\n mnemonic = await this.config.signer.generateMnemonic();\n mnemonicOrSeed = mnemonic;\n }\n\n let seed: Uint8Array;\n if (typeof mnemonicOrSeed !== \"string\") {\n seed = mnemonicOrSeed;\n } else {\n if (validateMnemonic(mnemonicOrSeed, wordlist)) {\n mnemonic = mnemonicOrSeed;\n seed = await this.config.signer.mnemonicToSeed(mnemonicOrSeed);\n } else {\n seed = hexToBytes(mnemonicOrSeed);\n }\n }\n await this.initWalletFromSeed(seed, accountNumber);\n\n const network = this.config.getNetwork();\n // TODO: remove this once we move it back to the signer\n if (typeof seed === \"string\") {\n seed = hexToBytes(seed);\n }\n\n const hdkey = getMasterHDKeyFromSeed(seed);\n\n if (!hdkey.privateKey || !hdkey.publicKey) {\n throw new ValidationError(\"Failed to derive keys from seed\", {\n field: \"hdkey\",\n value: seed,\n });\n }\n const accountNetwork = network === Network.REGTEST ? 0 : 1;\n const identityKey = hdkey.derive(\n `m/8797555'/${accountNumber ?? accountNetwork}'/0'`, // When an accountNumber is not provided, set a value based on the network\n );\n this.lrc20Wallet = new LRCWallet(\n bytesToHex(identityKey.privateKey!),\n LRC_WALLET_NETWORK[network],\n LRC_WALLET_NETWORK_TYPE[network],\n this.config.lrc20ApiConfig,\n );\n\n return {\n mnemonic,\n };\n }\n\n /**\n * Initializes a wallet from a seed.\n *\n * @param {Uint8Array | string} seed - The seed to initialize the wallet from\n * @returns {Promise<string>} The identity public key\n * @private\n */\n private async initWalletFromSeed(\n seed: Uint8Array | string,\n accountNumber?: number,\n ) {\n const identityPublicKey =\n await this.config.signer.createSparkWalletFromSeed(\n seed,\n this.config.getNetwork(),\n accountNumber,\n );\n await this.initializeWallet();\n\n this.sparkAddress = encodeSparkAddress({\n identityPublicKey: identityPublicKey,\n network: this.config.getNetworkType(),\n });\n\n return this.sparkAddress;\n }\n\n /**\n * Gets the estimated fee for a swap of leaves.\n *\n * @param amountSats - The amount of sats to swap\n * @returns {Promise<LeavesSwapFeeEstimateOutput>} The estimated fee for the swap\n */\n public async getSwapFeeEstimate(\n amountSats: number,\n ): Promise<LeavesSwapFeeEstimateOutput> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n const feeEstimate = await this.sspClient.getSwapFeeEstimate(amountSats);\n if (!feeEstimate) {\n throw new Error(\"Failed to get swap fee estimate\");\n }\n\n return feeEstimate;\n }\n\n /**\n * Requests a swap of leaves to optimize wallet structure.\n *\n * @param {Object} params - Parameters for the leaves swap\n * @param {number} [params.targetAmount] - Target amount for the swap\n * @param {TreeNode[]} [params.leaves] - Specific leaves to swap\n * @returns {Promise<Object>} The completed swap response\n * @private\n */\n private async requestLeavesSwap({\n targetAmount,\n leaves,\n }: {\n targetAmount?: number;\n leaves?: TreeNode[];\n }) {\n if (targetAmount && targetAmount <= 0) {\n throw new Error(\"targetAmount must be positive\");\n }\n\n if (targetAmount && !Number.isSafeInteger(targetAmount)) {\n throw new ValidationError(\"targetAmount must be less than 2^53\", {\n field: \"targetAmount\",\n value: targetAmount,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n try {\n await this.claimTransfers();\n } catch (e) {\n console.warn(\"Unabled to claim transfers.\");\n }\n\n let leavesToSwap: TreeNode[];\n if (targetAmount && leaves && leaves.length > 0) {\n if (targetAmount < leaves.reduce((acc, leaf) => acc + leaf.value, 0)) {\n throw new Error(\"targetAmount is less than the sum of leaves\");\n }\n leavesToSwap = leaves;\n } else if (targetAmount) {\n leavesToSwap = await this.selectLeavesForSwap(targetAmount);\n } else if (leaves && leaves.length > 0) {\n leavesToSwap = leaves;\n } else {\n throw new Error(\"targetAmount or leaves must be provided\");\n }\n\n const leafKeyTweaks = await Promise.all(\n leavesToSwap.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const { transfer, signatureMap } =\n await this.transferService.startSwapSignRefund(\n leafKeyTweaks,\n hexToBytes(this.config.getSspIdentityPublicKey()),\n new Date(Date.now() + 2 * 60 * 1000),\n );\n try {\n if (!transfer.leaves[0]?.leaf) {\n throw new Error(\"Failed to get leaf\");\n }\n\n const refundSignature = signatureMap.get(transfer.leaves[0].leaf.id);\n if (!refundSignature) {\n throw new Error(\"Failed to get refund signature\");\n }\n\n const { adaptorPrivateKey, adaptorSignature } =\n generateAdaptorFromSignature(refundSignature);\n\n if (!transfer.leaves[0].leaf) {\n throw new Error(\"Failed to get leaf\");\n }\n\n const userLeaves: UserLeafInput[] = [];\n userLeaves.push({\n leaf_id: transfer.leaves[0].leaf.id,\n raw_unsigned_refund_transaction: bytesToHex(\n transfer.leaves[0].intermediateRefundTx,\n ),\n adaptor_added_signature: bytesToHex(adaptorSignature),\n });\n\n for (let i = 1; i < transfer.leaves.length; i++) {\n const leaf = transfer.leaves[i];\n if (!leaf?.leaf) {\n throw new Error(\"Failed to get leaf\");\n }\n\n const refundSignature = signatureMap.get(leaf.leaf.id);\n if (!refundSignature) {\n throw new Error(\"Failed to get refund signature\");\n }\n\n const signature = generateSignatureFromExistingAdaptor(\n refundSignature,\n adaptorPrivateKey,\n );\n\n userLeaves.push({\n leaf_id: leaf.leaf.id,\n raw_unsigned_refund_transaction: bytesToHex(\n leaf.intermediateRefundTx,\n ),\n adaptor_added_signature: bytesToHex(signature),\n });\n }\n\n const adaptorPubkey = bytesToHex(\n secp256k1.getPublicKey(adaptorPrivateKey),\n );\n let request: LeavesSwapRequest | null | undefined = null;\n request = await this.sspClient?.requestLeaveSwap({\n userLeaves,\n adaptorPubkey,\n targetAmountSats:\n targetAmount ||\n leavesToSwap.reduce((acc, leaf) => acc + leaf.value, 0),\n totalAmountSats: leavesToSwap.reduce(\n (acc, leaf) => acc + leaf.value,\n 0,\n ),\n // TODO: Request fee from SSP\n feeSats: 0,\n idempotencyKey: uuidv7(),\n });\n\n if (!request) {\n throw new Error(\"Failed to request leaves swap. No response returned.\");\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const nodes = await sparkClient.query_nodes({\n source: {\n $case: \"nodeIds\",\n nodeIds: {\n nodeIds: request.swapLeaves.map((leaf) => leaf.leafId),\n },\n },\n includeParents: false,\n });\n\n if (Object.values(nodes.nodes).length !== request.swapLeaves.length) {\n throw new Error(\"Expected same number of nodes as swapLeaves\");\n }\n\n for (const [nodeId, node] of Object.entries(nodes.nodes)) {\n if (!node.nodeTx) {\n throw new Error(`Node tx not found for leaf ${nodeId}`);\n }\n\n if (!node.verifyingPublicKey) {\n throw new Error(`Node public key not found for leaf ${nodeId}`);\n }\n\n const leaf = request.swapLeaves.find((leaf) => leaf.leafId === nodeId);\n if (!leaf) {\n throw new Error(`Leaf not found for node ${nodeId}`);\n }\n\n // @ts-ignore - We do a null check above\n const nodeTx = getTxFromRawTxBytes(node.nodeTx);\n const refundTxBytes = hexToBytes(leaf.rawUnsignedRefundTransaction);\n const refundTx = getTxFromRawTxBytes(refundTxBytes);\n const sighash = getSigHashFromTx(refundTx, 0, nodeTx.getOutput(0));\n\n const nodePublicKey = node.verifyingPublicKey;\n\n const taprootKey = computeTaprootKeyNoScript(nodePublicKey.slice(1));\n const adaptorSignatureBytes = hexToBytes(leaf.adaptorSignedSignature);\n applyAdaptorToSignature(\n taprootKey.slice(1),\n sighash,\n adaptorSignatureBytes,\n adaptorPrivateKey,\n );\n }\n\n await this.transferService.sendTransferTweakKey(\n transfer,\n leafKeyTweaks,\n signatureMap,\n );\n\n const completeResponse = await this.sspClient?.completeLeaveSwap({\n adaptorSecretKey: bytesToHex(adaptorPrivateKey),\n userOutboundTransferExternalId: transfer.id,\n leavesSwapRequestId: request.id,\n });\n\n if (!completeResponse) {\n throw new Error(\"Failed to complete leaves swap\");\n }\n\n await this.claimTransfers(TransferType.COUNTER_SWAP);\n\n return completeResponse;\n } catch (e) {\n await this.cancelAllSenderInitiatedTransfers();\n throw new Error(`Failed to request leaves swap: ${e}`);\n }\n }\n\n /**\n * Gets all transfers for the wallet.\n *\n * @param {number} [limit=20] - Maximum number of transfers to return\n * @param {number} [offset=0] - Offset for pagination\n * @returns {Promise<QueryTransfersResponse>} Response containing the list of transfers\n */\n public async getTransfers(\n limit: number = 20,\n offset: number = 0,\n ): Promise<{\n transfers: WalletTransfer[];\n offset: number;\n }> {\n const transfers = await this.transferService.queryAllTransfers(\n limit,\n offset,\n );\n const identityPublicKey = bytesToHex(\n await this.config.signer.getIdentityPublicKey(),\n );\n return {\n transfers: transfers.transfers.map((transfer) =>\n mapTransferToWalletTransfer(transfer, identityPublicKey),\n ),\n offset: transfers.offset,\n };\n }\n\n /**\n * Gets the held token info for the wallet.\n *\n * @deprecated The information is returned in getBalance\n */\n public async getTokenInfo(): Promise<TokenInfo[]> {\n console.warn(\"getTokenInfo is deprecated. Use getBalance instead.\");\n\n await this.syncTokenOutputs();\n\n const lrc20Client = await this.lrc20ConnectionManager.createLrc20Client();\n const { balance, tokenBalances } = await this.getBalance();\n\n const tokenInfo = await lrc20Client.getTokenPubkeyInfo({\n publicKeys: Array.from(tokenBalances.keys()).map(hexToBytes),\n });\n\n return tokenInfo.tokenPubkeyInfos.map((info) => ({\n tokenPublicKey: bytesToHex(info.announcement!.publicKey!.publicKey),\n tokenName: info.announcement!.name,\n tokenSymbol: info.announcement!.symbol,\n tokenDecimals: Number(bytesToNumberBE(info.announcement!.decimal)),\n maxSupply: bytesToNumberBE(info.announcement!.maxSupply),\n }));\n }\n\n /**\n * Gets the current balance of the wallet.\n * You can use the forceRefetch option to synchronize your wallet and claim any\n * pending incoming lightning payment, spark transfer, or bitcoin deposit before returning the balance.\n *\n * @returns {Promise<Object>} Object containing:\n * - balance: The wallet's current balance in satoshis\n * - tokenBalances: Map of token public keys to token balances and token info\n */\n public async getBalance(): Promise<{\n balance: bigint;\n tokenBalances: Map<string, { balance: bigint; tokenInfo: TokenInfo }>;\n }> {\n this.leaves = await this.getLeaves();\n await this.syncTokenOutputs();\n\n let tokenBalances: Map<string, { balance: bigint; tokenInfo: TokenInfo }>;\n\n if (this.tokenOutputs.size !== 0) {\n tokenBalances = await this.getTokenBalance();\n } else {\n tokenBalances = new Map<\n string,\n { balance: bigint; tokenInfo: TokenInfo }\n >();\n }\n\n return {\n balance: BigInt(this.getInternalBalance()),\n tokenBalances,\n };\n }\n\n private async getTokenBalance(): Promise<\n Map<string, { balance: bigint; tokenInfo: TokenInfo }>\n > {\n const lrc20Client = await this.lrc20ConnectionManager.createLrc20Client();\n\n // Get token info for all tokens\n const tokenInfo = await lrc20Client.getTokenPubkeyInfo({\n publicKeys: Array.from(this.tokenOutputs.keys()).map(hexToBytes),\n });\n\n const result = new Map<string, { balance: bigint; tokenInfo: TokenInfo }>();\n\n for (const info of tokenInfo.tokenPubkeyInfos) {\n const tokenPublicKey = bytesToHex(\n info.announcement!.publicKey!.publicKey,\n );\n const leaves = this.tokenOutputs.get(tokenPublicKey);\n\n result.set(tokenPublicKey, {\n balance: leaves ? calculateAvailableTokenAmount(leaves) : BigInt(0),\n tokenInfo: {\n tokenPublicKey,\n tokenName: info.announcement!.name,\n tokenSymbol: info.announcement!.symbol,\n tokenDecimals: Number(bytesToNumberBE(info.announcement!.decimal)),\n maxSupply: bytesToNumberBE(info.announcement!.maxSupply),\n },\n });\n }\n\n return result;\n }\n\n private getInternalBalance(): number {\n return this.leaves.reduce((acc, leaf) => acc + leaf.value, 0);\n }\n\n // ***** Deposit Flow *****\n\n /**\n * Generates a new deposit address for receiving bitcoin funds.\n * Note that this function returns a bitcoin address, not a spark address, and this address is single use.\n * Once you deposit funds to this address, it cannot be used again.\n * For Layer 1 Bitcoin deposits, Spark generates Pay to Taproot (P2TR) addresses.\n * These addresses start with \"bc1p\" and can be used to receive Bitcoin from any wallet.\n *\n * @returns {Promise<string>} A Bitcoin address for depositing funds\n */\n public async getSingleUseDepositAddress(): Promise<string> {\n return await this.generateDepositAddress();\n }\n\n /**\n * Generates a deposit address for receiving funds.\n *\n * @returns {Promise<string>} A deposit address\n * @private\n */\n private async generateDepositAddress(): Promise<string> {\n const leafId = uuidv7();\n const signingPubkey = await this.config.signer.generatePublicKey(\n sha256(leafId),\n );\n const address = await this.depositService!.generateDepositAddress({\n signingPubkey,\n leafId,\n });\n if (!address.depositAddress) {\n throw new RPCError(\"Failed to generate deposit address\", {\n method: \"generateDepositAddress\",\n params: { signingPubkey, leafId },\n });\n }\n return address.depositAddress.address;\n }\n\n /**\n * Finalizes a deposit to the wallet.\n *\n * @param {DepositParams} params - Parameters for finalizing the deposit\n * @returns {Promise<void>} The nodes created from the deposit\n * @private\n */\n private async finalizeDeposit({\n signingPubKey,\n verifyingKey,\n depositTx,\n vout,\n }: DepositParams) {\n if (!Number.isSafeInteger(vout)) {\n throw new ValidationError(\"vout must be less than 2^53\", {\n field: \"vout\",\n value: vout,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n const res = await this.depositService!.createTreeRoot({\n signingPubKey,\n verifyingKey,\n depositTx,\n vout,\n });\n\n const resultingNodes: TreeNode[] = [];\n for (const node of res.nodes) {\n if (node.status === \"AVAILABLE\") {\n const { nodes } = await this.transferService.extendTimelock(\n node,\n signingPubKey,\n );\n\n for (const n of nodes) {\n if (n.status === \"AVAILABLE\") {\n const transfer = await this.transferLeavesToSelf(\n [n],\n signingPubKey,\n );\n resultingNodes.push(...transfer);\n } else {\n resultingNodes.push(n);\n }\n }\n } else {\n resultingNodes.push(node);\n }\n }\n\n return resultingNodes;\n }\n\n /**\n * Gets all unused deposit addresses for the wallet.\n *\n * @returns {Promise<string[]>} The unused deposit addresses\n */\n public async getUnusedDepositAddresses(): Promise<string[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n return (\n await sparkClient.query_unused_deposit_addresses({\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n })\n ).depositAddresses.map((addr) => addr.depositAddress);\n }\n /**\n * Claims a deposit to the wallet.\n * Note that if you used advancedDeposit, you don't need to call this function.\n * @param {string} txid - The transaction ID of the deposit\n * @returns {Promise<WalletLeaf[] | undefined>} The nodes resulting from the deposit\n */\n public async claimDeposit(txid: string): Promise<WalletLeaf[]> {\n if (!txid) {\n throw new ValidationError(\"Transaction ID cannot be empty\", {\n field: \"txid\",\n });\n }\n\n let mutex = this.mutexes.get(txid);\n if (!mutex) {\n mutex = new Mutex();\n this.mutexes.set(txid, mutex);\n }\n\n const nodes = await mutex.runExclusive(async () => {\n const baseUrl = this.config.getElectrsUrl();\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n let txHex: string | undefined;\n\n if (this.config.getNetwork() === Network.LOCAL) {\n const localFaucet = BitcoinFaucet.getInstance();\n const response = await localFaucet.getRawTransaction(txid);\n txHex = response.hex;\n } else {\n if (this.config.getNetwork() === Network.REGTEST) {\n const auth = btoa(\n `${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`,\n );\n headers[\"Authorization\"] = `Basic ${auth}`;\n }\n\n const response = await fetch(`${baseUrl}/tx/${txid}/hex`, {\n headers,\n });\n\n txHex = await response.text();\n }\n\n if (!txHex) {\n throw new Error(\"Transaction not found\");\n }\n\n if (!/^[0-9A-Fa-f]+$/.test(txHex)) {\n throw new ValidationError(\"Invalid transaction hex\", {\n field: \"txHex\",\n value: txHex,\n });\n }\n const depositTx = getTxFromRawTxHex(txHex);\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const unusedDepositAddresses: Map<string, DepositAddressQueryResult> =\n new Map(\n (\n await sparkClient.query_unused_deposit_addresses({\n identityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n })\n ).depositAddresses.map((addr) => [addr.depositAddress, addr]),\n );\n\n let depositAddress: DepositAddressQueryResult | undefined;\n let vout = 0;\n for (let i = 0; i < depositTx.outputsLength; i++) {\n const output = depositTx.getOutput(i);\n if (!output) {\n continue;\n }\n const parsedScript = OutScript.decode(output.script!);\n const address = Address(getNetwork(this.config.getNetwork())).encode(\n parsedScript,\n );\n if (unusedDepositAddresses.has(address)) {\n vout = i;\n depositAddress = unusedDepositAddresses.get(address);\n break;\n }\n }\n if (!depositAddress) {\n throw new ValidationError(\"Deposit address has already been used\", {\n field: \"depositAddress\",\n value: depositAddress,\n });\n }\n\n let signingPubKey: Uint8Array;\n if (!depositAddress.leafId) {\n signingPubKey = depositAddress.userSigningPublicKey;\n } else {\n signingPubKey = await this.config.signer.generatePublicKey(\n sha256(depositAddress.leafId),\n );\n }\n\n const nodes = await this.finalizeDeposit({\n signingPubKey,\n verifyingKey: depositAddress.verifyingPublicKey,\n depositTx,\n vout,\n });\n\n return nodes;\n });\n\n this.mutexes.delete(txid);\n\n return nodes.map(mapTreeNodeToWalletLeaf);\n }\n\n /**\n * Non-trusty flow for depositing funds to the wallet.\n * Construct the tx spending from an L1 wallet to the Spark address.\n * After calling this function, you must sign and broadcast the tx.\n *\n * @param {string} txHex - The hex string of the transaction to deposit\n * @returns {Promise<TreeNode[] | undefined>} The nodes resulting from the deposit\n */\n public async advancedDeposit(txHex: string) {\n const depositTx = getTxFromRawTxHex(txHex);\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n const unusedDepositAddresses: Map<string, DepositAddressQueryResult> =\n new Map(\n (\n await sparkClient.query_unused_deposit_addresses({\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n })\n ).depositAddresses.map((addr) => [addr.depositAddress, addr]),\n );\n\n let vout = 0;\n const responses: TreeNode[] = [];\n for (let i = 0; i < depositTx.outputsLength; i++) {\n const output = depositTx.getOutput(i);\n if (!output) {\n continue;\n }\n const parsedScript = OutScript.decode(output.script!);\n const address = Address(getNetwork(this.config.getNetwork())).encode(\n parsedScript,\n );\n const unusedDepositAddress = unusedDepositAddresses.get(address);\n if (unusedDepositAddress) {\n vout = i;\n const response = await this.depositService!.createTreeRoot({\n signingPubKey: unusedDepositAddress.userSigningPublicKey,\n verifyingKey: unusedDepositAddress.verifyingPublicKey,\n depositTx,\n vout,\n });\n responses.push(...response.nodes);\n }\n }\n if (responses.length === 0) {\n throw new Error(\n `No unused deposit address found for tx: ${getTxId(depositTx)}`,\n );\n }\n\n return responses;\n }\n\n /**\n * Transfers deposit to self to claim ownership.\n *\n * @param {TreeNode[]} leaves - The leaves to transfer\n * @param {Uint8Array} signingPubKey - The signing public key\n * @returns {Promise<TreeNode[] | undefined>} The nodes resulting from the transfer\n * @private\n */\n private async transferLeavesToSelf(\n leaves: TreeNode[],\n signingPubKey: Uint8Array,\n ): Promise<TreeNode[]> {\n const leafKeyTweaks = await Promise.all(\n leaves.map(async (leaf) => ({\n leaf,\n signingPubKey,\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const transfer = await this.transferService.sendTransfer(\n leafKeyTweaks,\n await this.config.signer.getIdentityPublicKey(),\n );\n\n const resultNodes = await this.claimTransfer(transfer);\n\n const leavesToRemove = new Set(leaves.map((leaf) => leaf.id));\n this.leaves = [\n ...this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id)),\n ...resultNodes,\n ];\n\n return resultNodes;\n }\n // ***** Transfer Flow *****\n\n /**\n * Sends a transfer to another Spark user.\n *\n * @param {TransferParams} params - Parameters for the transfer\n * @param {string} params.receiverSparkAddress - The recipient's Spark address\n * @param {number} params.amountSats - Amount to send in satoshis\n * @returns {Promise<WalletTransfer>} The completed transfer details\n */\n public async transfer({\n amountSats,\n receiverSparkAddress,\n }: TransferParams): Promise<WalletTransfer> {\n if (!receiverSparkAddress) {\n throw new ValidationError(\"Receiver Spark address cannot be empty\", {\n field: \"receiverSparkAddress\",\n });\n }\n\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n if (amountSats <= 0) {\n throw new ValidationError(\"Amount must be greater than 0\", {\n field: \"amountSats\",\n value: amountSats,\n });\n }\n\n const receiverAddress = decodeSparkAddress(\n receiverSparkAddress,\n this.config.getNetworkType(),\n );\n\n const isSelfTransfer = equalBytes(\n await this.config.signer.getIdentityPublicKey(),\n hexToBytes(receiverAddress),\n );\n\n return await this.withLeaves(async () => {\n let leavesToSend = await this.selectLeaves(amountSats);\n\n await this.checkRefreshTimelockNodes(leavesToSend);\n leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);\n\n const leafKeyTweaks = await Promise.all(\n leavesToSend.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const transfer = await this.transferService.sendTransfer(\n leafKeyTweaks,\n hexToBytes(receiverAddress),\n );\n\n const leavesToRemove = new Set(leavesToSend.map((leaf) => leaf.id));\n this.leaves = this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id));\n\n // If this is a self-transfer, lets claim it immediately\n if (isSelfTransfer) {\n await this.claimTransfer(transfer);\n }\n\n return mapTransferToWalletTransfer(\n transfer,\n bytesToHex(await this.config.signer.getIdentityPublicKey()),\n );\n });\n }\n\n private async checkExtendTimeLockNodes(\n nodes?: TreeNode[],\n ): Promise<TreeNode[]> {\n const nodesToCheck = nodes ?? this.leaves;\n const nodesToExtend: TreeNode[] = [];\n const nodeIds: string[] = [];\n let resultNodes = [...nodesToCheck];\n\n for (const node of nodesToCheck) {\n const nodeTx = getTxFromRawTxBytes(node.nodeTx);\n const { needRefresh } = getNextTransactionSequence(\n nodeTx.getInput(0).sequence,\n );\n if (needRefresh) {\n nodesToExtend.push(node);\n nodeIds.push(node.id);\n }\n }\n\n resultNodes = resultNodes.filter((node) => !nodesToExtend.includes(node));\n\n for (const node of nodesToExtend) {\n const signingPubKey = await this.config.signer.generatePublicKey(\n sha256(node.id),\n );\n const { nodes } = await this.transferService.extendTimelock(\n node,\n signingPubKey,\n );\n this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);\n const newNodes = await this.transferLeavesToSelf(nodes, signingPubKey);\n resultNodes.push(...newNodes);\n }\n\n return resultNodes;\n }\n\n /**\n * Internal method to refresh timelock nodes.\n *\n * @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.\n * @returns {Promise<void>}\n * @private\n */\n private async checkRefreshTimelockNodes(nodes?: TreeNode[]) {\n const nodesToRefresh: TreeNode[] = [];\n const nodeIds: string[] = [];\n\n for (const node of nodes ?? this.leaves) {\n const refundTx = getTxFromRawTxBytes(node.refundTx);\n const { needRefresh } = getNextTransactionSequence(\n refundTx.getInput(0).sequence,\n true,\n );\n if (needRefresh) {\n nodesToRefresh.push(node);\n nodeIds.push(node.id);\n }\n }\n\n if (nodesToRefresh.length === 0) {\n return;\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const nodesResp = await sparkClient.query_nodes({\n source: {\n $case: \"nodeIds\",\n nodeIds: {\n nodeIds,\n },\n },\n includeParents: true,\n });\n\n const nodesMap = new Map<string, TreeNode>();\n for (const node of Object.values(nodesResp.nodes)) {\n nodesMap.set(node.id, node);\n }\n\n for (const node of nodesToRefresh) {\n if (!node.parentNodeId) {\n throw new Error(`node ${node.id} has no parent`);\n }\n\n const parentNode = nodesMap.get(node.parentNodeId);\n if (!parentNode) {\n throw new Error(`parent node ${node.parentNodeId} not found`);\n }\n\n const { nodes } = await this.transferService.refreshTimelockNodes(\n [node],\n parentNode,\n await this.config.signer.generatePublicKey(sha256(node.id)),\n );\n\n if (nodes.length !== 1) {\n throw new Error(`expected 1 node, got ${nodes.length}`);\n }\n\n const newNode = nodes[0];\n if (!newNode) {\n throw new Error(\"Failed to refresh timelock node\");\n }\n\n this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);\n this.leaves.push(newNode);\n }\n }\n\n /**\n * Claims a specific transfer.\n *\n * @param {Transfer} transfer - The transfer to claim\n * @returns {Promise<Object>} The claim result\n */\n private async claimTransfer(\n transfer: Transfer,\n emit: boolean = false,\n retryCount: number = 0,\n ) {\n const MAX_RETRIES = 5;\n const BASE_DELAY_MS = 1000;\n const MAX_DELAY_MS = 10000;\n\n if (retryCount > 0) {\n const delayMs = Math.min(\n BASE_DELAY_MS * Math.pow(2, retryCount - 1),\n MAX_DELAY_MS,\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n try {\n let result = await this.claimTransferMutex.runExclusive(async () => {\n const leafPubKeyMap =\n await this.transferService.verifyPendingTransfer(transfer);\n\n let leavesToClaim: LeafKeyTweak[] = [];\n\n for (const leaf of transfer.leaves) {\n if (leaf.leaf) {\n const leafPubKey = leafPubKeyMap.get(leaf.leaf.id);\n if (leafPubKey) {\n leavesToClaim.push({\n leaf: leaf.leaf,\n signingPubKey: leafPubKey,\n newSigningPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.leaf.id),\n ),\n });\n }\n }\n }\n\n const response = await this.transferService.claimTransfer(\n transfer,\n leavesToClaim,\n );\n\n this.leaves.push(...response.nodes);\n\n if (emit) {\n this.emit(\n \"transfer:claimed\",\n transfer.id,\n (await this.getBalance()).balance,\n );\n }\n\n return response.nodes;\n });\n\n await this.checkRefreshTimelockNodes(result);\n result = await this.checkExtendTimeLockNodes(result);\n\n return result;\n } catch (error) {\n if (retryCount < MAX_RETRIES) {\n console.error(\"Failed to claim transfer, retrying...\", error);\n this.claimTransfer(transfer, emit, retryCount + 1);\n return [];\n } else if (retryCount > 0) {\n console.error(\"Failed to claim transfer\", error);\n return [];\n } else {\n throw new NetworkError(\n \"Failed to claim transfer\",\n {\n operation: \"claimTransfer\",\n errors: error instanceof Error ? error.message : String(error),\n },\n error instanceof Error ? error : undefined,\n );\n }\n }\n }\n\n /**\n * Claims all pending transfers.\n *\n * @returns {Promise<string[]>} Array of successfully claimed transfer IDs\n * @private\n */\n private async claimTransfers(\n type?: TransferType,\n emit?: boolean,\n ): Promise<string[]> {\n const transfers = await this.transferService.queryPendingTransfers();\n const promises: Promise<string | null>[] = [];\n for (const transfer of transfers.transfers) {\n if (type && transfer.type !== type) {\n continue;\n }\n\n if (\n transfer.status !== TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED &&\n transfer.status !==\n TransferStatus.TRANSFER_STATUS_RECEIVER_KEY_TWEAKED &&\n transfer.status !==\n TransferStatus.TRANSFER_STATUSR_RECEIVER_REFUND_SIGNED\n ) {\n continue;\n }\n promises.push(\n this.claimTransfer(transfer, emit)\n .then(() => transfer.id)\n .catch((error) => {\n console.warn(`Failed to claim transfer ${transfer.id}:`, error);\n return null;\n }),\n );\n }\n const results = await Promise.allSettled(promises);\n return results\n .filter(\n (result) => result.status === \"fulfilled\" && result.value !== null,\n )\n .map((result) => (result as PromiseFulfilledResult<string>).value);\n }\n\n /**\n * Cancels all sender-initiated transfers.\n *\n * @returns {Promise<void>}\n * @private\n */\n private async cancelAllSenderInitiatedTransfers() {\n for (const operator of Object.values(this.config.getSigningOperators())) {\n const transfers =\n await this.transferService.queryPendingTransfersBySender(\n operator.address,\n );\n\n for (const transfer of transfers.transfers) {\n if (\n transfer.status === TransferStatus.TRANSFER_STATUS_SENDER_INITIATED\n ) {\n await this.transferService.cancelTransfer(transfer, operator.address);\n }\n }\n }\n }\n\n // ***** Lightning Flow *****\n\n /**\n * Creates a Lightning invoice for receiving payments.\n *\n * @param {Object} params - Parameters for the lightning invoice\n * @param {number} params.amountSats - Amount in satoshis\n * @param {string} params.memo - Description for the invoice\n * @param {number} [params.expirySeconds] - Optional expiry time in seconds\n * @returns {Promise<LightningReceiveRequest>} BOLT11 encoded invoice\n */\n public async createLightningInvoice({\n amountSats,\n memo,\n expirySeconds = 60 * 60 * 24 * 30,\n }: CreateLightningInvoiceParams): Promise<LightningReceiveRequest> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n if (isNaN(amountSats) || amountSats < 0) {\n throw new ValidationError(\"Invalid amount\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"non-negative number\",\n });\n }\n\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n if (!Number.isSafeInteger(expirySeconds)) {\n throw new ValidationError(\"Expiration time must be less than 2^53\", {\n field: \"expirySeconds\",\n value: expirySeconds,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n if (expirySeconds < 0) {\n throw new ValidationError(\"Invalid expiration time\", {\n field: \"expirySeconds\",\n value: expirySeconds,\n expected: \"Non-negative expiration time\",\n });\n }\n\n if (memo && memo.length > 639) {\n throw new ValidationError(\"Invalid memo size\", {\n field: \"memo\",\n value: memo,\n expected: \"Memo size within limits\",\n });\n }\n\n const requestLightningInvoice = async (\n amountSats: number,\n paymentHash: Uint8Array,\n memo?: string,\n ) => {\n const network = this.config.getNetwork();\n let bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.REGTEST;\n if (network === Network.MAINNET) {\n bitcoinNetwork = BitcoinNetwork.MAINNET;\n } else if (network === Network.REGTEST) {\n bitcoinNetwork = BitcoinNetwork.REGTEST;\n }\n\n const invoice = await this.sspClient!.requestLightningReceive({\n amountSats,\n network: bitcoinNetwork,\n paymentHash: bytesToHex(paymentHash),\n expirySecs: expirySeconds,\n memo,\n });\n\n return invoice;\n };\n\n const invoice = await this.lightningService!.createLightningInvoice({\n amountSats,\n memo,\n invoiceCreator: requestLightningInvoice,\n });\n\n return invoice;\n }\n\n /**\n * Pays a Lightning invoice.\n *\n * @param {Object} params - Parameters for paying the invoice\n * @param {string} params.invoice - The BOLT11-encoded Lightning invoice to pay\n * @returns {Promise<LightningSendRequest>} The Lightning payment request details\n */\n public async payLightningInvoice({\n invoice,\n maxFeeSats,\n }: PayLightningInvoiceParams) {\n return await this.withLeaves(async () => {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n const decodedInvoice = decode(invoice);\n const amountSats =\n Number(\n decodedInvoice.sections.find((section) => section.name === \"amount\")\n ?.value,\n ) / 1000;\n\n if (isNaN(amountSats) || amountSats <= 0) {\n throw new ValidationError(\"Invalid amount\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"positive number\",\n });\n }\n\n const paymentHash = decodedInvoice.sections.find(\n (section) => section.name === \"payment_hash\",\n )?.value;\n\n if (!paymentHash) {\n throw new ValidationError(\"No payment hash found in invoice\", {\n field: \"paymentHash\",\n });\n }\n\n const feeEstimate = await this.getLightningSendFeeEstimate({\n encodedInvoice: invoice,\n });\n\n if (maxFeeSats < feeEstimate) {\n throw new ValidationError(\"maxFeeSats does not cover fee estimate\", {\n field: \"maxFeeSats\",\n value: maxFeeSats,\n expected: `${feeEstimate} sats`,\n });\n }\n\n const totalAmount = amountSats + feeEstimate;\n\n const internalBalance = this.getInternalBalance();\n if (totalAmount > internalBalance) {\n throw new ValidationError(\"Insufficient balance\", {\n field: \"balance\",\n value: internalBalance,\n expected: `${totalAmount} sats`,\n });\n }\n\n let leaves = await this.selectLeaves(totalAmount);\n\n await this.checkRefreshTimelockNodes(leaves);\n leaves = await this.checkExtendTimeLockNodes(leaves);\n\n const leavesToSend = await Promise.all(\n leaves.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const swapResponse = await this.lightningService.swapNodesForPreimage({\n leaves: leavesToSend,\n receiverIdentityPubkey: hexToBytes(\n this.config.getSspIdentityPublicKey(),\n ),\n paymentHash: hexToBytes(paymentHash),\n isInboundPayment: false,\n invoiceString: invoice,\n feeSats: feeEstimate,\n });\n\n if (!swapResponse.transfer) {\n throw new Error(\"Failed to swap nodes for preimage\");\n }\n\n const transfer = await this.transferService.sendTransferTweakKey(\n swapResponse.transfer,\n leavesToSend,\n new Map(),\n );\n\n const sspResponse = await this.sspClient.requestLightningSend({\n encodedInvoice: invoice,\n idempotencyKey: paymentHash,\n });\n\n if (!sspResponse) {\n throw new Error(\"Failed to contact SSP\");\n }\n // test\n const leavesToRemove = new Set(leavesToSend.map((leaf) => leaf.leaf.id));\n this.leaves = this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id));\n\n return sspResponse;\n });\n }\n\n /**\n * Gets fee estimate for sending Lightning payments.\n *\n * @param {LightningSendFeeEstimateInput} params - Input parameters for fee estimation\n * @returns {Promise<number>} Fee estimate for sending Lightning payments\n */\n public async getLightningSendFeeEstimate({\n encodedInvoice,\n }: LightningSendFeeEstimateInput): Promise<number> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n const feeEstimate =\n await this.sspClient.getLightningSendFeeEstimate(encodedInvoice);\n\n if (!feeEstimate) {\n throw new Error(\"Failed to get lightning send fee estimate\");\n }\n const satsFeeEstimate = mapCurrencyAmount(feeEstimate.feeEstimate);\n return Math.ceil(satsFeeEstimate.sats);\n }\n\n // ***** Tree Creation Flow *****\n\n /**\n * Generates a deposit address for a tree.\n *\n * @param {number} vout - The vout index\n * @param {Uint8Array} parentSigningPubKey - The parent signing public key\n * @param {Transaction} [parentTx] - Optional parent transaction\n * @param {TreeNode} [parentNode] - Optional parent node\n * @returns {Promise<Object>} Deposit address information\n * @private\n */\n private async generateDepositAddressForTree(\n vout: number,\n parentSigningPubKey: Uint8Array,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ) {\n return await this.treeCreationService!.generateDepositAddressForTree(\n vout,\n parentSigningPubKey,\n parentTx,\n parentNode,\n );\n }\n\n /**\n * Creates a tree structure.\n *\n * @param {number} vout - The vout index\n * @param {DepositAddressTree} root - The root of the tree\n * @param {boolean} createLeaves - Whether to create leaves\n * @param {Transaction} [parentTx] - Optional parent transaction\n * @param {TreeNode} [parentNode] - Optional parent node\n * @returns {Promise<Object>} The created tree\n * @private\n */\n private async createTree(\n vout: number,\n root: DepositAddressTree,\n createLeaves: boolean,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ) {\n return await this.treeCreationService!.createTree(\n vout,\n root,\n createLeaves,\n parentTx,\n parentNode,\n );\n }\n\n // ***** Cooperative Exit Flow *****\n\n /**\n * Initiates a withdrawal to move funds from the Spark network to an on-chain Bitcoin address.\n *\n * @param {Object} params - Parameters for the withdrawal\n * @param {string} params.onchainAddress - The Bitcoin address where the funds should be sent\n * @param {number} [params.amountSats] - The amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds\n * @returns {Promise<CoopExitRequest | null | undefined>} The withdrawal request details, or null/undefined if the request cannot be completed\n */\n public async withdraw({\n onchainAddress,\n exitSpeed,\n amountSats,\n }: {\n onchainAddress: string;\n exitSpeed: ExitSpeed;\n amountSats?: number;\n }) {\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n return await this.withLeaves(async () => {\n return await this.coopExit(onchainAddress, exitSpeed, amountSats);\n });\n }\n\n /**\n * Internal method to perform a cooperative exit (withdrawal).\n *\n * @param {string} onchainAddress - The Bitcoin address where the funds should be sent\n * @param {number} [targetAmountSats] - The amount in satoshis to withdraw\n * @returns {Promise<Object | null | undefined>} The exit request details\n * @private\n */\n private async coopExit(\n onchainAddress: string,\n exitSpeed: ExitSpeed,\n targetAmountSats?: number,\n ) {\n if (!Number.isSafeInteger(targetAmountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"targetAmountSats\",\n value: targetAmountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n let leavesToSend: TreeNode[] = [];\n if (targetAmountSats) {\n leavesToSend = await this.selectLeaves(targetAmountSats);\n } else {\n leavesToSend = this.leaves.map((leaf) => ({\n ...leaf,\n }));\n }\n\n const feeEstimate = await this.sspClient?.getCoopExitFeeEstimate({\n leafExternalIds: leavesToSend.map((leaf) => leaf.id),\n withdrawalAddress: onchainAddress,\n });\n\n if (feeEstimate) {\n let fee: number | undefined;\n switch (exitSpeed) {\n case ExitSpeed.FAST:\n fee =\n (feeEstimate.speedFast?.l1BroadcastFee.originalValue || 0) +\n (feeEstimate.speedFast?.userFee.originalValue || 0);\n break;\n case ExitSpeed.MEDIUM:\n fee =\n (feeEstimate.speedMedium?.l1BroadcastFee.originalValue || 0) +\n (feeEstimate.speedMedium?.userFee.originalValue || 0);\n break;\n case ExitSpeed.SLOW:\n fee =\n (feeEstimate.speedSlow?.l1BroadcastFee.originalValue || 0) +\n (feeEstimate.speedSlow?.userFee.originalValue || 0);\n break;\n default:\n throw new ValidationError(\"Invalid exit speed\", {\n field: \"exitSpeed\",\n value: exitSpeed,\n expected: \"FAST, MEDIUM, or SLOW\",\n });\n }\n\n if (\n fee !== undefined &&\n fee > leavesToSend.reduce((acc, leaf) => acc + leaf.value, 0)\n ) {\n throw new ValidationError(\n \"The fee for the withdrawal is greater than the target amount\",\n {\n field: \"fee\",\n value: fee,\n expected: \"less than or equal to the target amount\",\n },\n );\n }\n }\n await this.checkRefreshTimelockNodes(leavesToSend);\n leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);\n\n const leafKeyTweaks = await Promise.all(\n leavesToSend.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const coopExitRequest = await this.sspClient?.requestCoopExit({\n leafExternalIds: leavesToSend.map((leaf) => leaf.id),\n withdrawalAddress: onchainAddress,\n idempotencyKey: uuidv7(),\n exitSpeed,\n });\n\n if (!coopExitRequest?.rawConnectorTransaction) {\n throw new Error(\"Failed to request coop exit\");\n }\n\n const connectorTx = getTxFromRawTxHex(\n coopExitRequest.rawConnectorTransaction,\n );\n\n const coopExitTxId = connectorTx.getInput(0).txid;\n const connectorTxId = getTxId(connectorTx);\n\n if (!coopExitTxId) {\n throw new Error(\"Failed to get coop exit tx id\");\n }\n\n const connectorOutputs: TransactionInput[] = [];\n for (let i = 0; i < connectorTx.outputsLength - 1; i++) {\n connectorOutputs.push({\n txid: hexToBytes(connectorTxId),\n index: i,\n });\n }\n\n const sspPubIdentityKey = hexToBytes(this.config.getSspIdentityPublicKey());\n const transfer = await this.coopExitService.getConnectorRefundSignatures({\n leaves: leafKeyTweaks,\n exitTxId: coopExitTxId,\n connectorOutputs,\n receiverPubKey: sspPubIdentityKey,\n });\n\n const completeResponse = await this.sspClient?.completeCoopExit({\n userOutboundTransferExternalId: transfer.transfer.id,\n coopExitRequestId: coopExitRequest.id,\n });\n\n return completeResponse;\n }\n\n /**\n * Gets fee estimate for cooperative exit (on-chain withdrawal).\n *\n * @param {Object} params - Input parameters for fee estimation\n * @param {number} params.amountSats - The amount in satoshis to withdraw\n * @param {string} params.withdrawalAddress - The Bitcoin address where the funds should be sent\n * @returns {Promise<CoopExitFeeEstimatesOutput | null>} Fee estimate for the withdrawal\n */\n public async getWithdrawalFeeEstimate({\n amountSats,\n withdrawalAddress,\n }: {\n amountSats: number;\n withdrawalAddress: string;\n }): Promise<CoopExitFeeEstimatesOutput | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n let leaves = await this.selectLeaves(amountSats);\n\n await this.checkRefreshTimelockNodes(leaves);\n leaves = await this.checkExtendTimeLockNodes(leaves);\n\n const feeEstimate = await this.sspClient.getCoopExitFeeEstimate({\n leafExternalIds: leaves.map((leaf) => leaf.id),\n withdrawalAddress,\n });\n\n return feeEstimate;\n }\n\n // ***** Token Flow *****\n\n /**\n * Synchronizes token outputs for the wallet.\n *\n * @returns {Promise<void>}\n * @private\n */\n protected async syncTokenOutputs() {\n this.tokenOutputs.clear();\n\n const unsortedTokenOutputs =\n await this.tokenTransactionService.fetchOwnedTokenOutputs(\n [await this.config.signer.getIdentityPublicKey()],\n [],\n );\n\n const filteredTokenOutputs = unsortedTokenOutputs.filter(\n (output) =>\n !this.pendingWithdrawnOutputIds.includes(output.output?.id || \"\"),\n );\n\n const fetchedOutputIds = new Set(\n unsortedTokenOutputs.map((output) => output.output?.id).filter(Boolean),\n );\n this.pendingWithdrawnOutputIds = this.pendingWithdrawnOutputIds.filter(\n (id) => fetchedOutputIds.has(id),\n );\n\n // Group leaves by token key\n const groupedOutputs = new Map<\n string,\n OutputWithPreviousTransactionData[]\n >();\n\n filteredTokenOutputs.forEach((output) => {\n const tokenKey = bytesToHex(output.output!.tokenPublicKey!);\n const index = output.previousTransactionVout!;\n\n if (!groupedOutputs.has(tokenKey)) {\n groupedOutputs.set(tokenKey, []);\n }\n\n groupedOutputs.get(tokenKey)!.push({\n ...output,\n previousTransactionVout: index,\n });\n });\n\n this.tokenOutputs = groupedOutputs;\n }\n\n /**\n * Transfers tokens to another user.\n *\n * @param {Object} params - Parameters for the token transfer\n * @param {string} params.tokenPublicKey - The public key of the token to transfer\n * @param {bigint} params.tokenAmount - The amount of tokens to transfer\n * @param {string} params.receiverSparkAddress - The recipient's public key\n * @param {OutputWithPreviousTransactionData[]} [params.selectedOutputs] - Optional specific leaves to use for the transfer\n * @returns {Promise<string>} The transaction ID of the token transfer\n */\n public async transferTokens({\n tokenPublicKey,\n tokenAmount,\n receiverSparkAddress,\n selectedOutputs,\n }: {\n tokenPublicKey: string;\n tokenAmount: bigint;\n receiverSparkAddress: string;\n selectedOutputs?: OutputWithPreviousTransactionData[];\n }): Promise<string> {\n await this.syncTokenOutputs();\n\n return this.tokenTransactionService.tokenTransfer(\n this.tokenOutputs,\n [\n {\n tokenPublicKey,\n tokenAmount,\n receiverSparkAddress,\n },\n ],\n selectedOutputs,\n );\n }\n\n /**\n * Transfers tokens with multiple outputs\n *\n * @param {Array} receiverOutputs - Array of transfer parameters\n * @param {string} receiverOutputs[].tokenPublicKey - The public key of the token to transfer\n * @param {bigint} receiverOutputs[].tokenAmount - The amount of tokens to transfer\n * @param {string} receiverOutputs[].receiverSparkAddress - The recipient's public key\n * @param {OutputWithPreviousTransactionData[]} [selectedOutputs] - Optional specific leaves to use for the transfer\n * @returns {Promise<string[]>} Array of transaction IDs for the token transfers\n */\n public async batchTransferTokens(\n receiverOutputs: {\n tokenPublicKey: string;\n tokenAmount: bigint;\n receiverSparkAddress: string;\n }[],\n selectedOutputs?: OutputWithPreviousTransactionData[],\n ): Promise<string> {\n if (receiverOutputs.length === 0) {\n throw new ValidationError(\"At least one receiver output is required\", {\n field: \"receiverOutputs\",\n value: receiverOutputs,\n expected: \"Non-empty array\",\n });\n }\n const firstTokenPublicKey = receiverOutputs[0]!.tokenPublicKey;\n const allSameToken = receiverOutputs.every(\n (output) => output.tokenPublicKey === firstTokenPublicKey,\n );\n if (!allSameToken) {\n throw new ValidationError(\n \"All receiver outputs must have the same token public key\",\n {\n field: \"receiverOutputs\",\n value: receiverOutputs,\n expected: \"All outputs must have the same token public key\",\n },\n );\n }\n\n await this.syncTokenOutputs();\n\n return this.tokenTransactionService.tokenTransfer(\n this.tokenOutputs,\n receiverOutputs,\n selectedOutputs,\n );\n }\n\n public async queryTokenTransactions(\n tokenPublicKeys: string[],\n tokenTransactionHashes?: string[],\n ): Promise<TokenTransactionWithStatus[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let queryParams;\n if (tokenTransactionHashes?.length) {\n queryParams = {\n tokenPublicKeys: tokenPublicKeys?.map(hexToBytes)!,\n ownerPublicKeys: [hexToBytes(await this.getIdentityPublicKey())],\n tokenTransactionHashes: tokenTransactionHashes.map(hexToBytes),\n };\n } else {\n queryParams = {\n tokenPublicKeys: tokenPublicKeys?.map(hexToBytes)!,\n ownerPublicKeys: [hexToBytes(await this.getIdentityPublicKey())],\n };\n }\n\n const response = await sparkClient.query_token_transactions(queryParams);\n return response.tokenTransactionsWithStatus;\n }\n\n public async getTokenL1Address(): Promise<string> {\n return getP2WPKHAddressFromPublicKey(\n await this.config.signer.getIdentityPublicKey(),\n this.config.getNetwork(),\n );\n }\n\n /**\n * Signs a message with the identity key.\n *\n * @param {string} message - The message to sign\n * @param {boolean} [compact] - Whether to use compact encoding. If false, the message will be encoded as DER.\n * @returns {Promise<string>} The signed message\n */\n public async signMessageWithIdentityKey(\n message: string,\n compact?: boolean,\n ): Promise<string> {\n const hash = sha256(message);\n const signature = await this.config.signer.signMessageWithIdentityKey(\n hash,\n compact,\n );\n return bytesToHex(signature);\n }\n\n /**\n * Validates a message with the identity key.\n *\n * @param {string} message - The original message that was signed\n * @param {string | Uint8Array} signature - Signature to validate\n * @returns {Promise<boolean>} Whether the message is valid\n */\n public async validateMessageWithIdentityKey(\n message: string,\n signature: string | Uint8Array,\n ): Promise<boolean> {\n const hash = sha256(message);\n if (typeof signature === \"string\") {\n signature = hexToBytes(signature);\n }\n return this.config.signer.validateMessageWithIdentityKey(hash, signature);\n }\n\n /**\n * Get a Lightning receive request by ID.\n *\n * @param {string} id - The ID of the Lightning receive request\n * @returns {Promise<LightningReceiveRequest | null>} The Lightning receive request\n */\n public async getLightningReceiveRequest(\n id: string,\n ): Promise<LightningReceiveRequest | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n return await this.sspClient.getLightningReceiveRequest(id);\n }\n\n /**\n * Get a Lightning send request by ID.\n *\n * @param {string} id - The ID of the Lightning send request\n * @returns {Promise<LightningSendRequest | null>} The Lightning send request\n */\n public async getLightningSendRequest(\n id: string,\n ): Promise<LightningSendRequest | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n return await this.sspClient.getLightningSendRequest(id);\n }\n\n /**\n * Get a coop exit request by ID.\n *\n * @param {string} id - The ID of the coop exit request\n * @returns {Promise<CoopExitRequest | null>} The coop exit request\n */\n public async getCoopExitRequest(id: string): Promise<CoopExitRequest | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n return await this.sspClient.getCoopExitRequest(id);\n }\n\n private cleanup() {\n if (this.claimTransfersInterval) {\n clearInterval(this.claimTransfersInterval);\n this.claimTransfersInterval = null;\n }\n this.streamController?.abort();\n this.removeAllListeners();\n }\n\n public async cleanupConnections() {\n this.cleanup();\n await this.connectionManager.closeConnections();\n }\n\n // Add this new method to start periodic claiming\n private startPeriodicClaimTransfers() {\n // Clear any existing interval first\n if (this.claimTransfersInterval) {\n clearInterval(this.claimTransfersInterval);\n }\n\n // Set up new interval to claim transfers every 5 seconds\n // @ts-ignore\n this.claimTransfersInterval = setInterval(async () => {\n try {\n await this.claimTransfers(undefined, true);\n } catch (error) {\n console.error(\"Error in periodic transfer claiming:\", error);\n }\n }, 10000);\n }\n}\n","import {\n AuthProvider,\n bytesToHex,\n DefaultCrypto,\n NodeKeyCache,\n Query,\n Requester,\n} from \"@lightsparkdev/core\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { AuthenticationError, NetworkError } from \"../errors/index.js\";\nimport { SparkSigner } from \"../signer/signer.js\";\nimport { CompleteCoopExit } from \"./mutations/CompleteCoopExit.js\";\nimport { CompleteLeavesSwap } from \"./mutations/CompleteLeavesSwap.js\";\nimport { GetChallenge } from \"./mutations/GetChallenge.js\";\nimport { RequestCoopExit } from \"./mutations/RequestCoopExit.js\";\nimport { RequestLightningReceive } from \"./mutations/RequestLightningReceive.js\";\nimport { RequestLightningSend } from \"./mutations/RequestLightningSend.js\";\nimport { RequestSwapLeaves } from \"./mutations/RequestSwapLeaves.js\";\nimport { VerifyChallenge } from \"./mutations/VerifyChallenge.js\";\nimport { CoopExitFeeEstimatesOutputFromJson } from \"./objects/CoopExitFeeEstimatesOutput.js\";\nimport CoopExitRequest, {\n CoopExitRequestFromJson,\n} from \"./objects/CoopExitRequest.js\";\nimport { GetChallengeOutputFromJson } from \"./objects/GetChallengeOutput.js\";\nimport type {\n CompleteCoopExitInput,\n CompleteLeavesSwapInput,\n CoopExitFeeEstimatesInput,\n CoopExitFeeEstimatesOutput,\n GetChallengeOutput,\n LeavesSwapFeeEstimateOutput,\n LightningSendRequest,\n RequestCoopExitInput,\n RequestLeavesSwapInput,\n RequestLightningReceiveInput,\n RequestLightningSendInput,\n} from \"./objects/index.js\";\nimport { LeavesSwapFeeEstimateOutputFromJson } from \"./objects/LeavesSwapFeeEstimateOutput.js\";\nimport LeavesSwapRequest, {\n LeavesSwapRequestFromJson,\n} from \"./objects/LeavesSwapRequest.js\";\nimport LightningReceiveRequest, {\n LightningReceiveRequestFromJson,\n} from \"./objects/LightningReceiveRequest.js\";\nimport LightningSendFeeEstimateOutput, {\n LightningSendFeeEstimateOutputFromJson,\n} from \"./objects/LightningSendFeeEstimateOutput.js\";\nimport { LightningSendRequestFromJson } from \"./objects/LightningSendRequest.js\";\nimport VerifyChallengeOutput, {\n VerifyChallengeOutputFromJson,\n} from \"./objects/VerifyChallengeOutput.js\";\nimport { CoopExitFeeEstimate } from \"./queries/CoopExitFeeEstimate.js\";\nimport { LeavesSwapFeeEstimate } from \"./queries/LeavesSwapFeeEstimate.js\";\nimport { LightningSendFeeEstimate } from \"./queries/LightningSendFeeEstimate.js\";\nimport { UserRequest } from \"./queries/UserRequest.js\";\n\nexport interface SspClientOptions {\n baseUrl: string;\n identityPublicKey: string;\n schemaEndpoint?: string;\n}\n\nexport interface MayHaveSspClientOptions {\n readonly sspClientOptions?: SspClientOptions;\n}\n\nexport interface HasSspClientOptions {\n readonly sspClientOptions: SspClientOptions;\n}\n\nexport default class SspClient {\n private readonly requester: Requester;\n\n private readonly signer: SparkSigner;\n private readonly authProvider: SparkAuthProvider;\n\n constructor(\n config: HasSspClientOptions & {\n signer: SparkSigner;\n },\n ) {\n this.signer = config.signer;\n this.authProvider = new SparkAuthProvider();\n\n const fetchFunction =\n typeof window !== \"undefined\" ? window.fetch.bind(window) : fetch;\n const options = config.sspClientOptions;\n\n this.requester = new Requester(\n new NodeKeyCache(DefaultCrypto),\n options.schemaEndpoint || `graphql/spark/2025-03-19`,\n `spark-sdk/0.0.0`,\n this.authProvider,\n options.baseUrl,\n DefaultCrypto,\n undefined,\n fetchFunction,\n );\n }\n\n async executeRawQuery<T>(\n query: Query<T>,\n needsAuth: boolean = true,\n ): Promise<T | null> {\n if (needsAuth && !(await this.authProvider.isAuthorized())) {\n await this.authenticate();\n }\n\n try {\n return await this.requester.executeQuery(query);\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.toLowerCase().includes(\"unauthorized\")\n ) {\n try {\n await this.authenticate();\n return await this.requester.executeQuery(query);\n } catch (authError) {\n throw new AuthenticationError(\n \"Failed to authenticate after unauthorized response\",\n {\n endpoint: \"graphql\",\n reason: error.message,\n },\n authError as Error,\n );\n }\n }\n throw new NetworkError(\n \"Failed to execute GraphQL query\",\n {\n method: \"POST\",\n },\n error as Error,\n );\n }\n }\n\n async getSwapFeeEstimate(\n amountSats: number,\n ): Promise<LeavesSwapFeeEstimateOutput | null> {\n return await this.executeRawQuery({\n queryPayload: LeavesSwapFeeEstimate,\n variables: {\n total_amount_sats: amountSats,\n },\n constructObject: (response: { leaves_swap_fee_estimate: any }) => {\n return LeavesSwapFeeEstimateOutputFromJson(\n response.leaves_swap_fee_estimate,\n );\n },\n });\n }\n\n async getLightningSendFeeEstimate(\n encodedInvoice: string,\n ): Promise<LightningSendFeeEstimateOutput | null> {\n return await this.executeRawQuery({\n queryPayload: LightningSendFeeEstimate,\n variables: {\n encoded_invoice: encodedInvoice,\n },\n constructObject: (response: { lightning_send_fee_estimate: any }) => {\n return LightningSendFeeEstimateOutputFromJson(\n response.lightning_send_fee_estimate,\n );\n },\n });\n }\n\n async getCoopExitFeeEstimate({\n leafExternalIds,\n withdrawalAddress,\n }: CoopExitFeeEstimatesInput): Promise<CoopExitFeeEstimatesOutput | null> {\n return await this.executeRawQuery({\n queryPayload: CoopExitFeeEstimate,\n variables: {\n leaf_external_ids: leafExternalIds,\n withdrawal_address: withdrawalAddress,\n },\n constructObject: (response: { coop_exit_fee_estimates: any }) => {\n return CoopExitFeeEstimatesOutputFromJson(\n response.coop_exit_fee_estimates,\n );\n },\n });\n }\n\n // TODO: Might not need\n async getCurrentUser() {\n throw new Error(\"Not implemented\");\n }\n\n async completeCoopExit({\n userOutboundTransferExternalId,\n coopExitRequestId,\n }: CompleteCoopExitInput): Promise<CoopExitRequest | null> {\n return await this.executeRawQuery({\n queryPayload: CompleteCoopExit,\n variables: {\n user_outbound_transfer_external_id: userOutboundTransferExternalId,\n coop_exit_request_id: coopExitRequestId,\n },\n constructObject: (response: { complete_coop_exit: any }) => {\n return CoopExitRequestFromJson(response.complete_coop_exit.request);\n },\n });\n }\n\n async requestCoopExit({\n leafExternalIds,\n withdrawalAddress,\n idempotencyKey,\n exitSpeed,\n }: RequestCoopExitInput): Promise<CoopExitRequest | null> {\n return await this.executeRawQuery({\n queryPayload: RequestCoopExit,\n variables: {\n leaf_external_ids: leafExternalIds,\n withdrawal_address: withdrawalAddress,\n idempotency_key: idempotencyKey,\n exit_speed: exitSpeed,\n },\n constructObject: (response: { request_coop_exit: any }) => {\n return CoopExitRequestFromJson(response.request_coop_exit.request);\n },\n });\n }\n\n // TODO: Lets name this better\n async requestLightningReceive({\n amountSats,\n network,\n paymentHash,\n expirySecs,\n memo,\n }: RequestLightningReceiveInput): Promise<LightningReceiveRequest | null> {\n return await this.executeRawQuery({\n queryPayload: RequestLightningReceive,\n variables: {\n amount_sats: amountSats,\n network: network,\n payment_hash: paymentHash,\n expiry_secs: expirySecs,\n memo: memo,\n },\n constructObject: (response: { request_lightning_receive: any }) => {\n return LightningReceiveRequestFromJson(\n response.request_lightning_receive.request,\n );\n },\n });\n }\n\n async requestLightningSend({\n encodedInvoice,\n idempotencyKey,\n }: RequestLightningSendInput): Promise<LightningSendRequest | null> {\n return await this.executeRawQuery({\n queryPayload: RequestLightningSend,\n variables: {\n encoded_invoice: encodedInvoice,\n idempotency_key: idempotencyKey,\n },\n constructObject: (response: { request_lightning_send: any }) => {\n return LightningSendRequestFromJson(\n response.request_lightning_send.request,\n );\n },\n });\n }\n\n async requestLeaveSwap({\n adaptorPubkey,\n totalAmountSats,\n targetAmountSats,\n feeSats,\n userLeaves,\n idempotencyKey,\n }: RequestLeavesSwapInput): Promise<LeavesSwapRequest | null> {\n const query = {\n queryPayload: RequestSwapLeaves,\n variables: {\n adaptor_pubkey: adaptorPubkey,\n total_amount_sats: totalAmountSats,\n target_amount_sats: targetAmountSats,\n fee_sats: feeSats,\n user_leaves: userLeaves,\n idempotency_key: idempotencyKey,\n },\n constructObject: (response: { request_leaves_swap: any }) => {\n if (!response.request_leaves_swap) {\n return null;\n }\n\n return LeavesSwapRequestFromJson(response.request_leaves_swap.request);\n },\n };\n return await this.executeRawQuery(query);\n }\n\n async completeLeaveSwap({\n adaptorSecretKey,\n userOutboundTransferExternalId,\n leavesSwapRequestId,\n }: CompleteLeavesSwapInput): Promise<LeavesSwapRequest | null> {\n return await this.executeRawQuery({\n queryPayload: CompleteLeavesSwap,\n variables: {\n adaptor_secret_key: adaptorSecretKey,\n user_outbound_transfer_external_id: userOutboundTransferExternalId,\n leaves_swap_request_id: leavesSwapRequestId,\n },\n constructObject: (response: { complete_leaves_swap: any }) => {\n return LeavesSwapRequestFromJson(response.complete_leaves_swap.request);\n },\n });\n }\n\n async getLightningReceiveRequest(\n id: string,\n ): Promise<LightningReceiveRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return LightningReceiveRequestFromJson(response.user_request);\n },\n });\n }\n\n async getLightningSendRequest(\n id: string,\n ): Promise<LightningSendRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return LightningSendRequestFromJson(response.user_request);\n },\n });\n }\n\n async getLeaveSwapRequest(id: string): Promise<LeavesSwapRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return LeavesSwapRequestFromJson(response.user_request);\n },\n });\n }\n\n async getCoopExitRequest(id: string): Promise<CoopExitRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return CoopExitRequestFromJson(response.user_request);\n },\n });\n }\n\n async getChallenge(): Promise<GetChallengeOutput | null> {\n return await this.executeRawQuery(\n {\n queryPayload: GetChallenge,\n variables: {\n public_key: bytesToHex(await this.signer.getIdentityPublicKey()),\n },\n constructObject: (response: { get_challenge: any }) => {\n return GetChallengeOutputFromJson(response.get_challenge);\n },\n },\n false,\n );\n }\n\n async verifyChallenge(\n signature: string,\n protectedChallenge: string,\n ): Promise<VerifyChallengeOutput | null> {\n return await this.executeRawQuery(\n {\n queryPayload: VerifyChallenge,\n variables: {\n protected_challenge: protectedChallenge,\n signature: signature,\n identity_public_key: bytesToHex(\n await this.signer.getIdentityPublicKey(),\n ),\n },\n constructObject: (response: any) => {\n return VerifyChallengeOutputFromJson(response.verify_challenge);\n },\n },\n false,\n );\n }\n\n async authenticate() {\n this.authProvider.removeAuth();\n\n const challenge = await this.getChallenge();\n if (!challenge) {\n throw new Error(\"Failed to get challenge\");\n }\n\n const challengeBytes = Buffer.from(challenge.protectedChallenge, \"base64\");\n const signature = await this.signer.signMessageWithIdentityKey(\n sha256(challengeBytes),\n );\n\n const verifyChallenge = await this.verifyChallenge(\n Buffer.from(signature).toString(\"base64\"),\n challenge.protectedChallenge,\n );\n if (!verifyChallenge) {\n throw new Error(\"Failed to verify challenge\");\n }\n\n this.authProvider.setAuth(\n verifyChallenge.sessionToken,\n new Date(verifyChallenge.validUntil),\n );\n }\n}\n\nclass SparkAuthProvider implements AuthProvider {\n private sessionToken: string | undefined;\n private validUntil: Date | undefined;\n\n async addAuthHeaders(\n headers: Record<string, string>,\n ): Promise<Record<string, string>> {\n const _headers = {\n \"Content-Type\": \"application/json\",\n ...headers,\n };\n\n if (this.sessionToken) {\n _headers[\"Authorization\"] = `Bearer ${this.sessionToken}`;\n }\n\n return Promise.resolve(_headers);\n }\n\n async isAuthorized(): Promise<boolean> {\n return (\n !!this.sessionToken && !!this.validUntil && this.validUntil > new Date()\n );\n }\n\n async addWsConnectionParams(\n params: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n const _params = {\n ...params,\n };\n\n if (this.sessionToken) {\n _params[\"Authorization\"] = `Bearer ${this.sessionToken}`;\n }\n\n return Promise.resolve(_params);\n }\n\n setAuth(sessionToken: string, validUntil: Date) {\n this.sessionToken = sessionToken;\n this.validUntil = validUntil;\n }\n\n removeAuth() {\n this.sessionToken = undefined;\n this.validUntil = undefined;\n }\n}\n","import { FRAGMENT as CompleteCoopExitOutputFragment } from \"../objects/CoopExitRequest.js\";\n\nexport const CompleteCoopExit = `\n mutation CompleteCoopExit(\n $user_outbound_transfer_external_id: UUID!\n $coop_exit_request_id: ID!\n ) {\n complete_coop_exit(input: {\n user_outbound_transfer_external_id: $user_outbound_transfer_external_id\n coop_exit_request_id: $coop_exit_request_id\n }) {\n request {\n ...CoopExitRequestFragment\n }\n }\n }\n \n ${CompleteCoopExitOutputFragment}\n`;\n","import { FRAGMENT as LeavesSwapRequestFragment } from \"../objects/LeavesSwapRequest.js\";\n\nexport const CompleteLeavesSwap = `\n mutation CompleteLeavesSwap(\n $adaptor_secret_key: String!\n $user_outbound_transfer_external_id: UUID!\n $leaves_swap_request_id: ID!\n ) {\n complete_leaves_swap(input: { adaptor_secret_key: $adaptor_secret_key, user_outbound_transfer_external_id: $user_outbound_transfer_external_id, leaves_swap_request_id: $leaves_swap_request_id }) {\n request {\n ...LeavesSwapRequestFragment\n }\n }\n }\n\n ${LeavesSwapRequestFragment}\n`;\n","import { FRAGMENT as GetChallengeOutputFragment } from \"../objects/GetChallengeOutput.js\";\n\nexport const GetChallenge = `\n mutation GetChallenge(\n $public_key: PublicKey!\n ) {\n get_challenge(input: {\n public_key: $public_key\n }) {\n ...GetChallengeOutputFragment\n }\n }\n \n ${GetChallengeOutputFragment}\n`;\n","import { FRAGMENT as RequestCoopExitOutputFragment } from \"../objects/CoopExitRequest.js\";\n\nexport const RequestCoopExit = `\n mutation RequestCoopExit(\n $leaf_external_ids: [UUID!]!\n $withdrawal_address: String!\n $idempotency_key: String!\n $exit_speed: ExitSpeed!\n ) {\n request_coop_exit(\n input: {\n leaf_external_ids: $leaf_external_ids\n withdrawal_address: $withdrawal_address\n idempotency_key: $idempotency_key\n exit_speed: $exit_speed\n }\n ) {\n request {\n ...CoopExitRequestFragment\n }\n }\n }\n ${RequestCoopExitOutputFragment}\n`;\n","import { FRAGMENT as RequestLightningReceiveOutputFragment } from \"../objects/LightningReceiveRequest.js\";\n\nexport const RequestLightningReceive = `\n mutation RequestLightningReceive(\n $network: BitcoinNetwork!\n $amount_sats: Long!\n $payment_hash: Hash32!\n $expiry_secs: Int\n $memo: String\n ) {\n request_lightning_receive(\n input: {\n network: $network\n amount_sats: $amount_sats\n payment_hash: $payment_hash\n expiry_secs: $expiry_secs\n memo: $memo\n }\n ) {\n request {\n ...LightningReceiveRequestFragment\n }\n }\n }\n ${RequestLightningReceiveOutputFragment}\n`;\n","import { FRAGMENT as RequestLightningSendOutputFragment } from \"../objects/LightningSendRequest.js\";\nexport const RequestLightningSend = `\n mutation RequestLightningSend(\n $encoded_invoice: String!\n $idempotency_key: String!\n ) {\n request_lightning_send(input: {\n encoded_invoice: $encoded_invoice\n idempotency_key: $idempotency_key\n }) {\n request {\n ...LightningSendRequestFragment\n }\n }\n }\n ${RequestLightningSendOutputFragment}\n`;\n","import { FRAGMENT as LeavesSwapRequestFragment } from \"../objects/LeavesSwapRequest.js\";\n\nexport const RequestSwapLeaves = `\n mutation RequestSwapLeaves(\n $adaptor_pubkey: PublicKey!\n $total_amount_sats: Long!\n $target_amount_sats: Long!\n $fee_sats: Long!\n $user_leaves: [UserLeafInput!]!\n $idempotency_key: String!\n ) {\n request_leaves_swap(input: {\n adaptor_pubkey: $adaptor_pubkey\n total_amount_sats: $total_amount_sats\n target_amount_sats: $target_amount_sats\n fee_sats: $fee_sats\n user_leaves: $user_leaves\n idempotency_key: $idempotency_key\n }) {\n request {\n ...LeavesSwapRequestFragment\n }\n }\n }\n ${LeavesSwapRequestFragment}\n`;\n","import { FRAGMENT as VerifyChallengeOutputFragment } from \"../objects/VerifyChallengeOutput.js\";\n\nexport const VerifyChallenge = `\n mutation VerifyChallenge(\n $protected_challenge: String!\n $signature: String!\n $identity_public_key: PublicKey!\n $provider: Provider\n ) {\n verify_challenge(input: {\n protected_challenge: $protected_challenge\n signature: $signature\n identity_public_key: $identity_public_key\n provider: $provider\n }) {\n ...VerifyChallengeOutputFragment\n }\n }\n \n ${VerifyChallengeOutputFragment}\n`;\n","import { FRAGMENT as CoopExitFeeEstimatesOutputFragment } from \"../objects/CoopExitFeeEstimatesOutput.js\";\n\nexport const CoopExitFeeEstimate = `\n query CoopExitFeeEstimate(\n $leaf_external_ids: [UUID!]!\n $withdrawal_address: String!\n ) {\n coop_exit_fee_estimates(\n input: {\n leaf_external_ids: $leaf_external_ids\n withdrawal_address: $withdrawal_address\n }\n ) {\n ...CoopExitFeeEstimatesOutputFragment\n }\n }\n ${CoopExitFeeEstimatesOutputFragment}\n`;\n","import { FRAGMENT as LeavesSwapFeeEstimateOutputFragment } from \"../objects/LeavesSwapFeeEstimateOutput.js\";\n\nexport const LeavesSwapFeeEstimate = `\n query LeavesSwapFeeEstimate(\n $total_amount_sats: Int!\n ) {\n leaves_swap_fee_estimate(\n input: {\n total_amount_sats: $total_amount_sats\n }\n ) {\n ...LeavesSwapFeeEstimateOutputFragment\n }\n }\n ${LeavesSwapFeeEstimateOutputFragment}\n`;\n","import { FRAGMENT as LightningSendFeeEstimateOutputFragment } from \"../objects/LightningSendFeeEstimateOutput.js\";\n\nexport const LightningSendFeeEstimate = `\n query LightningSendFeeEstimate(\n $encoded_invoice: String!\n ) {\n lightning_send_fee_estimate(\n input: {\n encoded_invoice: $encoded_invoice\n }\n ) {\n ...LightningSendFeeEstimateOutputFragment\n }\n }\n ${LightningSendFeeEstimateOutputFragment}\n`;\n","import { FRAGMENT as UserRequestFragment } from \"../objects/UserRequest.js\";\n\nexport const UserRequest = `\n query UserRequest($request_id: ID!) {\n user_request(request_id: $request_id) {\n ...UserRequestFragment\n }\n }\n ${UserRequestFragment}\n`;\n","import { Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { uuidv7 } from \"uuidv7\";\nimport { NetworkError, ValidationError } from \"../errors/types.js\";\nimport {\n CooperativeExitResponse,\n LeafRefundTxSigningJob,\n Transfer,\n} from \"../proto/spark.js\";\nimport {\n getP2TRScriptFromPublicKey,\n getTxFromRawTxBytes,\n} from \"../utils/bitcoin.js\";\nimport { getCrypto } from \"../utils/crypto.js\";\nimport { Network } from \"../utils/network.js\";\nimport { getNextTransactionSequence } from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport {\n BaseTransferService,\n LeafKeyTweak,\n LeafRefundSigningData,\n} from \"./transfer.js\";\n\nconst crypto = getCrypto();\n\nexport type GetConnectorRefundSignaturesParams = {\n leaves: LeafKeyTweak[];\n exitTxId: Uint8Array;\n connectorOutputs: TransactionInput[];\n receiverPubKey: Uint8Array;\n};\n\nexport class CoopExitService extends BaseTransferService {\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n super(config, connectionManager);\n }\n\n async getConnectorRefundSignatures({\n leaves,\n exitTxId,\n connectorOutputs,\n receiverPubKey,\n }: GetConnectorRefundSignaturesParams): Promise<{\n transfer: Transfer;\n signaturesMap: Map<string, Uint8Array>;\n }> {\n const { transfer, signaturesMap } = await this.signCoopExitRefunds(\n leaves,\n exitTxId,\n connectorOutputs,\n receiverPubKey,\n );\n const transferTweak = await this.sendTransferTweakKey(\n transfer,\n leaves,\n signaturesMap,\n );\n\n return { transfer: transferTweak, signaturesMap };\n }\n\n private createConnectorRefundTransaction(\n sequence: number,\n nodeOutPoint: TransactionInput,\n connectorOutput: TransactionInput,\n amountSats: bigint,\n receiverPubKey: Uint8Array,\n ): Transaction {\n const refundTx = new Transaction();\n if (!nodeOutPoint.txid || nodeOutPoint.index === undefined) {\n throw new ValidationError(\"Invalid node outpoint\", {\n field: \"nodeOutPoint\",\n value: { txid: nodeOutPoint.txid, index: nodeOutPoint.index },\n expected: \"Both txid and index must be defined\",\n });\n }\n refundTx.addInput({\n txid: nodeOutPoint.txid,\n index: nodeOutPoint.index,\n sequence,\n });\n\n refundTx.addInput(connectorOutput);\n const receiverScript = getP2TRScriptFromPublicKey(\n receiverPubKey,\n this.config.getNetwork(),\n );\n\n refundTx.addOutput({\n script: receiverScript,\n amount: amountSats,\n });\n\n return refundTx;\n }\n private async signCoopExitRefunds(\n leaves: LeafKeyTweak[],\n exitTxId: Uint8Array,\n connectorOutputs: TransactionInput[],\n receiverPubKey: Uint8Array,\n ): Promise<{ transfer: Transfer; signaturesMap: Map<string, Uint8Array> }> {\n if (leaves.length !== connectorOutputs.length) {\n throw new ValidationError(\n \"Mismatch between leaves and connector outputs\",\n {\n field: \"leaves/connectorOutputs\",\n value: {\n leavesCount: leaves.length,\n outputsCount: connectorOutputs.length,\n },\n expected: \"Equal length\",\n },\n );\n }\n\n const signingJobs: LeafRefundTxSigningJob[] = [];\n const leafDataMap: Map<string, LeafRefundSigningData> = new Map();\n\n for (let i = 0; i < leaves.length; i++) {\n const leaf = leaves[i];\n if (!leaf) {\n throw new ValidationError(\"Missing leaf\", {\n field: \"leaf\",\n value: leaf,\n expected: \"Valid leaf object\",\n });\n }\n const connectorOutput = connectorOutputs[i];\n if (!connectorOutput) {\n throw new ValidationError(\"Missing connector output\", {\n field: \"connectorOutput\",\n value: connectorOutput,\n expected: \"Valid connector output\",\n });\n }\n const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n\n const { nextSequence } = getNextTransactionSequence(\n currentRefundTx.getInput(0).sequence,\n );\n\n const refundTx = this.createConnectorRefundTransaction(\n nextSequence,\n currentRefundTx.getInput(0),\n connectorOutput,\n BigInt(leaf.leaf.value),\n receiverPubKey,\n );\n\n const signingNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const signingJob: LeafRefundTxSigningJob = {\n leafId: leaf.leaf.id,\n refundTxSigningJob: {\n signingPublicKey: leaf.signingPubKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: signingNonceCommitment,\n },\n };\n\n signingJobs.push(signingJob);\n const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n leafDataMap.set(leaf.leaf.id, {\n signingPubKey: leaf.signingPubKey,\n refundTx,\n signingNonceCommitment,\n tx,\n vout: leaf.leaf.vout,\n receivingPubkey: receiverPubKey,\n });\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: CooperativeExitResponse;\n try {\n response = await sparkClient.cooperative_exit({\n transfer: {\n transferId: uuidv7(),\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverPubKey,\n expiryTime:\n this.config.getNetwork() == Network.MAINNET\n ? new Date(Date.now() + 2 * 24 * 60 * 60 * 1000 + 5 * 60 * 1000)\n : new Date(Date.now() + 5 * 60 * 1000), // 48 hours 5 min for mainnet, 5 min otherwise\n },\n exitId: uuidv7(),\n exitTxid: exitTxId,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to initiate cooperative exit\",\n {\n operation: \"cooperative_exit\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n if (!response.transfer) {\n throw new NetworkError(\"Failed to initiate cooperative exit\", {\n operation: \"cooperative_exit\",\n errors: \"No transfer in response\",\n });\n }\n\n const signatures = await this.signRefunds(\n leafDataMap,\n response.signingResults,\n );\n\n const signaturesMap: Map<string, Uint8Array> = new Map();\n for (const signature of signatures) {\n signaturesMap.set(signature.nodeId, signature.refundTxSignature);\n }\n\n return { transfer: response.transfer, signaturesMap };\n }\n}\n","import {\n bytesToHex,\n equalBytes,\n hexToBytes,\n numberToBytesBE,\n} from \"@noble/curves/abstract/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport * as ecies from \"eciesjs\";\nimport { uuidv7 } from \"uuidv7\";\nimport {\n NetworkError,\n SparkSDKError,\n ValidationError,\n} from \"../errors/index.js\";\nimport { SignatureIntent } from \"../proto/common.js\";\nimport {\n ClaimLeafKeyTweak,\n ClaimTransferSignRefundsResponse,\n CounterLeafSwapResponse,\n FinalizeTransferResponse,\n LeafRefundTxSigningJob,\n LeafRefundTxSigningResult,\n NodeSignatures,\n QueryTransfersResponse,\n SecretProof,\n SendLeafKeyTweak,\n SigningJob,\n Transfer,\n TransferStatus,\n TransferType,\n TreeNode,\n} from \"../proto/spark.js\";\nimport { SigningCommitment } from \"../signer/signer.js\";\nimport {\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxId,\n} from \"../utils/bitcoin.js\";\nimport { getCrypto } from \"../utils/crypto.js\";\nimport { VerifiableSecretShare } from \"../utils/secret-sharing.js\";\nimport {\n createRefundTx,\n getEphemeralAnchorOutput,\n getNextTransactionSequence,\n getTransactionSequence,\n} from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport { SigningOperator } from \"./wallet-config.js\";\nconst INITIAL_TIME_LOCK = 2000;\n\nconst DEFAULT_EXPIRY_TIME = 10 * 60 * 1000;\n\nfunction initialSequence() {\n return (1 << 30) | INITIAL_TIME_LOCK;\n}\n\nconst crypto = getCrypto();\n\nexport type LeafKeyTweak = {\n leaf: TreeNode;\n signingPubKey: Uint8Array;\n newSigningPubKey: Uint8Array;\n};\n\nexport type ClaimLeafData = {\n signingPubKey: Uint8Array;\n tx?: Transaction;\n refundTx?: Transaction;\n signingNonceCommitment: SigningCommitment;\n vout?: number;\n};\n\nexport type LeafRefundSigningData = {\n signingPubKey: Uint8Array;\n receivingPubkey: Uint8Array;\n tx: Transaction;\n refundTx?: Transaction;\n signingNonceCommitment: SigningCommitment;\n vout: number;\n};\n\nexport class BaseTransferService {\n protected readonly config: WalletConfigService;\n protected readonly connectionManager: ConnectionManager;\n\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n this.config = config;\n this.connectionManager = connectionManager;\n }\n\n async sendTransferTweakKey(\n transfer: Transfer,\n leaves: LeafKeyTweak[],\n refundSignatureMap: Map<string, Uint8Array>,\n ): Promise<Transfer> {\n const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(\n transfer,\n leaves,\n refundSignatureMap,\n );\n\n let updatedTransfer: Transfer | undefined;\n\n const coordinatorOperator =\n this.config.getSigningOperators()[this.config.getCoordinatorIdentifier()];\n if (!coordinatorOperator) {\n throw new ValidationError(\"Coordinator operator not found\", {\n field: \"coordinator\",\n });\n }\n\n for (const [identifier, operator] of Object.entries(\n this.config.getSigningOperators(),\n ).filter(([_, op]) => op.address !== this.config.getCoordinatorAddress())) {\n updatedTransfer = await this.finalizeTransfer(\n operator,\n identifier,\n keyTweakInputMap,\n transfer,\n updatedTransfer,\n );\n }\n\n updatedTransfer = await this.finalizeTransfer(\n coordinatorOperator,\n this.config.getCoordinatorIdentifier(),\n keyTweakInputMap,\n transfer,\n updatedTransfer,\n );\n\n if (!updatedTransfer) {\n throw new ValidationError(\n \"No transfer response received from any operator\",\n {\n field: \"operators\",\n value: Object.keys(this.config.getSigningOperators()).length,\n },\n );\n }\n\n return updatedTransfer;\n }\n\n private async finalizeTransfer(\n operator: SigningOperator,\n identifier: string,\n keyTweakInputMap: Map<string, SendLeafKeyTweak[]>,\n transfer: Transfer,\n updatedTransfer: Transfer | undefined,\n ) {\n const sparkClient = await this.connectionManager.createSparkClient(\n operator.address,\n );\n\n const leavesToSend = keyTweakInputMap.get(identifier);\n if (!leavesToSend) {\n throw new ValidationError(\"No leaves to send for operator\", {\n field: \"operator\",\n value: identifier,\n });\n }\n let transferResp: FinalizeTransferResponse;\n try {\n transferResp = await sparkClient.finalize_transfer({\n transferId: transfer.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n leavesToSend,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to finalize transfer\",\n {\n method: \"POST\",\n },\n error as Error,\n );\n }\n\n if (!updatedTransfer) {\n updatedTransfer = transferResp.transfer;\n } else {\n if (!transferResp.transfer) {\n throw new ValidationError(\"No transfer response from operator\", {\n field: \"transfer\",\n value: transfer.id,\n });\n }\n\n if (!this.compareTransfers(updatedTransfer, transferResp.transfer)) {\n throw new ValidationError(\n \"Inconsistent transfer response from operators\",\n {\n field: \"transfer\",\n value: transfer.id,\n },\n );\n }\n }\n\n return updatedTransfer;\n }\n\n async signRefunds(\n leafDataMap: Map<string, ClaimLeafData>,\n operatorSigningResults: LeafRefundTxSigningResult[],\n adaptorPubKey?: Uint8Array,\n ): Promise<NodeSignatures[]> {\n const nodeSignatures: NodeSignatures[] = [];\n for (const operatorSigningResult of operatorSigningResults) {\n const leafData = leafDataMap.get(operatorSigningResult.leafId);\n if (\n !leafData ||\n !leafData.tx ||\n leafData.vout === undefined ||\n !leafData.refundTx\n ) {\n throw new Error(\n `Leaf data not found for leaf ${operatorSigningResult.leafId}`,\n );\n }\n\n const txOutput = leafData.tx?.getOutput(0);\n if (!txOutput) {\n throw new Error(\n `Output not found for leaf ${operatorSigningResult.leafId}`,\n );\n }\n\n const refundTxSighash = getSigHashFromTx(leafData.refundTx, 0, txOutput);\n\n const userSignature = await this.config.signer.signFrost({\n message: refundTxSighash,\n publicKey: leafData.signingPubKey,\n privateAsPubKey: leafData.signingPubKey,\n selfCommitment: leafData.signingNonceCommitment,\n statechainCommitments:\n operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,\n adaptorPubKey: adaptorPubKey,\n verifyingKey: operatorSigningResult.verifyingKey,\n });\n\n const refundAggregate = await this.config.signer.aggregateFrost({\n message: refundTxSighash,\n statechainSignatures:\n operatorSigningResult.refundTxSigningResult?.signatureShares,\n statechainPublicKeys:\n operatorSigningResult.refundTxSigningResult?.publicKeys,\n verifyingKey: operatorSigningResult.verifyingKey,\n statechainCommitments:\n operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,\n selfCommitment: leafData.signingNonceCommitment,\n publicKey: leafData.signingPubKey,\n selfSignature: userSignature,\n adaptorPubKey: adaptorPubKey,\n });\n\n nodeSignatures.push({\n nodeId: operatorSigningResult.leafId,\n refundTxSignature: refundAggregate,\n nodeTxSignature: new Uint8Array(),\n });\n }\n\n return nodeSignatures;\n }\n\n private async prepareSendTransferKeyTweaks(\n transfer: Transfer,\n leaves: LeafKeyTweak[],\n refundSignatureMap: Map<string, Uint8Array>,\n ): Promise<Map<string, SendLeafKeyTweak[]>> {\n const receiverEciesPubKey = ecies.PublicKey.fromHex(\n bytesToHex(transfer.receiverIdentityPublicKey),\n );\n\n const leavesTweaksMap = new Map<string, SendLeafKeyTweak[]>();\n\n for (const leaf of leaves) {\n const refundSignature = refundSignatureMap.get(leaf.leaf.id);\n const leafTweaksMap = await this.prepareSingleSendTransferKeyTweak(\n transfer.id,\n leaf,\n receiverEciesPubKey,\n refundSignature,\n );\n for (const [identifier, leafTweak] of leafTweaksMap) {\n leavesTweaksMap.set(identifier, [\n ...(leavesTweaksMap.get(identifier) || []),\n leafTweak,\n ]);\n }\n }\n\n return leavesTweaksMap;\n }\n\n private async prepareSingleSendTransferKeyTweak(\n transferID: string,\n leaf: LeafKeyTweak,\n receiverEciesPubKey: ecies.PublicKey,\n refundSignature?: Uint8Array,\n ): Promise<Map<string, SendLeafKeyTweak>> {\n const signingOperators = this.config.getSigningOperators();\n const pubKeyTweak =\n await this.config.signer.subtractPrivateKeysGivenPublicKeys(\n leaf.signingPubKey,\n leaf.newSigningPubKey,\n );\n\n const shares = await this.config.signer.splitSecretWithProofs({\n secret: pubKeyTweak,\n curveOrder: secp256k1.CURVE.n,\n threshold: this.config.getThreshold(),\n numShares: Object.keys(signingOperators).length,\n isSecretPubkey: true,\n });\n\n const pubkeySharesTweak = new Map<string, Uint8Array>();\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n\n const pubkeyTweak = secp256k1.getPublicKey(\n numberToBytesBE(share.share, 32),\n true,\n );\n pubkeySharesTweak.set(identifier, pubkeyTweak);\n }\n\n const secretCipher = await this.config.signer.encryptLeafPrivateKeyEcies(\n receiverEciesPubKey.toBytes(),\n leaf.newSigningPubKey,\n );\n\n const encoder = new TextEncoder();\n const payload = new Uint8Array([\n ...encoder.encode(leaf.leaf.id),\n ...encoder.encode(transferID),\n ...secretCipher,\n ]);\n\n const payloadHash = sha256(payload);\n const signature = await this.config.signer.signMessageWithIdentityKey(\n payloadHash,\n true,\n );\n\n const leafTweaksMap = new Map<string, SendLeafKeyTweak>();\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n\n leafTweaksMap.set(identifier, {\n leafId: leaf.leaf.id,\n secretShareTweak: {\n secretShare: numberToBytesBE(share.share, 32),\n proofs: share.proofs,\n },\n pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),\n secretCipher,\n signature,\n refundSignature: refundSignature ?? new Uint8Array(),\n });\n }\n\n return leafTweaksMap;\n }\n\n protected findShare(shares: VerifiableSecretShare[], operatorID: number) {\n const targetShareIndex = BigInt(operatorID + 1);\n for (const s of shares) {\n if (s.index === targetShareIndex) {\n return s;\n }\n }\n return undefined;\n }\n\n private compareTransfers(transfer1: Transfer, transfer2: Transfer) {\n return (\n transfer1.id === transfer2.id &&\n equalBytes(\n transfer1.senderIdentityPublicKey,\n transfer2.senderIdentityPublicKey,\n ) &&\n transfer1.status === transfer2.status &&\n transfer1.totalValue === transfer2.totalValue &&\n transfer1.expiryTime?.getTime() === transfer2.expiryTime?.getTime() &&\n transfer1.leaves.length === transfer2.leaves.length\n );\n }\n}\n\nexport class TransferService extends BaseTransferService {\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n super(config, connectionManager);\n }\n\n async sendTransfer(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n ): Promise<Transfer> {\n const { transfer, signatureMap } = await this.sendTransferSignRefund(\n leaves,\n receiverIdentityPubkey,\n new Date(Date.now() + DEFAULT_EXPIRY_TIME),\n );\n\n const transferWithTweakedKeys = await this.sendTransferTweakKey(\n transfer,\n leaves,\n signatureMap,\n );\n\n return transferWithTweakedKeys;\n }\n\n async claimTransfer(transfer: Transfer, leaves: LeafKeyTweak[]) {\n let proofMap: Map<string, Uint8Array[]> | undefined;\n if (\n transfer.status === TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED ||\n transfer.status === TransferStatus.TRANSFER_STATUS_RECEIVER_KEY_TWEAKED\n ) {\n proofMap = await this.claimTransferTweakKeys(transfer, leaves);\n }\n const signatures = await this.claimTransferSignRefunds(\n transfer,\n leaves,\n proofMap,\n );\n\n return await this.finalizeNodeSignatures(signatures);\n }\n\n async queryPendingTransfers(): Promise<QueryTransfersResponse> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n let pendingTransfersResp: QueryTransfersResponse;\n try {\n pendingTransfersResp = await sparkClient.query_pending_transfers({\n participant: {\n $case: \"receiverIdentityPublicKey\",\n receiverIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n },\n });\n } catch (error) {\n throw new Error(`Error querying pending transfers: ${error}`);\n }\n return pendingTransfersResp;\n }\n\n async queryAllTransfers(\n limit: number,\n offset: number,\n ): Promise<QueryTransfersResponse> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let allTransfersResp: QueryTransfersResponse;\n try {\n allTransfersResp = await sparkClient.query_all_transfers({\n participant: {\n $case: \"senderOrReceiverIdentityPublicKey\",\n senderOrReceiverIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n },\n limit,\n offset,\n types: [\n TransferType.TRANSFER,\n TransferType.PREIMAGE_SWAP,\n TransferType.COOPERATIVE_EXIT,\n ],\n });\n } catch (error) {\n throw new Error(`Error querying all transfers: ${error}`);\n }\n return allTransfersResp;\n }\n\n async verifyPendingTransfer(\n transfer: Transfer,\n ): Promise<Map<string, Uint8Array>> {\n const leafPubKeyMap = new Map<string, Uint8Array>();\n for (const leaf of transfer.leaves) {\n if (!leaf.leaf) {\n throw new Error(\"Leaf is undefined\");\n }\n\n const encoder = new TextEncoder();\n const leafIdBytes = encoder.encode(leaf.leaf.id);\n const transferIdBytes = encoder.encode(transfer.id);\n\n const payload = new Uint8Array([\n ...leafIdBytes,\n ...transferIdBytes,\n ...leaf.secretCipher,\n ]);\n\n const payloadHash = sha256(payload);\n if (\n !secp256k1.verify(\n leaf.signature,\n payloadHash,\n transfer.senderIdentityPublicKey,\n )\n ) {\n throw new Error(\"Signature verification failed\");\n }\n\n const leafSecret = await this.config.signer.decryptEcies(\n leaf.secretCipher,\n );\n\n leafPubKeyMap.set(leaf.leaf.id, leafSecret);\n }\n return leafPubKeyMap;\n }\n\n async sendTransferSignRefund(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n }> {\n const { transfer, signatureMap, leafDataMap } =\n await this.sendTransferSignRefundInternal(\n leaves,\n receiverIdentityPubkey,\n expiryTime,\n false,\n );\n\n return {\n transfer,\n signatureMap,\n leafDataMap,\n };\n }\n\n async startSwapSignRefund(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n }> {\n const { transfer, signatureMap, leafDataMap } =\n await this.sendTransferSignRefundInternal(\n leaves,\n receiverIdentityPubkey,\n expiryTime,\n true,\n );\n\n return {\n transfer,\n signatureMap,\n leafDataMap,\n };\n }\n\n async counterSwapSignRefund(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n adaptorPubKey?: Uint8Array,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n signingResults: LeafRefundTxSigningResult[];\n }> {\n return this.sendTransferSignRefundInternal(\n leaves,\n receiverIdentityPubkey,\n expiryTime,\n true,\n adaptorPubKey,\n );\n }\n\n async sendTransferSignRefundInternal(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n forSwap: boolean,\n adaptorPubKey?: Uint8Array,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n signingResults: LeafRefundTxSigningResult[];\n }> {\n const transferId = uuidv7();\n const leafDataMap = new Map<string, LeafRefundSigningData>();\n for (const leaf of leaves) {\n const signingNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n\n const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n leafDataMap.set(leaf.leaf.id, {\n signingPubKey: leaf.signingPubKey,\n receivingPubkey: receiverIdentityPubkey,\n signingNonceCommitment,\n tx,\n refundTx,\n vout: leaf.leaf.vout,\n });\n }\n\n const signingJobs = this.prepareRefundSoSigningJobs(leaves, leafDataMap);\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: CounterLeafSwapResponse;\n try {\n if (adaptorPubKey !== undefined) {\n response = await sparkClient.counter_leaf_swap({\n transfer: {\n transferId,\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: expiryTime,\n },\n swapId: uuidv7(),\n adaptorPublicKey: adaptorPubKey || new Uint8Array(),\n });\n } else if (forSwap) {\n response = await sparkClient.start_leaf_swap({\n transferId,\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: expiryTime,\n });\n } else {\n response = await sparkClient.start_transfer({\n transferId,\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: expiryTime,\n });\n }\n } catch (error) {\n throw new Error(`Error starting send transfer: ${error}`);\n }\n\n if (!response.transfer) {\n throw new Error(\"No transfer response from coordinator\");\n }\n\n const signatures = await this.signRefunds(\n leafDataMap,\n response.signingResults,\n adaptorPubKey,\n );\n\n const signatureMap = new Map<string, Uint8Array>();\n for (const signature of signatures) {\n signatureMap.set(signature.nodeId, signature.refundTxSignature);\n }\n\n return {\n transfer: response.transfer,\n signatureMap,\n leafDataMap,\n signingResults: response.signingResults,\n };\n }\n\n private prepareRefundSoSigningJobs(\n leaves: LeafKeyTweak[],\n leafDataMap: Map<string, LeafRefundSigningData>,\n isForClaim?: boolean,\n ): LeafRefundTxSigningJob[] {\n const signingJobs: LeafRefundTxSigningJob[] = [];\n for (const leaf of leaves) {\n const refundSigningData = leafDataMap.get(leaf.leaf.id);\n if (!refundSigningData) {\n throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);\n }\n\n const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n const nodeOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(nodeTx)),\n index: 0,\n };\n\n const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n const nextSequence = isForClaim\n ? getTransactionSequence(currRefundTx.getInput(0).sequence)\n : getNextTransactionSequence(currRefundTx.getInput(0).sequence)\n .nextSequence;\n\n const amountSats = currRefundTx.getOutput(0).amount;\n if (amountSats === undefined) {\n throw new Error(\"Amount not found in signRefunds\");\n }\n\n const refundTx = createRefundTx(\n nextSequence,\n nodeOutPoint,\n amountSats,\n refundSigningData.receivingPubkey,\n this.config.getNetwork(),\n );\n\n refundSigningData.refundTx = refundTx;\n\n const refundNonceCommitmentProto =\n refundSigningData.signingNonceCommitment;\n\n signingJobs.push({\n leafId: leaf.leaf.id,\n refundTxSigningJob: {\n signingPublicKey: refundSigningData.signingPubKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: refundNonceCommitmentProto,\n },\n });\n }\n\n return signingJobs;\n }\n\n async claimTransferTweakKeys(\n transfer: Transfer,\n leaves: LeafKeyTweak[],\n ): Promise<Map<string, Uint8Array[]>> {\n const { leafDataMap: leavesTweaksMap, proofMap } =\n await this.prepareClaimLeavesKeyTweaks(leaves);\n\n const errors: Error[] = [];\n\n const promises = Object.entries(this.config.getSigningOperators()).map(\n async ([identifier, operator]) => {\n const sparkClient = await this.connectionManager.createSparkClient(\n operator.address,\n );\n\n const leavesToReceive = leavesTweaksMap.get(identifier);\n if (!leavesToReceive) {\n errors.push(\n new ValidationError(\"No leaves to receive for operator\", {\n field: \"operator\",\n value: identifier,\n }) as SparkSDKError,\n );\n return;\n }\n\n try {\n await sparkClient.claim_transfer_tweak_keys({\n transferId: transfer.id,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n leavesToReceive,\n });\n } catch (error) {\n errors.push(\n new NetworkError(\n \"Failed to claim transfer tweak keys\",\n {\n method: \"POST\",\n },\n error as Error,\n ) as SparkSDKError,\n );\n return;\n }\n },\n );\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n throw new NetworkError(\n \"Failed to claim transfer tweak keys\",\n {\n method: \"POST\",\n errorCount: errors.length,\n errors: errors.map((e) => e.message).join(\", \"),\n },\n errors[0],\n );\n }\n\n return proofMap;\n }\n\n private async prepareClaimLeavesKeyTweaks(leaves: LeafKeyTweak[]): Promise<{\n leafDataMap: Map<string, ClaimLeafKeyTweak[]>;\n proofMap: Map<string, Uint8Array[]>;\n }> {\n const leafDataMap = new Map<string, ClaimLeafKeyTweak[]>();\n const proofMap = new Map<string, Uint8Array[]>();\n for (const leaf of leaves) {\n const { leafKeyTweaks: leafData, proofs } =\n await this.prepareClaimLeafKeyTweaks(leaf);\n proofMap.set(leaf.leaf.id, proofs);\n\n for (const [identifier, leafTweak] of leafData) {\n leafDataMap.set(identifier, [\n ...(leafDataMap.get(identifier) || []),\n leafTweak,\n ]);\n }\n }\n return { leafDataMap, proofMap };\n }\n\n private async prepareClaimLeafKeyTweaks(leaf: LeafKeyTweak): Promise<{\n leafKeyTweaks: Map<string, ClaimLeafKeyTweak>;\n proofs: Uint8Array[];\n }> {\n const signingOperators = this.config.getSigningOperators();\n\n const pubKeyTweak =\n await this.config.signer.subtractPrivateKeysGivenPublicKeys(\n leaf.signingPubKey,\n leaf.newSigningPubKey,\n );\n\n const shares = await this.config.signer.splitSecretWithProofs({\n secret: pubKeyTweak,\n curveOrder: secp256k1.CURVE.n,\n threshold: this.config.getThreshold(),\n numShares: Object.keys(signingOperators).length,\n isSecretPubkey: true,\n });\n\n const pubkeySharesTweak = new Map<string, Uint8Array>();\n\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n const pubkeyTweak = secp256k1.getPublicKey(\n numberToBytesBE(share.share, 32),\n );\n pubkeySharesTweak.set(identifier, pubkeyTweak);\n }\n\n const leafTweaksMap = new Map<string, ClaimLeafKeyTweak>();\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n\n leafTweaksMap.set(identifier, {\n leafId: leaf.leaf.id,\n secretShareTweak: {\n secretShare: numberToBytesBE(share.share, 32),\n proofs: share.proofs,\n },\n pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),\n });\n }\n\n if (!shares[0]?.proofs) {\n throw new ValidationError(\"Proofs not found\", {\n field: \"proofs\",\n value: shares[0]?.proofs,\n }) as SparkSDKError;\n }\n\n return { leafKeyTweaks: leafTweaksMap, proofs: shares[0].proofs };\n }\n\n async claimTransferSignRefunds(\n transfer: Transfer,\n leafKeys: LeafKeyTweak[],\n proofMap?: Map<string, Uint8Array[]>,\n ): Promise<NodeSignatures[]> {\n const leafDataMap: Map<string, LeafRefundSigningData> = new Map();\n for (const leafKey of leafKeys) {\n const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);\n leafDataMap.set(leafKey.leaf.id, {\n signingPubKey: leafKey.newSigningPubKey,\n receivingPubkey: leafKey.newSigningPubKey,\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n tx,\n vout: leafKey.leaf.vout,\n });\n }\n\n const signingJobs = this.prepareRefundSoSigningJobs(\n leafKeys,\n leafDataMap,\n true,\n );\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n let resp: ClaimTransferSignRefundsResponse;\n\n const secretProofMap: { [key: string]: SecretProof } = {};\n if (proofMap) {\n for (const [leafId, proof] of proofMap.entries()) {\n secretProofMap[leafId] = {\n proofs: proof,\n };\n }\n }\n try {\n resp = await sparkClient.claim_transfer_sign_refunds({\n transferId: transfer.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n signingJobs,\n keyTweakProofs: secretProofMap,\n });\n } catch (error) {\n throw new Error(`Error claiming transfer sign refunds: ${error}`);\n }\n return this.signRefunds(leafDataMap, resp.signingResults);\n }\n\n private async finalizeNodeSignatures(nodeSignatures: NodeSignatures[]) {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n try {\n return await sparkClient.finalize_node_signatures({\n intent: SignatureIntent.TRANSFER,\n nodeSignatures,\n });\n } catch (error) {\n throw new Error(`Error finalizing node signatures in transfer: ${error}`);\n }\n }\n\n async cancelTransfer(\n transfer: Transfer,\n operatorAddress: string,\n ): Promise<Transfer | undefined> {\n const sparkClient =\n await this.connectionManager.createSparkClient(operatorAddress);\n\n try {\n const response = await sparkClient.cancel_transfer({\n transferId: transfer.id,\n senderIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n });\n\n return response.transfer;\n } catch (error) {\n throw new NetworkError(\n \"Failed to cancel transfer\",\n {\n method: \"POST\",\n },\n error as Error,\n );\n }\n }\n\n async queryPendingTransfersBySender(\n operatorAddress: string,\n ): Promise<QueryTransfersResponse> {\n const sparkClient =\n await this.connectionManager.createSparkClient(operatorAddress);\n try {\n return await sparkClient.query_pending_transfers({\n participant: {\n $case: \"senderIdentityPublicKey\",\n senderIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n },\n });\n } catch (error) {\n throw new Error(`Error querying pending transfers by sender: ${error}`);\n }\n }\n\n async refreshTimelockNodes(\n nodes: TreeNode[],\n parentNode: TreeNode,\n signingPubKey: Uint8Array,\n ) {\n if (nodes.length === 0) {\n throw Error(\"no nodes to refresh\");\n }\n\n const signingJobs: SigningJob[] = [];\n const newNodeTxs: Transaction[] = [];\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node) {\n throw Error(\"could not get node\");\n }\n const nodeTx = getTxFromRawTxBytes(node?.nodeTx);\n const input = nodeTx.getInput(0);\n\n if (!input) {\n throw Error(\"Could not fetch tx input\");\n }\n\n const newTx = new Transaction({ allowUnknownOutputs: true });\n for (let j = 0; j < nodeTx.outputsLength; j++) {\n newTx.addOutput(nodeTx.getOutput(j));\n }\n if (i === 0) {\n const currSequence = input.sequence;\n\n newTx.addInput({\n ...input,\n sequence: getNextTransactionSequence(currSequence).nextSequence,\n });\n } else {\n newTx.addInput({\n ...input,\n sequence: initialSequence(),\n txid: newNodeTxs[i - 1]?.id,\n });\n }\n\n signingJobs.push({\n signingPublicKey: signingPubKey,\n rawTx: newTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n });\n newNodeTxs[i] = newTx;\n }\n\n const leaf = nodes[nodes.length - 1];\n if (!leaf?.refundTx) {\n throw Error(\"leaf does not have refund tx\");\n }\n const refundTx = getTxFromRawTxBytes(leaf?.refundTx);\n const newRefundTx = new Transaction({ allowUnknownOutputs: true });\n\n for (let j = 0; j < refundTx.outputsLength; j++) {\n newRefundTx.addOutput(refundTx.getOutput(j));\n }\n\n const refundTxInput = refundTx.getInput(0);\n if (!refundTxInput) {\n throw Error(\"refund tx doesn't have input\");\n }\n\n if (!newNodeTxs[newNodeTxs.length - 1]) {\n throw Error(\"Could not get last node tx\");\n }\n newRefundTx.addInput({\n ...refundTxInput,\n sequence: initialSequence(),\n txid: getTxId(newNodeTxs[newNodeTxs.length - 1]!),\n });\n\n const refundSigningJob = {\n signingPublicKey: signingPubKey,\n rawTx: newRefundTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n };\n\n signingJobs.push(refundSigningJob);\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const response = await sparkClient.refresh_timelock({\n leafId: leaf.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n signingJobs,\n });\n\n if (signingJobs.length !== response.signingResults.length) {\n throw Error(\n `number of signing jobs and signing results do not match: ${signingJobs.length} !== ${response.signingResults.length}`,\n );\n }\n\n let nodeSignatures: NodeSignatures[] = [];\n let leafSignature: Uint8Array | undefined;\n let refundSignature: Uint8Array | undefined;\n let leafNodeId: string | undefined;\n for (let i = 0; i < response.signingResults.length; i++) {\n const signingResult = response.signingResults[i];\n const signingJob = signingJobs[i];\n if (!signingJob || !signingResult) {\n throw Error(\"Signing job does not exist\");\n }\n\n if (!signingJob.signingNonceCommitment) {\n throw Error(\"nonce commitment does not exist\");\n }\n const rawTx = getTxFromRawTxBytes(signingJob.rawTx);\n\n let parentTx: Transaction | undefined;\n let nodeId: string | undefined;\n let vout: number | undefined;\n\n if (i === nodes.length) {\n nodeId = nodes[i - 1]?.id;\n parentTx = newNodeTxs[i - 1];\n vout = 0;\n } else if (i === 0) {\n nodeId = nodes[i]?.id;\n parentTx = getTxFromRawTxBytes(parentNode.nodeTx);\n vout = nodes[i]?.vout;\n } else {\n nodeId = nodes[i]?.id;\n parentTx = newNodeTxs[i - 1];\n vout = nodes[i]?.vout;\n }\n\n if (!parentTx || !nodeId || vout === undefined) {\n throw Error(\"Could not parse signing results\");\n }\n\n const txOut = parentTx.getOutput(vout);\n\n const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);\n\n const userSignature = await this.config.signer.signFrost({\n message: rawTxSighash,\n privateAsPubKey: signingPubKey,\n publicKey: signingPubKey,\n verifyingKey: signingResult.verifyingKey,\n selfCommitment: signingJob.signingNonceCommitment,\n statechainCommitments:\n signingResult.signingResult?.signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n });\n\n const signature = await this.config.signer.aggregateFrost({\n message: rawTxSighash,\n statechainSignatures: signingResult.signingResult?.signatureShares,\n statechainPublicKeys: signingResult.signingResult?.publicKeys,\n verifyingKey: signingResult.verifyingKey,\n statechainCommitments:\n signingResult.signingResult?.signingNonceCommitments,\n selfCommitment: signingJob.signingNonceCommitment,\n publicKey: signingPubKey,\n selfSignature: userSignature,\n adaptorPubKey: new Uint8Array(),\n });\n\n if (i !== nodes.length && i !== nodes.length - 1) {\n nodeSignatures.push({\n nodeId: nodeId,\n nodeTxSignature: signature,\n refundTxSignature: new Uint8Array(),\n });\n } else if (i === nodes.length) {\n refundSignature = signature;\n } else if (i === nodes.length - 1) {\n leafNodeId = nodeId;\n leafSignature = signature;\n }\n }\n\n if (!leafSignature || !refundSignature || !leafNodeId) {\n throw Error(\"leaf or refund signature does not exist\");\n }\n\n nodeSignatures.push({\n nodeId: leafNodeId,\n nodeTxSignature: leafSignature,\n refundTxSignature: refundSignature,\n });\n\n return await sparkClient.finalize_node_signatures({\n intent: SignatureIntent.REFRESH,\n nodeSignatures,\n });\n }\n\n async extendTimelock(node: TreeNode, signingPubKey: Uint8Array) {\n const nodeTx = getTxFromRawTxBytes(node.nodeTx);\n const refundTx = getTxFromRawTxBytes(node.refundTx);\n\n const refundSequence = refundTx.getInput(0).sequence || 0;\n const newNodeOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(nodeTx)),\n index: 0,\n };\n\n const { nextSequence: newNodeSequence } =\n getNextTransactionSequence(refundSequence);\n const newNodeTx = new Transaction({ allowUnknownOutputs: true });\n newNodeTx.addInput({ ...newNodeOutPoint, sequence: newNodeSequence });\n newNodeTx.addOutput(nodeTx.getOutput(0));\n newNodeTx.addOutput(getEphemeralAnchorOutput());\n\n const newRefundOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(newNodeTx)!),\n index: 0,\n };\n\n const amountSats = refundTx.getOutput(0).amount;\n if (amountSats === undefined) {\n throw new Error(\"Amount not found in extendTimelock\");\n }\n\n const newRefundTx = createRefundTx(\n initialSequence(),\n newRefundOutPoint,\n amountSats,\n signingPubKey,\n this.config.getNetwork(),\n );\n\n const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));\n const refundSighash = getSigHashFromTx(newRefundTx, 0, nodeTx.getOutput(0));\n\n const newNodeSigningJob = {\n signingPublicKey: signingPubKey,\n rawTx: newNodeTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n };\n\n const newRefundSigningJob = {\n signingPublicKey: signingPubKey,\n rawTx: newRefundTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n };\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const response = await sparkClient.extend_leaf({\n leafId: node.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n nodeTxSigningJob: newNodeSigningJob,\n refundTxSigningJob: newRefundSigningJob,\n });\n\n if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {\n throw new Error(\"Signing result does not exist\");\n }\n\n const nodeUserSig = await this.config.signer.signFrost({\n message: nodeSighash,\n privateAsPubKey: signingPubKey,\n publicKey: signingPubKey,\n verifyingKey: response.nodeTxSigningResult.verifyingKey,\n selfCommitment: newNodeSigningJob.signingNonceCommitment,\n statechainCommitments:\n response.nodeTxSigningResult.signingResult?.signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n });\n\n const refundUserSig = await this.config.signer.signFrost({\n message: refundSighash,\n privateAsPubKey: signingPubKey,\n publicKey: signingPubKey,\n verifyingKey: response.refundTxSigningResult.verifyingKey,\n selfCommitment: newRefundSigningJob.signingNonceCommitment,\n statechainCommitments:\n response.refundTxSigningResult.signingResult?.signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n });\n\n const nodeSig = await this.config.signer.aggregateFrost({\n message: nodeSighash,\n statechainSignatures:\n response.nodeTxSigningResult.signingResult?.signatureShares,\n statechainPublicKeys:\n response.nodeTxSigningResult.signingResult?.publicKeys,\n verifyingKey: response.nodeTxSigningResult.verifyingKey,\n statechainCommitments:\n response.nodeTxSigningResult.signingResult?.signingNonceCommitments,\n selfCommitment: newNodeSigningJob.signingNonceCommitment,\n publicKey: signingPubKey,\n selfSignature: nodeUserSig,\n adaptorPubKey: new Uint8Array(),\n });\n\n const refundSig = await this.config.signer.aggregateFrost({\n message: refundSighash,\n statechainSignatures:\n response.refundTxSigningResult.signingResult?.signatureShares,\n statechainPublicKeys:\n response.refundTxSigningResult.signingResult?.publicKeys,\n verifyingKey: response.refundTxSigningResult.verifyingKey,\n statechainCommitments:\n response.refundTxSigningResult.signingResult?.signingNonceCommitments,\n selfCommitment: newRefundSigningJob.signingNonceCommitment,\n publicKey: signingPubKey,\n selfSignature: refundUserSig,\n adaptorPubKey: new Uint8Array(),\n });\n\n return await sparkClient.finalize_node_signatures({\n intent: SignatureIntent.EXTEND,\n nodeSignatures: [\n {\n nodeId: response.leafId,\n nodeTxSignature: nodeSig,\n refundTxSignature: refundSig,\n },\n ],\n });\n }\n}\n","import {\n bytesToNumberBE,\n hexToBytes,\n numberToBytesBE,\n} from \"@noble/curves/abstract/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport { decode } from \"light-bolt11-decoder\";\nimport { uuidv7 } from \"uuidv7\";\nimport { NetworkError, ValidationError } from \"../errors/types.js\";\nimport LightningReceiveRequest from \"../graphql/objects/LightningReceiveRequest.js\";\nimport {\n GetSigningCommitmentsResponse,\n InitiatePreimageSwapRequest_Reason,\n InitiatePreimageSwapResponse,\n ProvidePreimageResponse,\n QueryUserSignedRefundsResponse,\n RequestedSigningCommitments,\n Transfer,\n UserSignedRefund,\n UserSignedTxSigningJob,\n} from \"../proto/spark.js\";\nimport {\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxId,\n} from \"../utils/bitcoin.js\";\nimport { getCrypto } from \"../utils/crypto.js\";\nimport {\n createRefundTx,\n getNextTransactionSequence,\n} from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport { LeafKeyTweak } from \"./transfer.js\";\n\nconst crypto = getCrypto();\n\nexport type CreateLightningInvoiceParams = {\n invoiceCreator: (\n amountSats: number,\n paymentHash: Uint8Array,\n memo?: string,\n ) => Promise<LightningReceiveRequest | null>;\n amountSats: number;\n memo?: string;\n};\n\nexport type CreateLightningInvoiceWithPreimageParams = {\n preimage: Uint8Array;\n} & CreateLightningInvoiceParams;\n\nexport type SwapNodesForPreimageParams = {\n leaves: LeafKeyTweak[];\n receiverIdentityPubkey: Uint8Array;\n paymentHash: Uint8Array;\n invoiceString?: string;\n isInboundPayment: boolean;\n feeSats?: number;\n};\n\nexport class LightningService {\n private readonly config: WalletConfigService;\n private readonly connectionManager: ConnectionManager;\n\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n this.config = config;\n this.connectionManager = connectionManager;\n }\n\n async createLightningInvoice({\n invoiceCreator,\n amountSats,\n memo,\n }: CreateLightningInvoiceParams): Promise<LightningReceiveRequest> {\n const randBytes = crypto.getRandomValues(new Uint8Array(32));\n const preimage = numberToBytesBE(\n bytesToNumberBE(randBytes) % secp256k1.CURVE.n,\n 32,\n );\n return await this.createLightningInvoiceWithPreImage({\n invoiceCreator,\n amountSats,\n memo,\n preimage,\n });\n }\n\n async createLightningInvoiceWithPreImage({\n invoiceCreator,\n amountSats,\n memo,\n preimage,\n }: CreateLightningInvoiceWithPreimageParams): Promise<LightningReceiveRequest> {\n const paymentHash = sha256(preimage);\n const invoice = await invoiceCreator(amountSats, paymentHash, memo);\n if (!invoice) {\n throw new ValidationError(\"Failed to create lightning invoice\", {\n field: \"invoice\",\n value: null,\n expected: \"Non-null invoice\",\n });\n }\n\n const shares = await this.config.signer.splitSecretWithProofs({\n secret: preimage,\n curveOrder: secp256k1.CURVE.n,\n threshold: this.config.getThreshold(),\n numShares: Object.keys(this.config.getSigningOperators()).length,\n });\n\n const errors: Error[] = [];\n const promises = Object.entries(this.config.getSigningOperators()).map(\n async ([_, operator]) => {\n const share = shares[operator.id];\n if (!share) {\n throw new ValidationError(\"Share not found for operator\", {\n field: \"share\",\n value: operator.id,\n expected: \"Non-null share\",\n });\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n operator.address,\n );\n\n try {\n await sparkClient.store_preimage_share({\n paymentHash,\n preimageShare: {\n secretShare: numberToBytesBE(share.share, 32),\n proofs: share.proofs,\n },\n threshold: this.config.getThreshold(),\n invoiceString: invoice.invoice.encodedInvoice,\n userIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n });\n } catch (e: any) {\n errors.push(e);\n }\n },\n );\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n throw new NetworkError(\n \"Failed to store preimage shares\",\n {\n operation: \"store_preimage_share\",\n errorCount: errors.length,\n errors: errors.map((e) => e.message).join(\", \"),\n },\n errors[0],\n );\n }\n\n return invoice;\n }\n\n async swapNodesForPreimage({\n leaves,\n receiverIdentityPubkey,\n paymentHash,\n invoiceString,\n isInboundPayment,\n feeSats = 0,\n }: SwapNodesForPreimageParams): Promise<InitiatePreimageSwapResponse> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let signingCommitments: GetSigningCommitmentsResponse;\n try {\n signingCommitments = await sparkClient.get_signing_commitments({\n nodeIds: leaves.map((leaf) => leaf.leaf.id),\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to get signing commitments\",\n {\n operation: \"get_signing_commitments\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n const leafSigningJobs = await this.signRefunds(\n leaves,\n signingCommitments.signingCommitments,\n receiverIdentityPubkey,\n );\n\n const transferId = uuidv7();\n let bolt11String = \"\";\n let amountSats: number = 0;\n if (invoiceString) {\n const decodedInvoice = decode(invoiceString);\n let amountMsats = 0;\n try {\n amountMsats = Number(\n decodedInvoice.sections.find((section) => section.name === \"amount\")\n ?.value,\n );\n } catch (error) {\n console.error(\"Error decoding invoice\", error);\n }\n\n amountSats = amountMsats / 1000;\n bolt11String = invoiceString;\n }\n\n const reason = isInboundPayment\n ? InitiatePreimageSwapRequest_Reason.REASON_RECEIVE\n : InitiatePreimageSwapRequest_Reason.REASON_SEND;\n\n let response: InitiatePreimageSwapResponse;\n try {\n response = await sparkClient.initiate_preimage_swap({\n paymentHash,\n invoiceAmount: {\n invoiceAmountProof: {\n bolt11Invoice: bolt11String,\n },\n valueSats: amountSats,\n },\n reason,\n transfer: {\n transferId,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n leavesToSend: leafSigningJobs,\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: new Date(Date.now() + 2 * 60 * 1000),\n },\n receiverIdentityPublicKey: receiverIdentityPubkey,\n feeSats,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to initiate preimage swap\",\n {\n operation: \"initiate_preimage_swap\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n return response;\n }\n\n async queryUserSignedRefunds(\n paymentHash: Uint8Array,\n ): Promise<UserSignedRefund[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: QueryUserSignedRefundsResponse;\n try {\n response = await sparkClient.query_user_signed_refunds({\n paymentHash,\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to query user signed refunds\",\n {\n operation: \"query_user_signed_refunds\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n return response.userSignedRefunds;\n }\n\n validateUserSignedRefund(userSignedRefund: UserSignedRefund): bigint {\n const refundTx = getTxFromRawTxBytes(userSignedRefund.refundTx);\n // TODO: Should we assert that the amount is always defined here?\n return refundTx.getOutput(0).amount || 0n;\n }\n\n async providePreimage(preimage: Uint8Array): Promise<Transfer> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const paymentHash = sha256(preimage);\n let response: ProvidePreimageResponse;\n try {\n response = await sparkClient.provide_preimage({\n preimage,\n paymentHash,\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to provide preimage\",\n {\n operation: \"provide_preimage\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n if (!response.transfer) {\n throw new ValidationError(\"No transfer returned from coordinator\", {\n field: \"transfer\",\n value: response,\n expected: \"Non-null transfer\",\n });\n }\n\n return response.transfer;\n }\n\n private async signRefunds(\n leaves: LeafKeyTweak[],\n signingCommitments: RequestedSigningCommitments[],\n receiverIdentityPubkey: Uint8Array,\n ): Promise<UserSignedTxSigningJob[]> {\n const leafSigningJobs: UserSignedTxSigningJob[] = [];\n for (let i = 0; i < leaves.length; i++) {\n const leaf = leaves[i];\n if (!leaf?.leaf) {\n throw new ValidationError(\"Leaf not found in signRefunds\", {\n field: \"leaf\",\n value: leaf,\n expected: \"Non-null leaf\",\n });\n }\n\n const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n const nodeOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(nodeTx)),\n index: 0,\n };\n\n const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n const { nextSequence } = getNextTransactionSequence(\n currRefundTx.getInput(0).sequence,\n );\n const amountSats = currRefundTx.getOutput(0).amount;\n if (amountSats === undefined) {\n throw new ValidationError(\"Invalid refund transaction\", {\n field: \"amount\",\n value: currRefundTx.getOutput(0),\n expected: \"Non-null amount\",\n });\n }\n\n const refundTx = createRefundTx(\n nextSequence,\n nodeOutPoint,\n amountSats,\n receiverIdentityPubkey,\n this.config.getNetwork(),\n );\n\n const sighash = getSigHashFromTx(refundTx, 0, nodeTx.getOutput(0));\n\n const signingCommitment =\n await this.config.signer.getRandomSigningCommitment();\n\n const signingNonceCommitments =\n signingCommitments[i]?.signingNonceCommitments;\n if (!signingNonceCommitments) {\n throw new ValidationError(\"Invalid signing commitments\", {\n field: \"signingNonceCommitments\",\n value: signingCommitments[i],\n expected: \"Non-null signing nonce commitments\",\n });\n }\n const signingResult = await this.config.signer.signFrost({\n message: sighash,\n publicKey: leaf.signingPubKey,\n privateAsPubKey: leaf.signingPubKey,\n selfCommitment: signingCommitment,\n statechainCommitments: signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n verifyingKey: leaf.leaf.verifyingPublicKey,\n });\n\n leafSigningJobs.push({\n leafId: leaf.leaf.id,\n signingPublicKey: leaf.signingPubKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: signingCommitment,\n userSignature: signingResult,\n signingCommitments: {\n signingCommitments: signingNonceCommitments,\n },\n });\n }\n\n return leafSigningJobs;\n }\n}\n","import { Address, OutScript, Transaction } from \"@scure/btc-signer\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport {\n AddressNode,\n AddressRequestNode,\n CreateTreeRequest,\n CreateTreeResponse,\n CreationNode,\n CreationResponseNode,\n FinalizeNodeSignaturesResponse,\n NodeSignatures,\n PrepareTreeAddressRequest,\n PrepareTreeAddressResponse,\n SigningJob,\n TreeNode,\n} from \"../proto/spark.js\";\nimport { SigningCommitment } from \"../signer/signer.js\";\nimport {\n getP2TRAddressFromPublicKey,\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxId,\n} from \"../utils/bitcoin.js\";\nimport { getNetwork, Network } from \"../utils/network.js\";\nimport { getEphemeralAnchorOutput } from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport { NetworkError, ValidationError } from \"../errors/index.js\";\n\nexport type DepositAddressTree = {\n address?: string | undefined;\n signingPublicKey: Uint8Array;\n verificationKey?: Uint8Array | undefined;\n children: DepositAddressTree[];\n};\n\nexport type CreationNodeWithNonces = CreationNode & {\n nodeTxSigningCommitment?: SigningCommitment | undefined;\n refundTxSigningCommitment?: SigningCommitment | undefined;\n};\n\nconst INITIAL_TIME_LOCK = 2000;\n\nexport class TreeCreationService {\n private readonly config: WalletConfigService;\n private readonly connectionManager: ConnectionManager;\n\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n this.config = config;\n this.connectionManager = connectionManager;\n }\n\n async generateDepositAddressForTree(\n vout: number,\n parentSigningPublicKey: Uint8Array,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ): Promise<DepositAddressTree> {\n if (!parentTx && !parentNode) {\n throw new Error(\"No parent tx or parent node provided\");\n }\n\n const id = parentNode?.id ?? getTxId(parentTx!);\n\n const tree = await this.createDepositAddressTree(\n parentSigningPublicKey,\n id,\n );\n\n const addressRequestNodes =\n this.createAddressRequestNodeFromTreeNodes(tree);\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const request: PrepareTreeAddressRequest = {\n userIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n node: undefined,\n };\n if (parentNode) {\n if (!parentNode.parentNodeId) {\n throw new Error(\"Parent node ID is undefined\");\n }\n request.source = {\n $case: \"parentNodeOutput\",\n parentNodeOutput: {\n nodeId: parentNode.parentNodeId,\n vout: vout,\n },\n };\n } else if (parentTx) {\n request.source = {\n $case: \"onChainUtxo\",\n onChainUtxo: {\n vout: vout,\n rawTx: parentTx.toBytes(),\n network: this.config.getNetworkProto(),\n },\n };\n } else {\n throw new Error(\"No parent node or parent tx provided\");\n }\n\n request.node = {\n userPublicKey: parentSigningPublicKey,\n children: addressRequestNodes,\n };\n\n const root: DepositAddressTree = {\n address: undefined,\n signingPublicKey: parentSigningPublicKey,\n children: tree,\n };\n\n let response: PrepareTreeAddressResponse;\n try {\n response = await sparkClient.prepare_tree_address(request);\n } catch (error) {\n throw new Error(`Error preparing tree address: ${error}`);\n }\n\n if (!response.node) {\n throw new Error(\"No node found in response\");\n }\n\n this.applyAddressNodesToTree([root], [response.node]);\n\n return root;\n }\n\n async createTree(\n vout: number,\n root: DepositAddressTree,\n createLeaves: boolean,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ): Promise<FinalizeNodeSignaturesResponse> {\n const request: CreateTreeRequest = {\n userIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n node: undefined,\n };\n\n let tx: Transaction | undefined;\n if (parentTx) {\n tx = parentTx;\n request.source = {\n $case: \"onChainUtxo\",\n onChainUtxo: {\n vout: vout,\n rawTx: parentTx.toBytes(),\n network: this.config.getNetworkProto(),\n },\n };\n } else if (parentNode) {\n tx = getTxFromRawTxBytes(parentNode.nodeTx);\n if (!parentNode.parentNodeId) {\n throw new Error(\"Parent node ID is undefined\");\n }\n request.source = {\n $case: \"parentNodeOutput\",\n parentNodeOutput: {\n nodeId: parentNode.parentNodeId,\n vout: vout,\n },\n };\n } else {\n throw new Error(\"No parent node or parent tx provided\");\n }\n\n const rootCreationNode = await this.buildCreationNodesFromTree(\n vout,\n createLeaves,\n this.config.getNetwork(),\n root,\n tx,\n );\n\n request.node = rootCreationNode;\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: CreateTreeResponse;\n try {\n response = await sparkClient.create_tree(request);\n } catch (error) {\n throw new Error(`Error creating tree: ${error}`);\n }\n\n if (!response.node) {\n throw new Error(\"No node found in response\");\n }\n\n const creationResultTreeRoot = response.node;\n\n const nodeSignatures = await this.signTreeCreation(\n tx,\n vout,\n root,\n rootCreationNode,\n creationResultTreeRoot,\n );\n\n let finalizeResp: FinalizeNodeSignaturesResponse;\n try {\n finalizeResp = await sparkClient.finalize_node_signatures({\n nodeSignatures: nodeSignatures,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to finalize node signatures\",\n {\n operation: \"finalize_node_signatures\",\n nodeSignaturesCount: nodeSignatures.length,\n },\n error as Error,\n );\n }\n\n return finalizeResp;\n }\n\n private async createDepositAddressTree(\n targetSigningPublicKey: Uint8Array,\n nodeId: string,\n ): Promise<DepositAddressTree[]> {\n const leftKey = await this.config.signer.generatePublicKey(sha256(nodeId));\n const leftNode: DepositAddressTree = {\n signingPublicKey: leftKey,\n children: [],\n };\n\n const rightKey =\n await this.config.signer.subtractPrivateKeysGivenPublicKeys(\n targetSigningPublicKey,\n leftKey,\n );\n\n const rightNode: DepositAddressTree = {\n signingPublicKey: rightKey,\n children: [],\n };\n return [leftNode, rightNode];\n }\n\n private createAddressRequestNodeFromTreeNodes(\n treeNodes: DepositAddressTree[],\n ): AddressRequestNode[] {\n const results: AddressRequestNode[] = [];\n for (const node of treeNodes) {\n const result: AddressRequestNode = {\n userPublicKey: node.signingPublicKey,\n children: this.createAddressRequestNodeFromTreeNodes(node.children),\n };\n results.push(result);\n }\n return results;\n }\n\n private applyAddressNodesToTree(\n tree: DepositAddressTree[],\n addressNodes: AddressNode[],\n ) {\n for (let i = 0; i < tree.length; i++) {\n if (!tree[i]) {\n throw new ValidationError(\"Tree node is undefined\", {\n index: i,\n treeLength: tree.length,\n });\n }\n if (!addressNodes[i]) {\n throw new ValidationError(\"Address node is undefined\", {\n index: i,\n addressNodesLength: addressNodes.length,\n });\n }\n // @ts-ignore\n tree[i].address = addressNodes[i].address?.address;\n // @ts-ignore\n tree[i].verificationKey = addressNodes[i].address?.verifyingKey;\n // @ts-ignore\n this.applyAddressNodesToTree(tree[i].children, addressNodes[i].children);\n }\n }\n\n private async buildChildCreationNode(\n node: DepositAddressTree,\n parentTx: Transaction,\n vout: number,\n network: Network,\n ): Promise<CreationNodeWithNonces> {\n // internal node\n const internalCreationNode: CreationNodeWithNonces = {\n nodeTxSigningJob: undefined,\n refundTxSigningJob: undefined,\n children: [],\n };\n\n const tx = new Transaction();\n tx.addInput({\n txid: getTxId(parentTx),\n index: vout,\n });\n\n const parentTxOut = parentTx.getOutput(vout);\n if (!parentTxOut?.script || !parentTxOut?.amount) {\n throw new Error(\"parentTxOut is undefined\");\n }\n\n tx.addOutput({\n script: parentTxOut.script,\n amount: parentTxOut.amount,\n });\n\n // Add ephemeral anchor\n tx.addOutput(getEphemeralAnchorOutput());\n\n const signingNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const signingJob: SigningJob = {\n signingPublicKey: node.signingPublicKey,\n rawTx: tx.toBytes(),\n signingNonceCommitment: signingNonceCommitment,\n };\n\n internalCreationNode.nodeTxSigningCommitment = signingNonceCommitment;\n internalCreationNode.nodeTxSigningJob = signingJob;\n\n // leaf node\n const sequence = (1 << 30) | INITIAL_TIME_LOCK;\n\n const childCreationNode: CreationNodeWithNonces = {\n nodeTxSigningJob: undefined,\n refundTxSigningJob: undefined,\n children: [],\n };\n\n const childTx = new Transaction();\n childTx.addInput({\n txid: getTxId(tx),\n index: 0,\n sequence,\n });\n\n childTx.addOutput({\n script: parentTxOut.script,\n amount: parentTxOut.amount,\n });\n\n // Add ephemeral anchor\n childTx.addOutput(getEphemeralAnchorOutput());\n\n const childSigningNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const childSigningJob: SigningJob = {\n signingPublicKey: node.signingPublicKey,\n rawTx: childTx.toBytes(),\n signingNonceCommitment: childSigningNonceCommitment,\n };\n\n childCreationNode.nodeTxSigningCommitment = childSigningNonceCommitment;\n childCreationNode.nodeTxSigningJob = childSigningJob;\n\n const refundTx = new Transaction();\n refundTx.addInput({\n txid: getTxId(childTx),\n index: 0,\n sequence,\n });\n\n const refundP2trAddress = getP2TRAddressFromPublicKey(\n node.signingPublicKey,\n network,\n );\n const refundAddress = Address(getNetwork(network)).decode(\n refundP2trAddress,\n );\n const refundPkScript = OutScript.encode(refundAddress);\n refundTx.addOutput({\n script: refundPkScript,\n amount: parentTxOut.amount,\n });\n\n const refundSigningNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n\n const refundSigningJob: SigningJob = {\n signingPublicKey: node.signingPublicKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: refundSigningNonceCommitment,\n };\n childCreationNode.refundTxSigningCommitment = refundSigningNonceCommitment;\n childCreationNode.refundTxSigningJob = refundSigningJob;\n\n internalCreationNode.children.push(childCreationNode);\n\n return internalCreationNode;\n }\n\n private async buildCreationNodesFromTree(\n vout: number,\n createLeaves: boolean,\n network: Network,\n root: DepositAddressTree,\n parentTx: Transaction,\n ): Promise<CreationNodeWithNonces> {\n const parentTxOutput = parentTx.getOutput(vout);\n if (!parentTxOutput?.script || !parentTxOutput?.amount) {\n throw new Error(\"parentTxOutput is undefined\");\n }\n const rootNodeTx = new Transaction();\n rootNodeTx.addInput({\n txid: getTxId(parentTx),\n index: vout,\n });\n\n for (let i = 0; i < root.children.length; i++) {\n const child = root.children[i];\n if (!child || !child.address) {\n throw new Error(\"child address is undefined\");\n }\n const childAddress = Address(getNetwork(network)).decode(child.address);\n const childPkScript = OutScript.encode(childAddress);\n rootNodeTx.addOutput({\n script: childPkScript,\n amount: parentTxOutput.amount / 2n,\n });\n }\n\n // Add ephemeral anchor output\n const anchor = getEphemeralAnchorOutput();\n rootNodeTx.addOutput(anchor);\n\n const rootNodeSigningCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const rootNodeSigningJob: SigningJob = {\n signingPublicKey: root.signingPublicKey,\n rawTx: rootNodeTx.toBytes(),\n signingNonceCommitment: rootNodeSigningCommitment,\n };\n const rootCreationNode: CreationNodeWithNonces = {\n nodeTxSigningJob: rootNodeSigningJob,\n refundTxSigningJob: undefined,\n children: [],\n };\n rootCreationNode.nodeTxSigningCommitment = rootNodeSigningCommitment;\n\n const leftChild = root.children[0];\n const rightChild = root.children[1];\n if (!leftChild || !rightChild) {\n throw new Error(\"Root children are undefined\");\n }\n\n const leftChildCreationNode = await this.buildChildCreationNode(\n leftChild,\n rootNodeTx,\n 0,\n network,\n );\n const rightChildCreationNode = await this.buildChildCreationNode(\n rightChild,\n rootNodeTx,\n 1,\n network,\n );\n\n rootCreationNode.children.push(leftChildCreationNode);\n rootCreationNode.children.push(rightChildCreationNode);\n\n return rootCreationNode;\n }\n\n private async signNodeCreation(\n parentTx: Transaction,\n vout: number,\n internalNode: DepositAddressTree,\n creationNode: CreationNodeWithNonces,\n creationResponseNode: CreationResponseNode,\n ): Promise<{ tx: Transaction; signature: NodeSignatures }> {\n if (\n !creationNode.nodeTxSigningJob?.signingPublicKey ||\n !internalNode.verificationKey\n ) {\n throw new Error(\"signingPublicKey or verificationKey is undefined\");\n }\n\n const parentTxOutput = parentTx.getOutput(vout);\n if (!parentTxOutput) {\n throw new Error(\"parentTxOutput is undefined\");\n }\n\n const tx = getTxFromRawTxBytes(creationNode.nodeTxSigningJob.rawTx);\n const txSighash = getSigHashFromTx(tx, 0, parentTxOutput);\n\n let nodeTxSignature: Uint8Array = new Uint8Array();\n if (creationNode.nodeTxSigningCommitment) {\n const userSignature = await this.config.signer.signFrost({\n message: txSighash,\n publicKey: creationNode.nodeTxSigningJob.signingPublicKey,\n privateAsPubKey: internalNode.signingPublicKey,\n selfCommitment: creationNode.nodeTxSigningCommitment,\n statechainCommitments:\n creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,\n verifyingKey: internalNode.verificationKey,\n });\n\n nodeTxSignature = await this.config.signer.aggregateFrost({\n message: txSighash,\n statechainSignatures:\n creationResponseNode.nodeTxSigningResult?.signatureShares,\n statechainPublicKeys:\n creationResponseNode.nodeTxSigningResult?.publicKeys,\n verifyingKey: internalNode.verificationKey,\n statechainCommitments:\n creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,\n selfCommitment: creationNode.nodeTxSigningCommitment,\n selfSignature: userSignature,\n publicKey: internalNode.signingPublicKey,\n });\n }\n\n let refundTxSignature: Uint8Array = new Uint8Array();\n if (creationNode.refundTxSigningCommitment) {\n const rawTx = creationNode.refundTxSigningJob?.rawTx;\n if (!rawTx) {\n throw new Error(\"rawTx is undefined\");\n }\n if (!creationNode.refundTxSigningJob?.signingPublicKey) {\n throw new Error(\"signingPublicKey is undefined\");\n }\n const refundTx = getTxFromRawTxBytes(rawTx);\n const refundTxSighash = getSigHashFromTx(refundTx, 0, parentTxOutput);\n\n const refundSigningResponse = await this.config.signer.signFrost({\n message: refundTxSighash,\n publicKey: creationNode.refundTxSigningJob.signingPublicKey,\n privateAsPubKey: internalNode.signingPublicKey,\n selfCommitment: creationNode.refundTxSigningCommitment,\n statechainCommitments:\n creationResponseNode.refundTxSigningResult?.signingNonceCommitments,\n verifyingKey: internalNode.verificationKey,\n });\n\n refundTxSignature = await this.config.signer.aggregateFrost({\n message: refundTxSighash,\n statechainSignatures:\n creationResponseNode.refundTxSigningResult?.signatureShares,\n statechainPublicKeys:\n creationResponseNode.refundTxSigningResult?.publicKeys,\n verifyingKey: internalNode.verificationKey,\n statechainCommitments:\n creationResponseNode.refundTxSigningResult?.signingNonceCommitments,\n selfCommitment: creationNode.refundTxSigningCommitment,\n selfSignature: refundSigningResponse,\n publicKey: internalNode.signingPublicKey,\n });\n }\n\n return {\n tx: tx,\n signature: {\n nodeId: creationResponseNode.nodeId,\n nodeTxSignature: nodeTxSignature,\n refundTxSignature: refundTxSignature,\n },\n };\n }\n\n private async signTreeCreation(\n tx: Transaction,\n vout: number,\n root: DepositAddressTree,\n rootCreationNode: CreationNodeWithNonces,\n creationResultTreeRoot: CreationResponseNode,\n ): Promise<NodeSignatures[]> {\n const rootSignature = await this.signNodeCreation(\n tx,\n vout,\n root,\n rootCreationNode,\n creationResultTreeRoot,\n );\n\n const firstRootChild = root.children[0];\n const secondRootChild = root.children[1];\n const firstRootChildCreationNode = rootCreationNode.children[0];\n const secondRootChildCreationNode = rootCreationNode.children[1];\n const firstRootChildCreationResult = creationResultTreeRoot.children[0];\n const secondRootChildCreationResult = creationResultTreeRoot.children[1];\n if (!firstRootChild || !secondRootChild) {\n throw new Error(\"Root children are undefined\");\n }\n\n if (!firstRootChildCreationNode || !secondRootChildCreationNode) {\n throw new Error(\"Root child creation nodes are undefined\");\n }\n\n if (!firstRootChildCreationResult || !secondRootChildCreationResult) {\n throw new Error(\"Root child creation results are undefined\");\n }\n\n const leftChildSignature = await this.signNodeCreation(\n rootSignature.tx,\n 0,\n firstRootChild,\n firstRootChildCreationNode,\n firstRootChildCreationResult,\n );\n\n const rightChildSignature = await this.signNodeCreation(\n rootSignature.tx,\n 1,\n secondRootChild,\n secondRootChildCreationNode,\n secondRootChildCreationResult,\n );\n\n const signatures = [\n rootSignature.signature,\n leftChildSignature.signature,\n rightChildSignature.signature,\n ];\n\n return signatures;\n }\n}\n","import { bytesToHex, hexToBytes } from \"@noble/curves/abstract/utils\";\nimport { schnorr, secp256k1 } from \"@noble/curves/secp256k1\";\nimport * as btc from \"@scure/btc-signer\";\nimport { Address, OutScript, SigHash, Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput, TransactionOutput } from \"@scure/btc-signer/psbt\";\nimport { taprootTweakPrivKey } from \"@scure/btc-signer/utils\";\nimport { RPCError } from \"../../errors/index.js\";\nimport {\n getP2TRAddressFromPublicKey,\n getP2TRScriptFromPublicKey,\n} from \"../../utils/bitcoin.js\";\nimport { getNetwork, Network } from \"../../utils/network.js\";\n\n// Static keys for deterministic testing\n// P2TRAddress: bcrt1p2uy9zw5ltayucsuzl4tet6ckelzawp08qrtunacscsszflye907q62uqhl\nconst STATIC_FAUCET_KEY = hexToBytes(\n \"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242\",\n);\n\n// P2TRAddress: bcrt1pwr5k38p68ceyrnm2tvrp50dvmg3grh6uvayjl3urwtxejhd3dw4swz6p58\nconst STATIC_MINING_KEY = hexToBytes(\n \"1337cafe4242deadbeef4242424242421337cafe4242deadbeef424242424242\",\n);\nconst SATS_PER_BTC = 100_000_000;\n\nexport type FaucetCoin = {\n key: Uint8Array;\n outpoint: TransactionInput;\n txout: TransactionOutput;\n};\n\n// The amount of satoshis to put in each faucet coin to be used in tests\nconst COIN_AMOUNT = 10_000_000n;\nconst FEE_AMOUNT = 1000n;\nconst TARGET_NUM_COINS = 20;\n\nexport class BitcoinFaucet {\n private coins: FaucetCoin[] = [];\n private static instance: BitcoinFaucet | null = null;\n private miningAddress: string;\n private lock: Promise<void> = Promise.resolve();\n\n private constructor(\n private url: string = \"http://127.0.0.1:8332\",\n private username: string = \"testutil\",\n private password: string = \"testutilpassword\",\n ) {\n this.miningAddress = getP2TRAddressFromPublicKey(\n secp256k1.getPublicKey(STATIC_MINING_KEY),\n Network.LOCAL,\n );\n }\n\n static getInstance(\n url: string = \"http://127.0.0.1:8332\",\n username: string = \"testutil\",\n password: string = \"testutilpassword\",\n ): BitcoinFaucet {\n if (!BitcoinFaucet.instance) {\n BitcoinFaucet.instance = new BitcoinFaucet(url, username, password);\n }\n return BitcoinFaucet.instance;\n }\n\n private async withLock<T>(operation: () => Promise<T>): Promise<T> {\n const current = this.lock;\n let resolve: () => void;\n this.lock = new Promise<void>((r) => (resolve = r));\n await current;\n try {\n return await operation();\n } finally {\n resolve!();\n }\n }\n\n async fund(): Promise<FaucetCoin> {\n return this.withLock(async () => {\n if (this.coins.length === 0) {\n await this.refill();\n }\n\n const coin = this.coins[0];\n if (!coin) {\n throw new Error(\"Failed to get coin from faucet\");\n }\n this.coins = this.coins.slice(1);\n return coin;\n });\n }\n\n private async refill(): Promise<void> {\n const minerPubKey = secp256k1.getPublicKey(STATIC_MINING_KEY);\n const address = getP2TRAddressFromPublicKey(minerPubKey, Network.LOCAL);\n\n // Use scantxoutset to find UTXOs\n const scanResult = await this.call(\"scantxoutset\", [\n \"start\",\n [`addr(${address})`],\n ]);\n\n let selectedUtxo;\n let selectedUtxoAmountSats;\n if (!scanResult.success || scanResult.unspents.length === 0) {\n const blockHash = await this.generateToAddress(1, address);\n const block = await this.getBlock(blockHash[0]);\n const fundingTx = Transaction.fromRaw(hexToBytes(block.tx[0].hex), {\n allowUnknownOutputs: true,\n });\n\n await this.generateToAddress(100, this.miningAddress);\n\n selectedUtxo = {\n txid: block.tx[0].txid,\n vout: 0,\n amount: fundingTx.getOutput(0)!.amount!, // Already in sats\n };\n selectedUtxoAmountSats = BigInt(selectedUtxo.amount);\n } else {\n selectedUtxo = scanResult.unspents.find((utxo) => {\n const isValueEnough =\n BigInt(Math.floor(utxo.amount * SATS_PER_BTC)) >=\n COIN_AMOUNT + FEE_AMOUNT;\n const isMature = scanResult.height - utxo.height >= 100;\n return isValueEnough && isMature;\n });\n\n if (!selectedUtxo) {\n throw new Error(\"No UTXO large enough to create even one faucet coin\");\n }\n selectedUtxoAmountSats = BigInt(\n Math.floor(selectedUtxo.amount * SATS_PER_BTC),\n );\n }\n\n const maxPossibleCoins = Number(\n (selectedUtxoAmountSats - FEE_AMOUNT) / COIN_AMOUNT,\n );\n const numCoinsToCreate = Math.min(maxPossibleCoins, TARGET_NUM_COINS);\n\n if (numCoinsToCreate < 1) {\n throw new Error(\n `Selected UTXO (${selectedUtxoAmountSats} sats) is too small to create even one faucet coin of ${COIN_AMOUNT} sats`,\n );\n }\n\n const splitTx = new Transaction();\n splitTx.addInput({\n txid: selectedUtxo.txid,\n index: selectedUtxo.vout,\n });\n\n const faucetPubKey = secp256k1.getPublicKey(STATIC_FAUCET_KEY);\n const script = getP2TRScriptFromPublicKey(faucetPubKey, Network.LOCAL);\n for (let i = 0; i < numCoinsToCreate; i++) {\n splitTx.addOutput({\n script,\n amount: COIN_AMOUNT,\n });\n }\n\n const remainingValue =\n selectedUtxoAmountSats -\n COIN_AMOUNT * BigInt(numCoinsToCreate) -\n FEE_AMOUNT;\n const minerScript = getP2TRScriptFromPublicKey(minerPubKey, Network.LOCAL);\n if (remainingValue > 0n) {\n splitTx.addOutput({\n script: minerScript,\n amount: remainingValue,\n });\n }\n\n const signedSplitTx = await this.signFaucetCoin(\n splitTx,\n {\n amount: selectedUtxoAmountSats,\n script: minerScript,\n },\n STATIC_MINING_KEY,\n );\n\n await this.broadcastTx(bytesToHex(signedSplitTx.extract()));\n\n const splitTxId = signedSplitTx.id;\n for (let i = 0; i < numCoinsToCreate; i++) {\n this.coins.push({\n key: STATIC_FAUCET_KEY,\n outpoint: {\n txid: hexToBytes(splitTxId),\n index: i,\n },\n txout: signedSplitTx.getOutput(i)!,\n });\n }\n }\n\n async sendFaucetCoinToP2WPKHAddress(pubKey: Uint8Array) {\n const sendToPubKeyTx = new Transaction();\n\n // For P2WPKH, we need to hash the public key\n\n // Create a P2WPKH address\n const p2wpkhAddress = btc.p2wpkh(pubKey, getNetwork(Network.LOCAL)).address;\n if (!p2wpkhAddress) {\n throw new Error(\"Invalid P2WPKH address\");\n }\n\n // Get the coin to spend\n const coinToSend = await this.fund();\n if (!coinToSend) {\n throw new Error(\"No coins available\");\n }\n\n // Add the input\n sendToPubKeyTx.addInput(coinToSend.outpoint);\n\n // Add the output using the address directly, but subtract FEE_AMOUNT to ensure there's a fee\n sendToPubKeyTx.addOutputAddress(\n p2wpkhAddress,\n COIN_AMOUNT - FEE_AMOUNT,\n getNetwork(Network.LOCAL),\n );\n\n // Sign the transaction and get the signed result\n const signedTx = await this.signFaucetCoin(\n sendToPubKeyTx,\n coinToSend.txout,\n coinToSend.key,\n );\n\n // Broadcast the signed transaction\n await this.broadcastTx(bytesToHex(signedTx.extract()));\n }\n\n async signFaucetCoin(\n unsignedTx: Transaction,\n fundingTxOut: TransactionOutput,\n key: Uint8Array,\n ): Promise<Transaction> {\n const pubKey = secp256k1.getPublicKey(key);\n const internalKey = pubKey.slice(1); // Remove the 0x02/0x03 prefix\n\n const script = getP2TRScriptFromPublicKey(pubKey, Network.LOCAL);\n\n unsignedTx.updateInput(0, {\n tapInternalKey: internalKey,\n witnessUtxo: {\n script,\n amount: fundingTxOut.amount!,\n },\n });\n\n const sighash = unsignedTx.preimageWitnessV1(\n 0,\n new Array(unsignedTx.inputsLength).fill(script),\n SigHash.DEFAULT,\n new Array(unsignedTx.inputsLength).fill(fundingTxOut.amount!),\n );\n\n const merkleRoot = new Uint8Array();\n const tweakedKey = taprootTweakPrivKey(key, merkleRoot);\n if (!tweakedKey)\n throw new Error(\"Invalid private key for taproot tweaking\");\n\n const signature = schnorr.sign(sighash, tweakedKey);\n\n unsignedTx.updateInput(0, {\n tapKeySig: signature,\n });\n\n unsignedTx.finalize();\n\n return unsignedTx;\n }\n\n // MineBlocks mines the specified number of blocks to a random address\n // and returns the block hashes.\n async mineBlocks(numBlocks: number) {\n return await this.generateToAddress(numBlocks, this.miningAddress);\n }\n\n private async call(method: string, params: any[]) {\n try {\n const response = await fetch(this.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Basic \" + btoa(`${this.username}:${this.password}`),\n },\n body: JSON.stringify({\n jsonrpc: \"1.0\",\n id: \"spark-js\",\n method,\n params,\n }),\n });\n\n const data = await response.json();\n if (data.error) {\n console.error(`RPC Error for method ${method}:`, data.error);\n throw new RPCError(`Bitcoin RPC error: ${data.error.message}`, {\n method,\n params,\n code: data.error.code,\n });\n }\n\n return data.result;\n } catch (error) {\n if (error instanceof RPCError) {\n throw error;\n }\n throw new RPCError(\n \"Failed to call Bitcoin RPC\",\n {\n method,\n params,\n },\n error as Error,\n );\n }\n }\n\n async generateToAddress(numBlocks: number, address: string) {\n return await this.call(\"generatetoaddress\", [numBlocks, address]);\n }\n\n async getBlock(blockHash: string) {\n return await this.call(\"getblock\", [blockHash, 2]);\n }\n\n async broadcastTx(txHex: string) {\n let response = await this.call(\"sendrawtransaction\", [txHex, 0]);\n return response;\n }\n\n async getNewAddress(): Promise<string> {\n const key = secp256k1.utils.randomPrivateKey();\n const pubKey = secp256k1.getPublicKey(key);\n return getP2TRAddressFromPublicKey(pubKey, Network.LOCAL);\n }\n\n async sendToAddress(address: string, amount: bigint): Promise<Transaction> {\n const coin = await this.fund();\n if (!coin) {\n throw new Error(\"No coins available\");\n }\n\n const tx = new Transaction();\n tx.addInput(coin.outpoint);\n\n const availableAmount = COIN_AMOUNT - FEE_AMOUNT;\n\n const destinationAddress = Address(getNetwork(Network.LOCAL)).decode(\n address,\n );\n const destinationScript = OutScript.encode(destinationAddress);\n tx.addOutput({\n script: destinationScript,\n amount: amount,\n });\n\n const changeAmount = availableAmount - amount;\n if (changeAmount > 0) {\n const changeKey = secp256k1.utils.randomPrivateKey();\n const changePubKey = secp256k1.getPublicKey(changeKey);\n const changeScript = getP2TRScriptFromPublicKey(\n changePubKey,\n Network.LOCAL,\n );\n tx.addOutput({\n script: changeScript,\n amount: changeAmount,\n });\n }\n\n const signedTx = await this.signFaucetCoin(tx, coin.txout, coin.key);\n const txHex = bytesToHex(signedTx.extract());\n await this.broadcastTx(txHex);\n\n await this.generateToAddress(1, address);\n\n return signedTx;\n }\n\n async getRawTransaction(txid: string) {\n return await this.call(\"getrawtransaction\", [txid, 2]);\n }\n}\n"],"mappings":"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","names":["bytesToHex","bytesToNumberBE","equalBytes","hexToBytes","secp256k1","Address","OutScript","sha256","decode","uuidv7","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","Transaction","uuidv7","bytesToHex","sha256","bytesToHex","sha256","crypto","Transaction","uuidv7","hexToBytes","numberToBytesBE","secp256k1","sha256","uuidv7","crypto","numberToBytesBE","secp256k1","sha256","uuidv7","hexToBytes","Transaction","sha256","INITIAL_TIME_LOCK","sha256","Transaction","bytesToHex","hexToBytes","secp256k1","Address","OutScript","Transaction","hexToBytes","secp256k1","Transaction","bytesToHex","Address","OutScript","crypto","equalBytes","sha256","error","bytesToHex","hexToBytes","refundSignature","secp256k1","uuidv7","leaf","bytesToNumberBE","OutScript","Address","nodes","amountSats","memo","invoice","decode"]}
1
+ {"version":3,"sources":["../src/spark-wallet.ts","../src/graphql/client.ts","../src/graphql/mutations/CompleteCoopExit.ts","../src/graphql/mutations/CompleteLeavesSwap.ts","../src/graphql/mutations/GetChallenge.ts","../src/graphql/mutations/RequestCoopExit.ts","../src/graphql/mutations/RequestLightningReceive.ts","../src/graphql/mutations/RequestLightningSend.ts","../src/graphql/mutations/RequestSwapLeaves.ts","../src/graphql/mutations/VerifyChallenge.ts","../src/graphql/queries/CoopExitFeeEstimate.ts","../src/graphql/queries/LeavesSwapFeeEstimate.ts","../src/graphql/queries/LightningSendFeeEstimate.ts","../src/graphql/queries/UserRequest.ts","../src/services/coop-exit.ts","../src/services/transfer.ts","../src/services/lightning.ts","../src/services/tree-creation.ts","../src/tests/utils/test-faucet.ts"],"sourcesContent":["import { createLrc20ConnectionManager } from \"@buildonspark/lrc20-sdk/grpc\";\nimport { ILrc20ConnectionManager } from \"@buildonspark/lrc20-sdk/grpc/types\";\nimport { isNode, mapCurrencyAmount } from \"@lightsparkdev/core\";\nimport {\n bytesToHex,\n bytesToNumberBE,\n equalBytes,\n hexToBytes,\n} from \"@noble/curves/abstract/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { validateMnemonic } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english\";\nimport { Address, OutScript, Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport { Mutex } from \"async-mutex\";\nimport { decode } from \"light-bolt11-decoder\";\nimport { uuidv7 } from \"uuidv7\";\nimport {\n ConfigurationError,\n NetworkError,\n RPCError,\n ValidationError,\n} from \"./errors/types.js\";\n\nimport SspClient from \"./graphql/client.js\";\nimport {\n BitcoinNetwork,\n CoopExitFeeEstimatesOutput,\n CoopExitRequest,\n ExitSpeed,\n LeavesSwapFeeEstimateOutput,\n LeavesSwapRequest,\n LightningReceiveRequest,\n LightningSendFeeEstimateInput,\n LightningSendRequest,\n UserLeafInput,\n} from \"./graphql/objects/index.js\";\nimport {\n DepositAddressQueryResult,\n OutputWithPreviousTransactionData,\n QueryTransfersResponse,\n SubscribeToEventsResponse,\n TokenTransactionWithStatus,\n Transfer,\n TransferStatus,\n TransferType,\n TreeNode,\n} from \"./proto/spark.js\";\nimport { WalletConfigService } from \"./services/config.js\";\nimport { ConnectionManager } from \"./services/connection.js\";\nimport { CoopExitService } from \"./services/coop-exit.js\";\nimport { DepositService } from \"./services/deposit.js\";\nimport { LightningService } from \"./services/lightning.js\";\nimport { TokenTransactionService } from \"./services/token-transactions.js\";\nimport { LeafKeyTweak, TransferService } from \"./services/transfer.js\";\nimport {\n DepositAddressTree,\n TreeCreationService,\n} from \"./services/tree-creation.js\";\nimport {\n ConfigOptions,\n ELECTRS_CREDENTIALS,\n} from \"./services/wallet-config.js\";\nimport {\n applyAdaptorToSignature,\n generateAdaptorFromSignature,\n generateSignatureFromExistingAdaptor,\n} from \"./utils/adaptor-signature.js\";\nimport {\n computeTaprootKeyNoScript,\n getP2WPKHAddressFromPublicKey,\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxFromRawTxHex,\n getTxId,\n} from \"./utils/bitcoin.js\";\nimport {\n getNetwork,\n LRC_WALLET_NETWORK,\n LRC_WALLET_NETWORK_TYPE,\n Network,\n} from \"./utils/network.js\";\nimport {\n calculateAvailableTokenAmount,\n checkIfSelectedOutputsAreAvailable,\n} from \"./utils/token-transactions.js\";\nimport { getNextTransactionSequence } from \"./utils/transaction.js\";\n\nimport { LRCWallet } from \"@buildonspark/lrc20-sdk\";\nimport { EventEmitter } from \"eventemitter3\";\nimport {\n decodeSparkAddress,\n encodeSparkAddress,\n SparkAddressFormat,\n} from \"./address/index.js\";\nimport { isReactNative } from \"./constants.js\";\nimport { SparkSigner } from \"./signer/signer.js\";\nimport { BitcoinFaucet } from \"./tests/utils/test-faucet.js\";\nimport {\n mapTransferToWalletTransfer,\n mapTreeNodeToWalletLeaf,\n WalletLeaf,\n WalletTransfer,\n} from \"./types/sdk-types.js\";\nimport { getCrypto } from \"./utils/crypto.js\";\nimport { getMasterHDKeyFromSeed } from \"./utils/index.js\";\nimport type { Tracer } from \"@opentelemetry/api\";\n\nconst crypto = getCrypto();\n\nexport type CreateLightningInvoiceParams = {\n amountSats: number;\n memo?: string;\n expirySeconds?: number;\n};\n\nexport type PayLightningInvoiceParams = {\n invoice: string;\n maxFeeSats: number;\n};\n\nexport type TransferParams = {\n amountSats: number;\n receiverSparkAddress: string;\n};\n\ntype DepositParams = {\n signingPubKey: Uint8Array;\n verifyingKey: Uint8Array;\n depositTx: Transaction;\n vout: number;\n};\n\nexport type TokenInfo = {\n tokenPublicKey: string;\n tokenName: string;\n tokenSymbol: string;\n tokenDecimals: number;\n maxSupply: bigint;\n};\n\nexport type InitWalletResponse = {\n mnemonic?: string | undefined;\n};\nexport interface SparkWalletProps {\n mnemonicOrSeed?: Uint8Array | string;\n accountNumber?: number;\n signer?: SparkSigner;\n options?: ConfigOptions;\n}\n\nexport interface SparkWalletEvents {\n /** Emitted when an incoming transfer is successfully claimed. Includes the transfer ID and new total balance. */\n \"transfer:claimed\": (transferId: string, updatedBalance: number) => void;\n /** Emitted when a deposit is marked as available. Includes the deposit ID and new total balance. */\n \"deposit:confirmed\": (depositId: string, updatedBalance: number) => void;\n /** Emitted when the stream is connected */\n \"stream:connected\": () => void;\n /** Emitted when the stream disconnects and fails to reconnect after max attempts */\n \"stream:disconnected\": (reason: string) => void;\n /** Emitted when attempting to reconnect the stream */\n \"stream:reconnecting\": (\n attempt: number,\n maxAttempts: number,\n delayMs: number,\n error: string,\n ) => void;\n}\n\n/**\n * The SparkWallet class is the primary interface for interacting with the Spark network.\n * It provides methods for creating and managing wallets, handling deposits, executing transfers,\n * and interacting with the Lightning Network.\n */\nexport class SparkWallet extends EventEmitter {\n private tracer: Tracer | null = null;\n\n protected config: WalletConfigService;\n\n protected connectionManager: ConnectionManager;\n protected lrc20ConnectionManager: ILrc20ConnectionManager;\n protected lrc20Wallet: LRCWallet | undefined;\n protected transferService: TransferService;\n protected tracerId = \"spark-sdk\";\n\n private depositService: DepositService;\n private treeCreationService: TreeCreationService;\n private lightningService: LightningService;\n private coopExitService: CoopExitService;\n private tokenTransactionService: TokenTransactionService;\n\n private claimTransferMutex = new Mutex();\n private leavesMutex = new Mutex();\n private optimizationInProgress = false;\n private sspClient: SspClient | null = null;\n\n private mutexes: Map<string, Mutex> = new Map();\n\n private pendingWithdrawnOutputIds: string[] = [];\n\n private sparkAddress: SparkAddressFormat | undefined;\n\n private streamController: AbortController | null = null;\n\n protected leaves: TreeNode[] = [];\n protected tokenOutputs: Map<string, OutputWithPreviousTransactionData[]> =\n new Map();\n\n // Add this property near the top of the class with other private properties\n private claimTransfersInterval: NodeJS.Timeout | null = null;\n\n protected wrapWithOtelSpan<T>(\n name: string,\n fn: (...args: any[]) => Promise<T>,\n ): (...args: any[]) => Promise<T> {\n return async (...args: any[]): Promise<T> => {\n if (!this.tracer) {\n throw new Error(\"Tracer not initialized\");\n }\n\n return await this.tracer.startActiveSpan(name, async (span) => {\n const traceId = span.spanContext().traceId;\n try {\n return await fn(...args);\n } catch (error) {\n if (error instanceof Error) {\n error.message += ` [traceId: ${traceId}]`;\n } else if (typeof error === \"object\" && error !== null) {\n (error as any).traceId = traceId;\n }\n throw error;\n } finally {\n span.end();\n }\n });\n };\n }\n\n protected async initializeTracer(tracerName: string) {\n const { trace, propagation, context } = await import(\"@opentelemetry/api\");\n const { W3CTraceContextPropagator } = await import(\"@opentelemetry/core\");\n const { AsyncLocalStorageContextManager } = await import(\n \"@opentelemetry/context-async-hooks\"\n );\n const { BasicTracerProvider } = await import(\n \"@opentelemetry/sdk-trace-base\"\n );\n\n trace.setGlobalTracerProvider(new BasicTracerProvider());\n propagation.setGlobalPropagator(new W3CTraceContextPropagator());\n context.setGlobalContextManager(new AsyncLocalStorageContextManager());\n\n this.tracer = trace.getTracer(tracerName);\n }\n\n private wrapSparkWalletWithTracing() {\n this.getIdentityPublicKey = this.wrapWithOtelSpan(\n \"SparkWallet.getIdentityPublicKey\",\n this.getIdentityPublicKey.bind(this),\n );\n this.getSparkAddress = this.wrapWithOtelSpan(\n \"SparkWallet.getSparkAddress\",\n this.getSparkAddress.bind(this),\n );\n this.getSwapFeeEstimate = this.wrapWithOtelSpan(\n \"SparkWallet.getSwapFeeEstimate\",\n this.getSwapFeeEstimate.bind(this),\n );\n this.getTransfers = this.wrapWithOtelSpan(\n \"SparkWallet.getTransfers\",\n this.getTransfers.bind(this),\n );\n this.getTokenInfo = this.wrapWithOtelSpan(\n \"SparkWallet.getTokenInfo\",\n this.getTokenInfo.bind(this),\n );\n this.getBalance = this.wrapWithOtelSpan(\n \"SparkWallet.getBalance\",\n this.getBalance.bind(this),\n );\n this.getSingleUseDepositAddress = this.wrapWithOtelSpan(\n \"SparkWallet.getSingleUseDepositAddress\",\n this.getSingleUseDepositAddress.bind(this),\n );\n this.getUnusedDepositAddresses = this.wrapWithOtelSpan(\n \"SparkWallet.getUnusedDepositAddresses\",\n this.getUnusedDepositAddresses.bind(this),\n );\n this.claimDeposit = this.wrapWithOtelSpan(\n \"SparkWallet.claimDeposit\",\n this.claimDeposit.bind(this),\n );\n this.advancedDeposit = this.wrapWithOtelSpan(\n \"SparkWallet.advancedDeposit\",\n this.advancedDeposit.bind(this),\n );\n this.transfer = this.wrapWithOtelSpan(\n \"SparkWallet.transfer\",\n this.transfer.bind(this),\n );\n this.createLightningInvoice = this.wrapWithOtelSpan(\n \"SparkWallet.createLightningInvoice\",\n this.createLightningInvoice.bind(this),\n );\n this.payLightningInvoice = this.wrapWithOtelSpan(\n \"SparkWallet.payLightningInvoice\",\n this.payLightningInvoice.bind(this),\n );\n this.getLightningSendFeeEstimate = this.wrapWithOtelSpan(\n \"SparkWallet.getLightningSendFeeEstimate\",\n this.getLightningSendFeeEstimate.bind(this),\n );\n this.withdraw = this.wrapWithOtelSpan(\n \"SparkWallet.withdraw\",\n this.withdraw.bind(this),\n );\n this.getWithdrawalFeeEstimate = this.wrapWithOtelSpan(\n \"SparkWallet.getWithdrawalFeeEstimate\",\n this.getWithdrawalFeeEstimate.bind(this),\n );\n }\n\n protected constructor(options?: ConfigOptions, signer?: SparkSigner) {\n super();\n\n this.config = new WalletConfigService(options, signer);\n this.connectionManager = new ConnectionManager(this.config);\n this.lrc20ConnectionManager = createLrc20ConnectionManager(\n this.config.getLrc20Address(),\n );\n this.depositService = new DepositService(\n this.config,\n this.connectionManager,\n );\n this.transferService = new TransferService(\n this.config,\n this.connectionManager,\n );\n this.treeCreationService = new TreeCreationService(\n this.config,\n this.connectionManager,\n );\n this.tokenTransactionService = new TokenTransactionService(\n this.config,\n this.connectionManager,\n );\n this.lightningService = new LightningService(\n this.config,\n this.connectionManager,\n );\n this.coopExitService = new CoopExitService(\n this.config,\n this.connectionManager,\n );\n }\n\n public static async initialize({\n mnemonicOrSeed,\n accountNumber,\n signer,\n options,\n }: SparkWalletProps) {\n const wallet = new SparkWallet(options, signer);\n const initResponse = await wallet.initWallet(mnemonicOrSeed, accountNumber);\n\n return {\n wallet,\n ...initResponse,\n };\n }\n\n private async initializeWallet() {\n this.sspClient = new SspClient(this.config);\n await this.connectionManager.createClients();\n\n if (isReactNative) {\n this.startPeriodicClaimTransfers();\n } else {\n this.setupBackgroundStream();\n }\n\n await this.syncWallet();\n }\n\n private async handleStreamEvent({ event }: SubscribeToEventsResponse) {\n try {\n if (\n event?.$case === \"transfer\" &&\n event.transfer.transfer &&\n event.transfer.transfer.type !== TransferType.COUNTER_SWAP\n ) {\n const { senderIdentityPublicKey, receiverIdentityPublicKey } =\n event.transfer.transfer;\n\n // Don't claim if this is a self transfer, that's handled elsewhere\n if (\n event.transfer.transfer &&\n !equalBytes(senderIdentityPublicKey, receiverIdentityPublicKey)\n ) {\n await this.claimTransfer(event.transfer.transfer, true);\n }\n } else if (event?.$case === \"deposit\" && event.deposit.deposit) {\n const deposit = event.deposit.deposit;\n const signingKey = await this.config.signer.generatePublicKey(\n sha256(deposit.id),\n );\n\n const newLeaf = await this.transferService.extendTimelock(\n deposit,\n signingKey,\n );\n await this.transferLeavesToSelf(newLeaf.nodes, signingKey);\n this.emit(\n \"deposit:confirmed\",\n deposit.id,\n (await this.getBalance()).balance,\n );\n }\n } catch (error) {\n console.error(\"Error processing event\", error);\n }\n }\n\n protected async setupBackgroundStream() {\n const MAX_RETRIES = 10;\n const INITIAL_DELAY = 1000;\n const MAX_DELAY = 60000;\n\n this.streamController = new AbortController();\n\n const delay = (ms: number, signal?: AbortSignal): Promise<boolean> => {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n if (signal) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n resolve(true);\n }, ms);\n\n function onAbort() {\n clearTimeout(timer);\n resolve(false);\n signal?.removeEventListener(\"abort\", onAbort);\n }\n\n if (signal) {\n signal.addEventListener(\"abort\", onAbort);\n }\n });\n };\n\n let retryCount = 0;\n while (retryCount <= MAX_RETRIES) {\n try {\n const address = this.config.getCoordinatorAddress();\n\n const sparkClient =\n await this.connectionManager.createSparkStreamClient(address);\n const channel = await this.connectionManager.getStreamChannel(address);\n\n const stream = sparkClient.subscribe_to_events(\n {\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n },\n {\n signal: this.streamController?.signal,\n },\n );\n\n // In Node.js, long-lived gRPC streams keep the underlying socket \"ref'd\",\n // which prevents the process from exiting. To avoid that (e.g. in CLI tools),\n // we manually unref the socket so Node can shut down when nothing else is active.\n //\n // The gRPC client doesn't expose the socket directly, so we dig through\n // internal fields to find it. This is a bit of a hack and may break if the\n // internals change.\n //\n // Since the socket isn't always immediately available, we retry with setTimeout\n // until it shows up.\n const maybeUnref = () => {\n const internalChannel = (channel as any).internalChannel;\n if (\n internalChannel?.currentPicker?.subchannel?.child?.transport\n ?.session?.socket\n ) {\n internalChannel.currentPicker.subchannel.child.transport.session.socket.unref();\n } else {\n setTimeout(maybeUnref, 100);\n }\n };\n\n // Only need to unref in Node environments.\n // In the browser and React Native, the runtime handles shutdown when the tab/app closes.\n if (isNode) {\n maybeUnref();\n }\n\n const claimedTransfersIds = await this.claimTransfers();\n\n try {\n for await (const data of stream) {\n if (this.streamController?.signal.aborted) {\n break;\n }\n\n if (data.event?.$case === \"connected\") {\n console.log(\"connected\");\n this.emit(\"stream:connected\");\n retryCount = 0;\n }\n\n if (\n data.event?.$case === \"transfer\" &&\n data.event.transfer.transfer &&\n claimedTransfersIds.includes(data.event.transfer.transfer.id)\n ) {\n continue;\n }\n await this.handleStreamEvent(data);\n }\n } catch (error) {\n throw error;\n }\n } catch (error) {\n if (this.streamController?.signal.aborted) {\n break;\n }\n\n const backoffDelay = Math.min(\n INITIAL_DELAY * Math.pow(2, retryCount),\n MAX_DELAY,\n );\n\n if (retryCount < MAX_RETRIES) {\n retryCount++;\n this.emit(\n \"stream:reconnecting\",\n retryCount,\n MAX_RETRIES,\n backoffDelay,\n error instanceof Error ? error.message : String(error),\n );\n try {\n const completed = await delay(\n backoffDelay,\n this.streamController?.signal,\n );\n if (!completed) {\n break;\n }\n } catch (error) {\n if (this.streamController?.signal.aborted) {\n break;\n }\n }\n } else {\n this.emit(\"stream:disconnected\", \"Max reconnection attempts reached\");\n break;\n }\n }\n }\n }\n\n private async getLeaves(): Promise<TreeNode[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n const leaves = await sparkClient.query_nodes({\n source: {\n $case: \"ownerIdentityPubkey\",\n ownerIdentityPubkey: await this.config.signer.getIdentityPublicKey(),\n },\n includeParents: false,\n });\n\n return Object.entries(leaves.nodes)\n .filter(([_, node]) => node.status === \"AVAILABLE\")\n .map(([_, node]) => node);\n }\n\n private async selectLeaves(targetAmount: number): Promise<TreeNode[]> {\n if (targetAmount <= 0) {\n throw new ValidationError(\"Target amount must be positive\", {\n field: \"targetAmount\",\n value: targetAmount,\n });\n }\n\n const leaves = await this.getLeaves();\n if (leaves.length === 0) {\n throw new ValidationError(\"No owned leaves found\", {\n field: \"leaves\",\n });\n }\n\n leaves.sort((a, b) => b.value - a.value);\n\n let amount = 0;\n let nodes: TreeNode[] = [];\n for (const leaf of leaves) {\n if (targetAmount - amount >= leaf.value) {\n amount += leaf.value;\n nodes.push(leaf);\n }\n }\n\n if (amount !== targetAmount) {\n await this.requestLeavesSwap({ targetAmount });\n\n amount = 0;\n nodes = [];\n const newLeaves = await this.getLeaves();\n newLeaves.sort((a, b) => b.value - a.value);\n for (const leaf of newLeaves) {\n if (targetAmount - amount >= leaf.value) {\n amount += leaf.value;\n nodes.push(leaf);\n }\n }\n }\n\n if (nodes.reduce((acc, leaf) => acc + leaf.value, 0) !== targetAmount) {\n throw new Error(\n `Failed to select leaves for target amount ${targetAmount}`,\n );\n }\n\n return nodes;\n }\n\n private async selectLeavesForSwap(targetAmount: number) {\n if (targetAmount == 0) {\n throw new Error(\"Target amount needs to > 0\");\n }\n const leaves = await this.getLeaves();\n leaves.sort((a, b) => a.value - b.value);\n\n let amount = 0;\n const nodes: TreeNode[] = [];\n for (const leaf of leaves) {\n if (amount < targetAmount) {\n amount += leaf.value;\n nodes.push(leaf);\n }\n }\n\n if (amount < targetAmount) {\n throw new Error(\"Not enough leaves to swap for the target amount\");\n }\n\n return nodes;\n }\n\n private areLeavesInefficient() {\n const totalAmount = this.getInternalBalance();\n\n if (this.leaves.length <= 1) {\n return false;\n }\n\n const nextLowerPowerOfTwo = 31 - Math.clz32(totalAmount);\n\n let remainingAmount = totalAmount;\n let optimalLeavesLength = 0;\n\n for (let i = nextLowerPowerOfTwo; i >= 0; i--) {\n const denomination = 2 ** i;\n while (remainingAmount >= denomination) {\n remainingAmount -= denomination;\n optimalLeavesLength++;\n }\n }\n\n return this.leaves.length > optimalLeavesLength * 5;\n }\n\n private async optimizeLeaves() {\n if (this.optimizationInProgress || !this.areLeavesInefficient()) {\n return;\n }\n\n await this.withLeaves(async () => {\n this.optimizationInProgress = true;\n try {\n if (this.leaves.length > 0) {\n await this.requestLeavesSwap({ leaves: this.leaves });\n }\n this.leaves = await this.getLeaves();\n } finally {\n this.optimizationInProgress = false;\n }\n });\n }\n\n private async syncWallet() {\n await this.syncTokenOutputs();\n this.leaves = await this.getLeaves();\n await this.config.signer.restoreSigningKeysFromLeafs(this.leaves);\n await this.checkRefreshTimelockNodes();\n await this.checkExtendTimeLockNodes();\n this.optimizeLeaves().catch((e) => {\n console.error(\"Failed to optimize leaves\", e);\n });\n }\n\n private async withLeaves<T>(operation: () => Promise<T>): Promise<T> {\n const release = await this.leavesMutex.acquire();\n try {\n return await operation();\n } finally {\n release();\n }\n }\n\n /**\n * Gets the identity public key of the wallet.\n *\n * @returns {Promise<string>} The identity public key as a hex string.\n */\n public async getIdentityPublicKey(): Promise<string> {\n return bytesToHex(await this.config.signer.getIdentityPublicKey());\n }\n\n /**\n * Gets the Spark address of the wallet.\n *\n * @returns {Promise<string>} The Spark address as a hex string.\n */\n public async getSparkAddress(): Promise<SparkAddressFormat> {\n if (!this.sparkAddress) {\n this.sparkAddress = encodeSparkAddress({\n identityPublicKey: bytesToHex(\n await this.config.signer.getIdentityPublicKey(),\n ),\n network: this.config.getNetworkType(),\n });\n }\n\n return this.sparkAddress;\n }\n\n /**\n * Initializes the wallet using either a mnemonic phrase or a raw seed.\n * initWallet will also claim any pending incoming lightning payment, spark transfer,\n * or bitcoin deposit.\n *\n * @param {Uint8Array | string} [mnemonicOrSeed] - (Optional) Either:\n * - A BIP-39 mnemonic phrase as string\n * - A raw seed as Uint8Array or hex string\n * If not provided, generates a new mnemonic and uses it to create a new wallet\n *\n * @returns {Promise<Object>} Object containing:\n * - mnemonic: The mnemonic if one was generated (undefined for raw seed)\n * - balance: The wallet's initial balance in satoshis\n * - tokenBalance: Map of token balances\n * @private\n */\n protected async initWallet(\n mnemonicOrSeed?: Uint8Array | string,\n accountNumber?: number,\n ): Promise<InitWalletResponse | undefined> {\n if (accountNumber === 0 || accountNumber === 1) {\n // Reserved values for the case where no account number is provided\n throw new ValidationError(\n \"If an account number is provided, it must not be be 0 or 1\",\n {\n field: \"accountNumber\",\n value: accountNumber,\n expected: \"values that do not equal 0 or 1\",\n },\n );\n }\n let mnemonic: string | undefined;\n if (!mnemonicOrSeed) {\n mnemonic = await this.config.signer.generateMnemonic();\n mnemonicOrSeed = mnemonic;\n }\n\n let seed: Uint8Array;\n if (typeof mnemonicOrSeed !== \"string\") {\n seed = mnemonicOrSeed;\n } else {\n if (validateMnemonic(mnemonicOrSeed, wordlist)) {\n mnemonic = mnemonicOrSeed;\n seed = await this.config.signer.mnemonicToSeed(mnemonicOrSeed);\n } else {\n seed = hexToBytes(mnemonicOrSeed);\n }\n }\n await this.initWalletFromSeed(seed, accountNumber);\n\n const network = this.config.getNetwork();\n // TODO: remove this once we move it back to the signer\n if (typeof seed === \"string\") {\n seed = hexToBytes(seed);\n }\n\n const hdkey = getMasterHDKeyFromSeed(seed);\n\n if (!hdkey.privateKey || !hdkey.publicKey) {\n throw new ValidationError(\"Failed to derive keys from seed\", {\n field: \"hdkey\",\n value: seed,\n });\n }\n const accountNetwork = network === Network.REGTEST ? 0 : 1;\n const identityKey = hdkey.derive(\n `m/8797555'/${accountNumber ?? accountNetwork}'/0'`, // When an accountNumber is not provided, set a value based on the network\n );\n this.lrc20Wallet = new LRCWallet(\n bytesToHex(identityKey.privateKey!),\n LRC_WALLET_NETWORK[network],\n LRC_WALLET_NETWORK_TYPE[network],\n this.config.lrc20ApiConfig,\n );\n\n if (isNode) {\n await this.initializeTracer(this.tracerId);\n this.wrapSparkWalletWithTracing();\n }\n\n return {\n mnemonic,\n };\n }\n\n /**\n * Initializes a wallet from a seed.\n *\n * @param {Uint8Array | string} seed - The seed to initialize the wallet from\n * @returns {Promise<string>} The identity public key\n * @private\n */\n private async initWalletFromSeed(\n seed: Uint8Array | string,\n accountNumber?: number,\n ) {\n const identityPublicKey =\n await this.config.signer.createSparkWalletFromSeed(\n seed,\n this.config.getNetwork(),\n accountNumber,\n );\n await this.initializeWallet();\n\n this.sparkAddress = encodeSparkAddress({\n identityPublicKey: identityPublicKey,\n network: this.config.getNetworkType(),\n });\n\n return this.sparkAddress;\n }\n\n /**\n * Gets the estimated fee for a swap of leaves.\n *\n * @param amountSats - The amount of sats to swap\n * @returns {Promise<LeavesSwapFeeEstimateOutput>} The estimated fee for the swap\n */\n public async getSwapFeeEstimate(\n amountSats: number,\n ): Promise<LeavesSwapFeeEstimateOutput> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n const feeEstimate = await this.sspClient.getSwapFeeEstimate(amountSats);\n if (!feeEstimate) {\n throw new Error(\"Failed to get swap fee estimate\");\n }\n\n return feeEstimate;\n }\n\n /**\n * Requests a swap of leaves to optimize wallet structure.\n *\n * @param {Object} params - Parameters for the leaves swap\n * @param {number} [params.targetAmount] - Target amount for the swap\n * @param {TreeNode[]} [params.leaves] - Specific leaves to swap\n * @returns {Promise<Object>} The completed swap response\n * @private\n */\n private async requestLeavesSwap({\n targetAmount,\n leaves,\n }: {\n targetAmount?: number;\n leaves?: TreeNode[];\n }) {\n if (targetAmount && targetAmount <= 0) {\n throw new Error(\"targetAmount must be positive\");\n }\n\n if (targetAmount && !Number.isSafeInteger(targetAmount)) {\n throw new ValidationError(\"targetAmount must be less than 2^53\", {\n field: \"targetAmount\",\n value: targetAmount,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n try {\n await this.claimTransfers();\n } catch (e) {\n console.warn(\"Unabled to claim transfers.\");\n }\n\n let leavesToSwap: TreeNode[];\n if (targetAmount && leaves && leaves.length > 0) {\n if (targetAmount < leaves.reduce((acc, leaf) => acc + leaf.value, 0)) {\n throw new Error(\"targetAmount is less than the sum of leaves\");\n }\n leavesToSwap = leaves;\n } else if (targetAmount) {\n leavesToSwap = await this.selectLeavesForSwap(targetAmount);\n } else if (leaves && leaves.length > 0) {\n leavesToSwap = leaves;\n } else {\n throw new Error(\"targetAmount or leaves must be provided\");\n }\n\n const leafKeyTweaks = await Promise.all(\n leavesToSwap.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const { transfer, signatureMap } =\n await this.transferService.startSwapSignRefund(\n leafKeyTweaks,\n hexToBytes(this.config.getSspIdentityPublicKey()),\n new Date(Date.now() + 2 * 60 * 1000),\n );\n try {\n if (!transfer.leaves[0]?.leaf) {\n throw new Error(\"Failed to get leaf\");\n }\n\n const refundSignature = signatureMap.get(transfer.leaves[0].leaf.id);\n if (!refundSignature) {\n throw new Error(\"Failed to get refund signature\");\n }\n\n const { adaptorPrivateKey, adaptorSignature } =\n generateAdaptorFromSignature(refundSignature);\n\n if (!transfer.leaves[0].leaf) {\n throw new Error(\"Failed to get leaf\");\n }\n\n const userLeaves: UserLeafInput[] = [];\n userLeaves.push({\n leaf_id: transfer.leaves[0].leaf.id,\n raw_unsigned_refund_transaction: bytesToHex(\n transfer.leaves[0].intermediateRefundTx,\n ),\n adaptor_added_signature: bytesToHex(adaptorSignature),\n });\n\n for (let i = 1; i < transfer.leaves.length; i++) {\n const leaf = transfer.leaves[i];\n if (!leaf?.leaf) {\n throw new Error(\"Failed to get leaf\");\n }\n\n const refundSignature = signatureMap.get(leaf.leaf.id);\n if (!refundSignature) {\n throw new Error(\"Failed to get refund signature\");\n }\n\n const signature = generateSignatureFromExistingAdaptor(\n refundSignature,\n adaptorPrivateKey,\n );\n\n userLeaves.push({\n leaf_id: leaf.leaf.id,\n raw_unsigned_refund_transaction: bytesToHex(\n leaf.intermediateRefundTx,\n ),\n adaptor_added_signature: bytesToHex(signature),\n });\n }\n\n const adaptorPubkey = bytesToHex(\n secp256k1.getPublicKey(adaptorPrivateKey),\n );\n let request: LeavesSwapRequest | null | undefined = null;\n request = await this.sspClient?.requestLeaveSwap({\n userLeaves,\n adaptorPubkey,\n targetAmountSats:\n targetAmount ||\n leavesToSwap.reduce((acc, leaf) => acc + leaf.value, 0),\n totalAmountSats: leavesToSwap.reduce(\n (acc, leaf) => acc + leaf.value,\n 0,\n ),\n // TODO: Request fee from SSP\n feeSats: 0,\n idempotencyKey: uuidv7(),\n });\n\n if (!request) {\n throw new Error(\"Failed to request leaves swap. No response returned.\");\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const nodes = await sparkClient.query_nodes({\n source: {\n $case: \"nodeIds\",\n nodeIds: {\n nodeIds: request.swapLeaves.map((leaf) => leaf.leafId),\n },\n },\n includeParents: false,\n });\n\n if (Object.values(nodes.nodes).length !== request.swapLeaves.length) {\n throw new Error(\"Expected same number of nodes as swapLeaves\");\n }\n\n for (const [nodeId, node] of Object.entries(nodes.nodes)) {\n if (!node.nodeTx) {\n throw new Error(`Node tx not found for leaf ${nodeId}`);\n }\n\n if (!node.verifyingPublicKey) {\n throw new Error(`Node public key not found for leaf ${nodeId}`);\n }\n\n const leaf = request.swapLeaves.find((leaf) => leaf.leafId === nodeId);\n if (!leaf) {\n throw new Error(`Leaf not found for node ${nodeId}`);\n }\n\n // @ts-ignore - We do a null check above\n const nodeTx = getTxFromRawTxBytes(node.nodeTx);\n const refundTxBytes = hexToBytes(leaf.rawUnsignedRefundTransaction);\n const refundTx = getTxFromRawTxBytes(refundTxBytes);\n const sighash = getSigHashFromTx(refundTx, 0, nodeTx.getOutput(0));\n\n const nodePublicKey = node.verifyingPublicKey;\n\n const taprootKey = computeTaprootKeyNoScript(nodePublicKey.slice(1));\n const adaptorSignatureBytes = hexToBytes(leaf.adaptorSignedSignature);\n applyAdaptorToSignature(\n taprootKey.slice(1),\n sighash,\n adaptorSignatureBytes,\n adaptorPrivateKey,\n );\n }\n\n await this.transferService.sendTransferTweakKey(\n transfer,\n leafKeyTweaks,\n signatureMap,\n );\n\n const completeResponse = await this.sspClient?.completeLeaveSwap({\n adaptorSecretKey: bytesToHex(adaptorPrivateKey),\n userOutboundTransferExternalId: transfer.id,\n leavesSwapRequestId: request.id,\n });\n\n if (!completeResponse) {\n throw new Error(\"Failed to complete leaves swap\");\n }\n\n await this.claimTransfers(TransferType.COUNTER_SWAP);\n\n return completeResponse;\n } catch (e) {\n await this.cancelAllSenderInitiatedTransfers();\n throw new Error(`Failed to request leaves swap: ${e}`);\n }\n }\n\n /**\n * Gets all transfers for the wallet.\n *\n * @param {number} [limit=20] - Maximum number of transfers to return\n * @param {number} [offset=0] - Offset for pagination\n * @returns {Promise<QueryTransfersResponse>} Response containing the list of transfers\n */\n public async getTransfers(\n limit: number = 20,\n offset: number = 0,\n ): Promise<{\n transfers: WalletTransfer[];\n offset: number;\n }> {\n const transfers = await this.transferService.queryAllTransfers(\n limit,\n offset,\n );\n const identityPublicKey = bytesToHex(\n await this.config.signer.getIdentityPublicKey(),\n );\n return {\n transfers: transfers.transfers.map((transfer) =>\n mapTransferToWalletTransfer(transfer, identityPublicKey),\n ),\n offset: transfers.offset,\n };\n }\n\n /**\n * Gets the held token info for the wallet.\n *\n * @deprecated The information is returned in getBalance\n */\n public async getTokenInfo(): Promise<TokenInfo[]> {\n console.warn(\"getTokenInfo is deprecated. Use getBalance instead.\");\n\n await this.syncTokenOutputs();\n\n const lrc20Client = await this.lrc20ConnectionManager.createLrc20Client();\n const { balance, tokenBalances } = await this.getBalance();\n\n const tokenInfo = await lrc20Client.getTokenPubkeyInfo({\n publicKeys: Array.from(tokenBalances.keys()).map(hexToBytes),\n });\n\n return tokenInfo.tokenPubkeyInfos.map((info) => ({\n tokenPublicKey: bytesToHex(info.announcement!.publicKey!.publicKey),\n tokenName: info.announcement!.name,\n tokenSymbol: info.announcement!.symbol,\n tokenDecimals: Number(bytesToNumberBE(info.announcement!.decimal)),\n maxSupply: bytesToNumberBE(info.announcement!.maxSupply),\n }));\n }\n\n /**\n * Gets the current balance of the wallet.\n * You can use the forceRefetch option to synchronize your wallet and claim any\n * pending incoming lightning payment, spark transfer, or bitcoin deposit before returning the balance.\n *\n * @returns {Promise<Object>} Object containing:\n * - balance: The wallet's current balance in satoshis\n * - tokenBalances: Map of token public keys to token balances and token info\n */\n public async getBalance(): Promise<{\n balance: bigint;\n tokenBalances: Map<string, { balance: bigint; tokenInfo: TokenInfo }>;\n }> {\n this.leaves = await this.getLeaves();\n await this.syncTokenOutputs();\n\n let tokenBalances: Map<string, { balance: bigint; tokenInfo: TokenInfo }>;\n\n if (this.tokenOutputs.size !== 0) {\n tokenBalances = await this.getTokenBalance();\n } else {\n tokenBalances = new Map<\n string,\n { balance: bigint; tokenInfo: TokenInfo }\n >();\n }\n\n return {\n balance: BigInt(this.getInternalBalance()),\n tokenBalances,\n };\n }\n\n private async getTokenBalance(): Promise<\n Map<string, { balance: bigint; tokenInfo: TokenInfo }>\n > {\n const lrc20Client = await this.lrc20ConnectionManager.createLrc20Client();\n\n // Get token info for all tokens\n const tokenInfo = await lrc20Client.getTokenPubkeyInfo({\n publicKeys: Array.from(this.tokenOutputs.keys()).map(hexToBytes),\n });\n\n const result = new Map<string, { balance: bigint; tokenInfo: TokenInfo }>();\n\n for (const info of tokenInfo.tokenPubkeyInfos) {\n const tokenPublicKey = bytesToHex(\n info.announcement!.publicKey!.publicKey,\n );\n const leaves = this.tokenOutputs.get(tokenPublicKey);\n\n result.set(tokenPublicKey, {\n balance: leaves ? calculateAvailableTokenAmount(leaves) : BigInt(0),\n tokenInfo: {\n tokenPublicKey,\n tokenName: info.announcement!.name,\n tokenSymbol: info.announcement!.symbol,\n tokenDecimals: Number(bytesToNumberBE(info.announcement!.decimal)),\n maxSupply: bytesToNumberBE(info.announcement!.maxSupply),\n },\n });\n }\n\n return result;\n }\n\n private getInternalBalance(): number {\n return this.leaves.reduce((acc, leaf) => acc + leaf.value, 0);\n }\n\n // ***** Deposit Flow *****\n\n /**\n * Generates a new deposit address for receiving bitcoin funds.\n * Note that this function returns a bitcoin address, not a spark address, and this address is single use.\n * Once you deposit funds to this address, it cannot be used again.\n * For Layer 1 Bitcoin deposits, Spark generates Pay to Taproot (P2TR) addresses.\n * These addresses start with \"bc1p\" and can be used to receive Bitcoin from any wallet.\n *\n * @returns {Promise<string>} A Bitcoin address for depositing funds\n */\n public async getSingleUseDepositAddress(): Promise<string> {\n return await this.generateDepositAddress();\n }\n\n /**\n * Generates a deposit address for receiving funds.\n *\n * @returns {Promise<string>} A deposit address\n * @private\n */\n private async generateDepositAddress(): Promise<string> {\n const leafId = uuidv7();\n const signingPubkey = await this.config.signer.generatePublicKey(\n sha256(leafId),\n );\n const address = await this.depositService!.generateDepositAddress({\n signingPubkey,\n leafId,\n });\n if (!address.depositAddress) {\n throw new RPCError(\"Failed to generate deposit address\", {\n method: \"generateDepositAddress\",\n params: { signingPubkey, leafId },\n });\n }\n return address.depositAddress.address;\n }\n\n /**\n * Finalizes a deposit to the wallet.\n *\n * @param {DepositParams} params - Parameters for finalizing the deposit\n * @returns {Promise<void>} The nodes created from the deposit\n * @private\n */\n private async finalizeDeposit({\n signingPubKey,\n verifyingKey,\n depositTx,\n vout,\n }: DepositParams) {\n if (!Number.isSafeInteger(vout)) {\n throw new ValidationError(\"vout must be less than 2^53\", {\n field: \"vout\",\n value: vout,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n const res = await this.depositService!.createTreeRoot({\n signingPubKey,\n verifyingKey,\n depositTx,\n vout,\n });\n\n const resultingNodes: TreeNode[] = [];\n for (const node of res.nodes) {\n if (node.status === \"AVAILABLE\") {\n const { nodes } = await this.transferService.extendTimelock(\n node,\n signingPubKey,\n );\n\n for (const n of nodes) {\n if (n.status === \"AVAILABLE\") {\n const transfer = await this.transferLeavesToSelf(\n [n],\n signingPubKey,\n );\n resultingNodes.push(...transfer);\n } else {\n resultingNodes.push(n);\n }\n }\n } else {\n resultingNodes.push(node);\n }\n }\n\n return resultingNodes;\n }\n\n /**\n * Gets all unused deposit addresses for the wallet.\n *\n * @returns {Promise<string[]>} The unused deposit addresses\n */\n public async getUnusedDepositAddresses(): Promise<string[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n return (\n await sparkClient.query_unused_deposit_addresses({\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n })\n ).depositAddresses.map((addr) => addr.depositAddress);\n }\n /**\n * Claims a deposit to the wallet.\n * Note that if you used advancedDeposit, you don't need to call this function.\n * @param {string} txid - The transaction ID of the deposit\n * @returns {Promise<WalletLeaf[] | undefined>} The nodes resulting from the deposit\n */\n public async claimDeposit(txid: string): Promise<WalletLeaf[]> {\n if (!txid) {\n throw new ValidationError(\"Transaction ID cannot be empty\", {\n field: \"txid\",\n });\n }\n\n let mutex = this.mutexes.get(txid);\n if (!mutex) {\n mutex = new Mutex();\n this.mutexes.set(txid, mutex);\n }\n\n const nodes = await mutex.runExclusive(async () => {\n const baseUrl = this.config.getElectrsUrl();\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n let txHex: string | undefined;\n\n if (this.config.getNetwork() === Network.LOCAL) {\n const localFaucet = BitcoinFaucet.getInstance();\n const response = await localFaucet.getRawTransaction(txid);\n txHex = response.hex;\n } else {\n if (this.config.getNetwork() === Network.REGTEST) {\n const auth = btoa(\n `${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`,\n );\n headers[\"Authorization\"] = `Basic ${auth}`;\n }\n\n const response = await fetch(`${baseUrl}/tx/${txid}/hex`, {\n headers,\n });\n\n txHex = await response.text();\n }\n\n if (!txHex) {\n throw new Error(\"Transaction not found\");\n }\n\n if (!/^[0-9A-Fa-f]+$/.test(txHex)) {\n throw new ValidationError(\"Invalid transaction hex\", {\n field: \"txHex\",\n value: txHex,\n });\n }\n const depositTx = getTxFromRawTxHex(txHex);\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const unusedDepositAddresses: Map<string, DepositAddressQueryResult> =\n new Map(\n (\n await sparkClient.query_unused_deposit_addresses({\n identityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n })\n ).depositAddresses.map((addr) => [addr.depositAddress, addr]),\n );\n\n let depositAddress: DepositAddressQueryResult | undefined;\n let vout = 0;\n for (let i = 0; i < depositTx.outputsLength; i++) {\n const output = depositTx.getOutput(i);\n if (!output) {\n continue;\n }\n const parsedScript = OutScript.decode(output.script!);\n const address = Address(getNetwork(this.config.getNetwork())).encode(\n parsedScript,\n );\n if (unusedDepositAddresses.has(address)) {\n vout = i;\n depositAddress = unusedDepositAddresses.get(address);\n break;\n }\n }\n if (!depositAddress) {\n throw new ValidationError(\"Deposit address has already been used\", {\n field: \"depositAddress\",\n value: depositAddress,\n });\n }\n\n let signingPubKey: Uint8Array;\n if (!depositAddress.leafId) {\n signingPubKey = depositAddress.userSigningPublicKey;\n } else {\n signingPubKey = await this.config.signer.generatePublicKey(\n sha256(depositAddress.leafId),\n );\n }\n\n const nodes = await this.finalizeDeposit({\n signingPubKey,\n verifyingKey: depositAddress.verifyingPublicKey,\n depositTx,\n vout,\n });\n\n return nodes;\n });\n\n this.mutexes.delete(txid);\n\n return nodes.map(mapTreeNodeToWalletLeaf);\n }\n\n /**\n * Non-trusty flow for depositing funds to the wallet.\n * Construct the tx spending from an L1 wallet to the Spark address.\n * After calling this function, you must sign and broadcast the tx.\n *\n * @param {string} txHex - The hex string of the transaction to deposit\n * @returns {Promise<TreeNode[] | undefined>} The nodes resulting from the deposit\n */\n public async advancedDeposit(txHex: string) {\n const depositTx = getTxFromRawTxHex(txHex);\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n const unusedDepositAddresses: Map<string, DepositAddressQueryResult> =\n new Map(\n (\n await sparkClient.query_unused_deposit_addresses({\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n })\n ).depositAddresses.map((addr) => [addr.depositAddress, addr]),\n );\n\n let vout = 0;\n const responses: TreeNode[] = [];\n for (let i = 0; i < depositTx.outputsLength; i++) {\n const output = depositTx.getOutput(i);\n if (!output) {\n continue;\n }\n const parsedScript = OutScript.decode(output.script!);\n const address = Address(getNetwork(this.config.getNetwork())).encode(\n parsedScript,\n );\n const unusedDepositAddress = unusedDepositAddresses.get(address);\n if (unusedDepositAddress) {\n vout = i;\n const response = await this.depositService!.createTreeRoot({\n signingPubKey: unusedDepositAddress.userSigningPublicKey,\n verifyingKey: unusedDepositAddress.verifyingPublicKey,\n depositTx,\n vout,\n });\n responses.push(...response.nodes);\n }\n }\n if (responses.length === 0) {\n throw new Error(\n `No unused deposit address found for tx: ${getTxId(depositTx)}`,\n );\n }\n\n return responses;\n }\n\n /**\n * Transfers deposit to self to claim ownership.\n *\n * @param {TreeNode[]} leaves - The leaves to transfer\n * @param {Uint8Array} signingPubKey - The signing public key\n * @returns {Promise<TreeNode[] | undefined>} The nodes resulting from the transfer\n * @private\n */\n private async transferLeavesToSelf(\n leaves: TreeNode[],\n signingPubKey: Uint8Array,\n ): Promise<TreeNode[]> {\n const leafKeyTweaks = await Promise.all(\n leaves.map(async (leaf) => ({\n leaf,\n signingPubKey,\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const transfer = await this.transferService.sendTransfer(\n leafKeyTweaks,\n await this.config.signer.getIdentityPublicKey(),\n );\n\n const resultNodes = await this.claimTransfer(transfer);\n\n const leavesToRemove = new Set(leaves.map((leaf) => leaf.id));\n this.leaves = [\n ...this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id)),\n ...resultNodes,\n ];\n\n return resultNodes;\n }\n // ***** Transfer Flow *****\n\n /**\n * Sends a transfer to another Spark user.\n *\n * @param {TransferParams} params - Parameters for the transfer\n * @param {string} params.receiverSparkAddress - The recipient's Spark address\n * @param {number} params.amountSats - Amount to send in satoshis\n * @returns {Promise<WalletTransfer>} The completed transfer details\n */\n public async transfer({\n amountSats,\n receiverSparkAddress,\n }: TransferParams): Promise<WalletTransfer> {\n if (!receiverSparkAddress) {\n throw new ValidationError(\"Receiver Spark address cannot be empty\", {\n field: \"receiverSparkAddress\",\n });\n }\n\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n if (amountSats <= 0) {\n throw new ValidationError(\"Amount must be greater than 0\", {\n field: \"amountSats\",\n value: amountSats,\n });\n }\n\n const receiverAddress = decodeSparkAddress(\n receiverSparkAddress,\n this.config.getNetworkType(),\n );\n\n const isSelfTransfer = equalBytes(\n await this.config.signer.getIdentityPublicKey(),\n hexToBytes(receiverAddress),\n );\n\n return await this.withLeaves(async () => {\n let leavesToSend = await this.selectLeaves(amountSats);\n\n await this.checkRefreshTimelockNodes(leavesToSend);\n leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);\n\n const leafKeyTweaks = await Promise.all(\n leavesToSend.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const transfer = await this.transferService.sendTransfer(\n leafKeyTweaks,\n hexToBytes(receiverAddress),\n );\n\n const leavesToRemove = new Set(leavesToSend.map((leaf) => leaf.id));\n this.leaves = this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id));\n\n // If this is a self-transfer, lets claim it immediately\n if (isSelfTransfer) {\n await this.claimTransfer(transfer);\n }\n\n return mapTransferToWalletTransfer(\n transfer,\n bytesToHex(await this.config.signer.getIdentityPublicKey()),\n );\n });\n }\n\n private async checkExtendTimeLockNodes(\n nodes?: TreeNode[],\n ): Promise<TreeNode[]> {\n const nodesToCheck = nodes ?? this.leaves;\n const nodesToExtend: TreeNode[] = [];\n const nodeIds: string[] = [];\n let resultNodes = [...nodesToCheck];\n\n for (const node of nodesToCheck) {\n const nodeTx = getTxFromRawTxBytes(node.nodeTx);\n const { needRefresh } = getNextTransactionSequence(\n nodeTx.getInput(0).sequence,\n );\n if (needRefresh) {\n nodesToExtend.push(node);\n nodeIds.push(node.id);\n }\n }\n\n resultNodes = resultNodes.filter((node) => !nodesToExtend.includes(node));\n\n for (const node of nodesToExtend) {\n const signingPubKey = await this.config.signer.generatePublicKey(\n sha256(node.id),\n );\n const { nodes } = await this.transferService.extendTimelock(\n node,\n signingPubKey,\n );\n this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);\n const newNodes = await this.transferLeavesToSelf(nodes, signingPubKey);\n resultNodes.push(...newNodes);\n }\n\n return resultNodes;\n }\n\n /**\n * Internal method to refresh timelock nodes.\n *\n * @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.\n * @returns {Promise<void>}\n * @private\n */\n private async checkRefreshTimelockNodes(nodes?: TreeNode[]) {\n const nodesToRefresh: TreeNode[] = [];\n const nodeIds: string[] = [];\n\n for (const node of nodes ?? this.leaves) {\n const refundTx = getTxFromRawTxBytes(node.refundTx);\n const { needRefresh } = getNextTransactionSequence(\n refundTx.getInput(0).sequence,\n true,\n );\n if (needRefresh) {\n nodesToRefresh.push(node);\n nodeIds.push(node.id);\n }\n }\n\n if (nodesToRefresh.length === 0) {\n return;\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const nodesResp = await sparkClient.query_nodes({\n source: {\n $case: \"nodeIds\",\n nodeIds: {\n nodeIds,\n },\n },\n includeParents: true,\n });\n\n const nodesMap = new Map<string, TreeNode>();\n for (const node of Object.values(nodesResp.nodes)) {\n nodesMap.set(node.id, node);\n }\n\n for (const node of nodesToRefresh) {\n if (!node.parentNodeId) {\n throw new Error(`node ${node.id} has no parent`);\n }\n\n const parentNode = nodesMap.get(node.parentNodeId);\n if (!parentNode) {\n throw new Error(`parent node ${node.parentNodeId} not found`);\n }\n\n const { nodes } = await this.transferService.refreshTimelockNodes(\n [node],\n parentNode,\n await this.config.signer.generatePublicKey(sha256(node.id)),\n );\n\n if (nodes.length !== 1) {\n throw new Error(`expected 1 node, got ${nodes.length}`);\n }\n\n const newNode = nodes[0];\n if (!newNode) {\n throw new Error(\"Failed to refresh timelock node\");\n }\n\n this.leaves = this.leaves.filter((leaf) => leaf.id !== node.id);\n this.leaves.push(newNode);\n }\n }\n\n /**\n * Claims a specific transfer.\n *\n * @param {Transfer} transfer - The transfer to claim\n * @returns {Promise<Object>} The claim result\n */\n private async claimTransfer(\n transfer: Transfer,\n emit: boolean = false,\n retryCount: number = 0,\n ) {\n const MAX_RETRIES = 5;\n const BASE_DELAY_MS = 1000;\n const MAX_DELAY_MS = 10000;\n\n if (retryCount > 0) {\n const delayMs = Math.min(\n BASE_DELAY_MS * Math.pow(2, retryCount - 1),\n MAX_DELAY_MS,\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n try {\n let result = await this.claimTransferMutex.runExclusive(async () => {\n const leafPubKeyMap =\n await this.transferService.verifyPendingTransfer(transfer);\n\n let leavesToClaim: LeafKeyTweak[] = [];\n\n for (const leaf of transfer.leaves) {\n if (leaf.leaf) {\n const leafPubKey = leafPubKeyMap.get(leaf.leaf.id);\n if (leafPubKey) {\n leavesToClaim.push({\n leaf: leaf.leaf,\n signingPubKey: leafPubKey,\n newSigningPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.leaf.id),\n ),\n });\n }\n }\n }\n\n const response = await this.transferService.claimTransfer(\n transfer,\n leavesToClaim,\n );\n\n this.leaves.push(...response.nodes);\n\n if (emit) {\n this.emit(\n \"transfer:claimed\",\n transfer.id,\n (await this.getBalance()).balance,\n );\n }\n\n return response.nodes;\n });\n\n await this.checkRefreshTimelockNodes(result);\n result = await this.checkExtendTimeLockNodes(result);\n\n return result;\n } catch (error) {\n if (retryCount < MAX_RETRIES) {\n console.error(\"Failed to claim transfer, retrying...\", error);\n this.claimTransfer(transfer, emit, retryCount + 1);\n return [];\n } else if (retryCount > 0) {\n console.error(\"Failed to claim transfer\", error);\n return [];\n } else {\n throw new NetworkError(\n \"Failed to claim transfer\",\n {\n operation: \"claimTransfer\",\n errors: error instanceof Error ? error.message : String(error),\n },\n error instanceof Error ? error : undefined,\n );\n }\n }\n }\n\n /**\n * Claims all pending transfers.\n *\n * @returns {Promise<string[]>} Array of successfully claimed transfer IDs\n * @private\n */\n private async claimTransfers(\n type?: TransferType,\n emit?: boolean,\n ): Promise<string[]> {\n const transfers = await this.transferService.queryPendingTransfers();\n const promises: Promise<string | null>[] = [];\n for (const transfer of transfers.transfers) {\n if (type && transfer.type !== type) {\n continue;\n }\n\n if (\n transfer.status !== TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED &&\n transfer.status !==\n TransferStatus.TRANSFER_STATUS_RECEIVER_KEY_TWEAKED &&\n transfer.status !==\n TransferStatus.TRANSFER_STATUSR_RECEIVER_REFUND_SIGNED\n ) {\n continue;\n }\n promises.push(\n this.claimTransfer(transfer, emit)\n .then(() => transfer.id)\n .catch((error) => {\n console.warn(`Failed to claim transfer ${transfer.id}:`, error);\n return null;\n }),\n );\n }\n const results = await Promise.allSettled(promises);\n return results\n .filter(\n (result) => result.status === \"fulfilled\" && result.value !== null,\n )\n .map((result) => (result as PromiseFulfilledResult<string>).value);\n }\n\n /**\n * Cancels all sender-initiated transfers.\n *\n * @returns {Promise<void>}\n * @private\n */\n private async cancelAllSenderInitiatedTransfers() {\n for (const operator of Object.values(this.config.getSigningOperators())) {\n const transfers =\n await this.transferService.queryPendingTransfersBySender(\n operator.address,\n );\n\n for (const transfer of transfers.transfers) {\n if (\n transfer.status === TransferStatus.TRANSFER_STATUS_SENDER_INITIATED\n ) {\n await this.transferService.cancelTransfer(transfer, operator.address);\n }\n }\n }\n }\n\n // ***** Lightning Flow *****\n\n /**\n * Creates a Lightning invoice for receiving payments.\n *\n * @param {Object} params - Parameters for the lightning invoice\n * @param {number} params.amountSats - Amount in satoshis\n * @param {string} params.memo - Description for the invoice\n * @param {number} [params.expirySeconds] - Optional expiry time in seconds\n * @returns {Promise<LightningReceiveRequest>} BOLT11 encoded invoice\n */\n public async createLightningInvoice({\n amountSats,\n memo,\n expirySeconds = 60 * 60 * 24 * 30,\n }: CreateLightningInvoiceParams): Promise<LightningReceiveRequest> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n if (isNaN(amountSats) || amountSats < 0) {\n throw new ValidationError(\"Invalid amount\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"non-negative number\",\n });\n }\n\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n if (!Number.isSafeInteger(expirySeconds)) {\n throw new ValidationError(\"Expiration time must be less than 2^53\", {\n field: \"expirySeconds\",\n value: expirySeconds,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n if (expirySeconds < 0) {\n throw new ValidationError(\"Invalid expiration time\", {\n field: \"expirySeconds\",\n value: expirySeconds,\n expected: \"Non-negative expiration time\",\n });\n }\n\n if (memo && memo.length > 639) {\n throw new ValidationError(\"Invalid memo size\", {\n field: \"memo\",\n value: memo,\n expected: \"Memo size within limits\",\n });\n }\n\n const requestLightningInvoice = async (\n amountSats: number,\n paymentHash: Uint8Array,\n memo?: string,\n ) => {\n const network = this.config.getNetwork();\n let bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.REGTEST;\n if (network === Network.MAINNET) {\n bitcoinNetwork = BitcoinNetwork.MAINNET;\n } else if (network === Network.REGTEST) {\n bitcoinNetwork = BitcoinNetwork.REGTEST;\n }\n\n const invoice = await this.sspClient!.requestLightningReceive({\n amountSats,\n network: bitcoinNetwork,\n paymentHash: bytesToHex(paymentHash),\n expirySecs: expirySeconds,\n memo,\n });\n\n return invoice;\n };\n\n const invoice = await this.lightningService!.createLightningInvoice({\n amountSats,\n memo,\n invoiceCreator: requestLightningInvoice,\n });\n\n return invoice;\n }\n\n /**\n * Pays a Lightning invoice.\n *\n * @param {Object} params - Parameters for paying the invoice\n * @param {string} params.invoice - The BOLT11-encoded Lightning invoice to pay\n * @returns {Promise<LightningSendRequest>} The Lightning payment request details\n */\n public async payLightningInvoice({\n invoice,\n maxFeeSats,\n }: PayLightningInvoiceParams) {\n return await this.withLeaves(async () => {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n const decodedInvoice = decode(invoice);\n const amountSats =\n Number(\n decodedInvoice.sections.find((section) => section.name === \"amount\")\n ?.value,\n ) / 1000;\n\n if (isNaN(amountSats) || amountSats <= 0) {\n throw new ValidationError(\"Invalid amount\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"positive number\",\n });\n }\n\n const paymentHash = decodedInvoice.sections.find(\n (section) => section.name === \"payment_hash\",\n )?.value;\n\n if (!paymentHash) {\n throw new ValidationError(\"No payment hash found in invoice\", {\n field: \"paymentHash\",\n });\n }\n\n const feeEstimate = await this.getLightningSendFeeEstimate({\n encodedInvoice: invoice,\n });\n\n if (maxFeeSats < feeEstimate) {\n throw new ValidationError(\"maxFeeSats does not cover fee estimate\", {\n field: \"maxFeeSats\",\n value: maxFeeSats,\n expected: `${feeEstimate} sats`,\n });\n }\n\n const totalAmount = amountSats + feeEstimate;\n\n const internalBalance = this.getInternalBalance();\n if (totalAmount > internalBalance) {\n throw new ValidationError(\"Insufficient balance\", {\n field: \"balance\",\n value: internalBalance,\n expected: `${totalAmount} sats`,\n });\n }\n\n let leaves = await this.selectLeaves(totalAmount);\n\n await this.checkRefreshTimelockNodes(leaves);\n leaves = await this.checkExtendTimeLockNodes(leaves);\n\n const leavesToSend = await Promise.all(\n leaves.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const swapResponse = await this.lightningService.swapNodesForPreimage({\n leaves: leavesToSend,\n receiverIdentityPubkey: hexToBytes(\n this.config.getSspIdentityPublicKey(),\n ),\n paymentHash: hexToBytes(paymentHash),\n isInboundPayment: false,\n invoiceString: invoice,\n feeSats: feeEstimate,\n });\n\n if (!swapResponse.transfer) {\n throw new Error(\"Failed to swap nodes for preimage\");\n }\n\n const transfer = await this.transferService.sendTransferTweakKey(\n swapResponse.transfer,\n leavesToSend,\n new Map(),\n );\n\n const sspResponse = await this.sspClient.requestLightningSend({\n encodedInvoice: invoice,\n idempotencyKey: paymentHash,\n });\n\n if (!sspResponse) {\n throw new Error(\"Failed to contact SSP\");\n }\n // test\n const leavesToRemove = new Set(leavesToSend.map((leaf) => leaf.leaf.id));\n this.leaves = this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id));\n\n return sspResponse;\n });\n }\n\n /**\n * Gets fee estimate for sending Lightning payments.\n *\n * @param {LightningSendFeeEstimateInput} params - Input parameters for fee estimation\n * @returns {Promise<number>} Fee estimate for sending Lightning payments\n */\n public async getLightningSendFeeEstimate({\n encodedInvoice,\n }: LightningSendFeeEstimateInput): Promise<number> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n const feeEstimate =\n await this.sspClient.getLightningSendFeeEstimate(encodedInvoice);\n\n if (!feeEstimate) {\n throw new Error(\"Failed to get lightning send fee estimate\");\n }\n const satsFeeEstimate = mapCurrencyAmount(feeEstimate.feeEstimate);\n return Math.ceil(satsFeeEstimate.sats);\n }\n\n // ***** Tree Creation Flow *****\n\n /**\n * Generates a deposit address for a tree.\n *\n * @param {number} vout - The vout index\n * @param {Uint8Array} parentSigningPubKey - The parent signing public key\n * @param {Transaction} [parentTx] - Optional parent transaction\n * @param {TreeNode} [parentNode] - Optional parent node\n * @returns {Promise<Object>} Deposit address information\n * @private\n */\n private async generateDepositAddressForTree(\n vout: number,\n parentSigningPubKey: Uint8Array,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ) {\n return await this.treeCreationService!.generateDepositAddressForTree(\n vout,\n parentSigningPubKey,\n parentTx,\n parentNode,\n );\n }\n\n /**\n * Creates a tree structure.\n *\n * @param {number} vout - The vout index\n * @param {DepositAddressTree} root - The root of the tree\n * @param {boolean} createLeaves - Whether to create leaves\n * @param {Transaction} [parentTx] - Optional parent transaction\n * @param {TreeNode} [parentNode] - Optional parent node\n * @returns {Promise<Object>} The created tree\n * @private\n */\n private async createTree(\n vout: number,\n root: DepositAddressTree,\n createLeaves: boolean,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ) {\n return await this.treeCreationService!.createTree(\n vout,\n root,\n createLeaves,\n parentTx,\n parentNode,\n );\n }\n\n // ***** Cooperative Exit Flow *****\n\n /**\n * Initiates a withdrawal to move funds from the Spark network to an on-chain Bitcoin address.\n *\n * @param {Object} params - Parameters for the withdrawal\n * @param {string} params.onchainAddress - The Bitcoin address where the funds should be sent\n * @param {number} [params.amountSats] - The amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds\n * @returns {Promise<CoopExitRequest | null | undefined>} The withdrawal request details, or null/undefined if the request cannot be completed\n */\n public async withdraw({\n onchainAddress,\n exitSpeed,\n amountSats,\n }: {\n onchainAddress: string;\n exitSpeed: ExitSpeed;\n amountSats?: number;\n }) {\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n return await this.withLeaves(async () => {\n return await this.coopExit(onchainAddress, exitSpeed, amountSats);\n });\n }\n\n /**\n * Internal method to perform a cooperative exit (withdrawal).\n *\n * @param {string} onchainAddress - The Bitcoin address where the funds should be sent\n * @param {number} [targetAmountSats] - The amount in satoshis to withdraw\n * @returns {Promise<Object | null | undefined>} The exit request details\n * @private\n */\n private async coopExit(\n onchainAddress: string,\n exitSpeed: ExitSpeed,\n targetAmountSats?: number,\n ) {\n if (!Number.isSafeInteger(targetAmountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"targetAmountSats\",\n value: targetAmountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n let leavesToSend: TreeNode[] = [];\n if (targetAmountSats) {\n leavesToSend = await this.selectLeaves(targetAmountSats);\n } else {\n leavesToSend = this.leaves.map((leaf) => ({\n ...leaf,\n }));\n }\n\n const feeEstimate = await this.sspClient?.getCoopExitFeeEstimate({\n leafExternalIds: leavesToSend.map((leaf) => leaf.id),\n withdrawalAddress: onchainAddress,\n });\n\n if (feeEstimate) {\n let fee: number | undefined;\n switch (exitSpeed) {\n case ExitSpeed.FAST:\n fee =\n (feeEstimate.speedFast?.l1BroadcastFee.originalValue || 0) +\n (feeEstimate.speedFast?.userFee.originalValue || 0);\n break;\n case ExitSpeed.MEDIUM:\n fee =\n (feeEstimate.speedMedium?.l1BroadcastFee.originalValue || 0) +\n (feeEstimate.speedMedium?.userFee.originalValue || 0);\n break;\n case ExitSpeed.SLOW:\n fee =\n (feeEstimate.speedSlow?.l1BroadcastFee.originalValue || 0) +\n (feeEstimate.speedSlow?.userFee.originalValue || 0);\n break;\n default:\n throw new ValidationError(\"Invalid exit speed\", {\n field: \"exitSpeed\",\n value: exitSpeed,\n expected: \"FAST, MEDIUM, or SLOW\",\n });\n }\n\n if (\n fee !== undefined &&\n fee > leavesToSend.reduce((acc, leaf) => acc + leaf.value, 0)\n ) {\n throw new ValidationError(\n \"The fee for the withdrawal is greater than the target amount\",\n {\n field: \"fee\",\n value: fee,\n expected: \"less than or equal to the target amount\",\n },\n );\n }\n }\n await this.checkRefreshTimelockNodes(leavesToSend);\n leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);\n\n const leafKeyTweaks = await Promise.all(\n leavesToSend.map(async (leaf) => ({\n leaf,\n signingPubKey: await this.config.signer.generatePublicKey(\n sha256(leaf.id),\n ),\n newSigningPubKey: await this.config.signer.generatePublicKey(),\n })),\n );\n\n const coopExitRequest = await this.sspClient?.requestCoopExit({\n leafExternalIds: leavesToSend.map((leaf) => leaf.id),\n withdrawalAddress: onchainAddress,\n idempotencyKey: uuidv7(),\n exitSpeed,\n });\n\n if (!coopExitRequest?.rawConnectorTransaction) {\n throw new Error(\"Failed to request coop exit\");\n }\n\n const connectorTx = getTxFromRawTxHex(\n coopExitRequest.rawConnectorTransaction,\n );\n\n const coopExitTxId = connectorTx.getInput(0).txid;\n const connectorTxId = getTxId(connectorTx);\n\n if (!coopExitTxId) {\n throw new Error(\"Failed to get coop exit tx id\");\n }\n\n const connectorOutputs: TransactionInput[] = [];\n for (let i = 0; i < connectorTx.outputsLength - 1; i++) {\n connectorOutputs.push({\n txid: hexToBytes(connectorTxId),\n index: i,\n });\n }\n\n const sspPubIdentityKey = hexToBytes(this.config.getSspIdentityPublicKey());\n const transfer = await this.coopExitService.getConnectorRefundSignatures({\n leaves: leafKeyTweaks,\n exitTxId: coopExitTxId,\n connectorOutputs,\n receiverPubKey: sspPubIdentityKey,\n });\n\n const completeResponse = await this.sspClient?.completeCoopExit({\n userOutboundTransferExternalId: transfer.transfer.id,\n coopExitRequestId: coopExitRequest.id,\n });\n\n return completeResponse;\n }\n\n /**\n * Gets fee estimate for cooperative exit (on-chain withdrawal).\n *\n * @param {Object} params - Input parameters for fee estimation\n * @param {number} params.amountSats - The amount in satoshis to withdraw\n * @param {string} params.withdrawalAddress - The Bitcoin address where the funds should be sent\n * @returns {Promise<CoopExitFeeEstimatesOutput | null>} Fee estimate for the withdrawal\n */\n public async getWithdrawalFeeEstimate({\n amountSats,\n withdrawalAddress,\n }: {\n amountSats: number;\n withdrawalAddress: string;\n }): Promise<CoopExitFeeEstimatesOutput | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n if (!Number.isSafeInteger(amountSats)) {\n throw new ValidationError(\"Sats amount must be less than 2^53\", {\n field: \"amountSats\",\n value: amountSats,\n expected: \"smaller or equal to \" + Number.MAX_SAFE_INTEGER,\n });\n }\n\n let leaves = await this.selectLeaves(amountSats);\n\n await this.checkRefreshTimelockNodes(leaves);\n leaves = await this.checkExtendTimeLockNodes(leaves);\n\n const feeEstimate = await this.sspClient.getCoopExitFeeEstimate({\n leafExternalIds: leaves.map((leaf) => leaf.id),\n withdrawalAddress,\n });\n\n return feeEstimate;\n }\n\n // ***** Token Flow *****\n\n /**\n * Synchronizes token outputs for the wallet.\n *\n * @returns {Promise<void>}\n * @private\n */\n protected async syncTokenOutputs() {\n this.tokenOutputs.clear();\n\n const unsortedTokenOutputs =\n await this.tokenTransactionService.fetchOwnedTokenOutputs(\n [await this.config.signer.getIdentityPublicKey()],\n [],\n );\n\n const filteredTokenOutputs = unsortedTokenOutputs.filter(\n (output) =>\n !this.pendingWithdrawnOutputIds.includes(output.output?.id || \"\"),\n );\n\n const fetchedOutputIds = new Set(\n unsortedTokenOutputs.map((output) => output.output?.id).filter(Boolean),\n );\n this.pendingWithdrawnOutputIds = this.pendingWithdrawnOutputIds.filter(\n (id) => fetchedOutputIds.has(id),\n );\n\n // Group leaves by token key\n const groupedOutputs = new Map<\n string,\n OutputWithPreviousTransactionData[]\n >();\n\n filteredTokenOutputs.forEach((output) => {\n const tokenKey = bytesToHex(output.output!.tokenPublicKey!);\n const index = output.previousTransactionVout!;\n\n if (!groupedOutputs.has(tokenKey)) {\n groupedOutputs.set(tokenKey, []);\n }\n\n groupedOutputs.get(tokenKey)!.push({\n ...output,\n previousTransactionVout: index,\n });\n });\n\n this.tokenOutputs = groupedOutputs;\n }\n\n /**\n * Transfers tokens to another user.\n *\n * @param {Object} params - Parameters for the token transfer\n * @param {string} params.tokenPublicKey - The public key of the token to transfer\n * @param {bigint} params.tokenAmount - The amount of tokens to transfer\n * @param {string} params.receiverSparkAddress - The recipient's public key\n * @param {OutputWithPreviousTransactionData[]} [params.selectedOutputs] - Optional specific leaves to use for the transfer\n * @returns {Promise<string>} The transaction ID of the token transfer\n */\n public async transferTokens({\n tokenPublicKey,\n tokenAmount,\n receiverSparkAddress,\n selectedOutputs,\n }: {\n tokenPublicKey: string;\n tokenAmount: bigint;\n receiverSparkAddress: string;\n selectedOutputs?: OutputWithPreviousTransactionData[];\n }): Promise<string> {\n await this.syncTokenOutputs();\n\n return this.tokenTransactionService.tokenTransfer(\n this.tokenOutputs,\n [\n {\n tokenPublicKey,\n tokenAmount,\n receiverSparkAddress,\n },\n ],\n selectedOutputs,\n );\n }\n\n /**\n * Transfers tokens with multiple outputs\n *\n * @param {Array} receiverOutputs - Array of transfer parameters\n * @param {string} receiverOutputs[].tokenPublicKey - The public key of the token to transfer\n * @param {bigint} receiverOutputs[].tokenAmount - The amount of tokens to transfer\n * @param {string} receiverOutputs[].receiverSparkAddress - The recipient's public key\n * @param {OutputWithPreviousTransactionData[]} [selectedOutputs] - Optional specific leaves to use for the transfer\n * @returns {Promise<string[]>} Array of transaction IDs for the token transfers\n */\n public async batchTransferTokens(\n receiverOutputs: {\n tokenPublicKey: string;\n tokenAmount: bigint;\n receiverSparkAddress: string;\n }[],\n selectedOutputs?: OutputWithPreviousTransactionData[],\n ): Promise<string> {\n if (receiverOutputs.length === 0) {\n throw new ValidationError(\"At least one receiver output is required\", {\n field: \"receiverOutputs\",\n value: receiverOutputs,\n expected: \"Non-empty array\",\n });\n }\n const firstTokenPublicKey = receiverOutputs[0]!.tokenPublicKey;\n const allSameToken = receiverOutputs.every(\n (output) => output.tokenPublicKey === firstTokenPublicKey,\n );\n if (!allSameToken) {\n throw new ValidationError(\n \"All receiver outputs must have the same token public key\",\n {\n field: \"receiverOutputs\",\n value: receiverOutputs,\n expected: \"All outputs must have the same token public key\",\n },\n );\n }\n\n await this.syncTokenOutputs();\n\n return this.tokenTransactionService.tokenTransfer(\n this.tokenOutputs,\n receiverOutputs,\n selectedOutputs,\n );\n }\n\n /**\n * Retrieves token transaction history for specified tokens owned by the wallet.\n * Can optionally filter by specific transaction hashes.\n *\n * @param tokenPublicKeys - Array of token public keys to query transactions for\n * @param tokenTransactionHashes - Optional array of specific transaction hashes to filter by\n * @returns Promise resolving to array of token transactions with their current status\n */\n public async queryTokenTransactions(\n tokenPublicKeys: string[],\n tokenTransactionHashes?: string[],\n ): Promise<TokenTransactionWithStatus[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let queryParams;\n if (tokenTransactionHashes?.length) {\n queryParams = {\n tokenPublicKeys: tokenPublicKeys?.map(hexToBytes)!,\n ownerPublicKeys: [hexToBytes(await this.getIdentityPublicKey())],\n tokenTransactionHashes: tokenTransactionHashes.map(hexToBytes),\n };\n } else {\n queryParams = {\n tokenPublicKeys: tokenPublicKeys?.map(hexToBytes)!,\n ownerPublicKeys: [hexToBytes(await this.getIdentityPublicKey())],\n };\n }\n\n const response = await sparkClient.query_token_transactions(queryParams);\n return response.tokenTransactionsWithStatus;\n }\n\n public async getTokenL1Address(): Promise<string> {\n return getP2WPKHAddressFromPublicKey(\n await this.config.signer.getIdentityPublicKey(),\n this.config.getNetwork(),\n );\n }\n\n /**\n * Signs a message with the identity key.\n *\n * @param {string} message - The message to sign\n * @param {boolean} [compact] - Whether to use compact encoding. If false, the message will be encoded as DER.\n * @returns {Promise<string>} The signed message\n */\n public async signMessageWithIdentityKey(\n message: string,\n compact?: boolean,\n ): Promise<string> {\n const hash = sha256(message);\n const signature = await this.config.signer.signMessageWithIdentityKey(\n hash,\n compact,\n );\n return bytesToHex(signature);\n }\n\n /**\n * Validates a message with the identity key.\n *\n * @param {string} message - The original message that was signed\n * @param {string | Uint8Array} signature - Signature to validate\n * @returns {Promise<boolean>} Whether the message is valid\n */\n public async validateMessageWithIdentityKey(\n message: string,\n signature: string | Uint8Array,\n ): Promise<boolean> {\n const hash = sha256(message);\n if (typeof signature === \"string\") {\n signature = hexToBytes(signature);\n }\n return this.config.signer.validateMessageWithIdentityKey(hash, signature);\n }\n\n /**\n * Get a Lightning receive request by ID.\n *\n * @param {string} id - The ID of the Lightning receive request\n * @returns {Promise<LightningReceiveRequest | null>} The Lightning receive request\n */\n public async getLightningReceiveRequest(\n id: string,\n ): Promise<LightningReceiveRequest | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n return await this.sspClient.getLightningReceiveRequest(id);\n }\n\n /**\n * Get a Lightning send request by ID.\n *\n * @param {string} id - The ID of the Lightning send request\n * @returns {Promise<LightningSendRequest | null>} The Lightning send request\n */\n public async getLightningSendRequest(\n id: string,\n ): Promise<LightningSendRequest | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n return await this.sspClient.getLightningSendRequest(id);\n }\n\n /**\n * Get a coop exit request by ID.\n *\n * @param {string} id - The ID of the coop exit request\n * @returns {Promise<CoopExitRequest | null>} The coop exit request\n */\n public async getCoopExitRequest(id: string): Promise<CoopExitRequest | null> {\n if (!this.sspClient) {\n throw new ConfigurationError(\"SSP client not initialized\", {\n configKey: \"sspClient\",\n });\n }\n\n return await this.sspClient.getCoopExitRequest(id);\n }\n\n private cleanup() {\n if (this.claimTransfersInterval) {\n clearInterval(this.claimTransfersInterval);\n this.claimTransfersInterval = null;\n }\n this.streamController?.abort();\n this.removeAllListeners();\n }\n\n public async cleanupConnections() {\n this.cleanup();\n await this.connectionManager.closeConnections();\n }\n\n // Add this new method to start periodic claiming\n private startPeriodicClaimTransfers() {\n // Clear any existing interval first\n if (this.claimTransfersInterval) {\n clearInterval(this.claimTransfersInterval);\n }\n\n // Set up new interval to claim transfers every 5 seconds\n // @ts-ignore\n this.claimTransfersInterval = setInterval(async () => {\n try {\n await this.claimTransfers(undefined, true);\n } catch (error) {\n console.error(\"Error in periodic transfer claiming:\", error);\n }\n }, 10000);\n }\n}\n","import {\n AuthProvider,\n bytesToHex,\n DefaultCrypto,\n NodeKeyCache,\n Query,\n Requester,\n} from \"@lightsparkdev/core\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { AuthenticationError, NetworkError } from \"../errors/index.js\";\nimport { SparkSigner } from \"../signer/signer.js\";\nimport { CompleteCoopExit } from \"./mutations/CompleteCoopExit.js\";\nimport { CompleteLeavesSwap } from \"./mutations/CompleteLeavesSwap.js\";\nimport { GetChallenge } from \"./mutations/GetChallenge.js\";\nimport { RequestCoopExit } from \"./mutations/RequestCoopExit.js\";\nimport { RequestLightningReceive } from \"./mutations/RequestLightningReceive.js\";\nimport { RequestLightningSend } from \"./mutations/RequestLightningSend.js\";\nimport { RequestSwapLeaves } from \"./mutations/RequestSwapLeaves.js\";\nimport { VerifyChallenge } from \"./mutations/VerifyChallenge.js\";\nimport { CoopExitFeeEstimatesOutputFromJson } from \"./objects/CoopExitFeeEstimatesOutput.js\";\nimport CoopExitRequest, {\n CoopExitRequestFromJson,\n} from \"./objects/CoopExitRequest.js\";\nimport { GetChallengeOutputFromJson } from \"./objects/GetChallengeOutput.js\";\nimport type {\n CompleteCoopExitInput,\n CompleteLeavesSwapInput,\n CoopExitFeeEstimatesInput,\n CoopExitFeeEstimatesOutput,\n GetChallengeOutput,\n LeavesSwapFeeEstimateOutput,\n LightningSendRequest,\n RequestCoopExitInput,\n RequestLeavesSwapInput,\n RequestLightningReceiveInput,\n RequestLightningSendInput,\n} from \"./objects/index.js\";\nimport { LeavesSwapFeeEstimateOutputFromJson } from \"./objects/LeavesSwapFeeEstimateOutput.js\";\nimport LeavesSwapRequest, {\n LeavesSwapRequestFromJson,\n} from \"./objects/LeavesSwapRequest.js\";\nimport LightningReceiveRequest, {\n LightningReceiveRequestFromJson,\n} from \"./objects/LightningReceiveRequest.js\";\nimport LightningSendFeeEstimateOutput, {\n LightningSendFeeEstimateOutputFromJson,\n} from \"./objects/LightningSendFeeEstimateOutput.js\";\nimport { LightningSendRequestFromJson } from \"./objects/LightningSendRequest.js\";\nimport VerifyChallengeOutput, {\n VerifyChallengeOutputFromJson,\n} from \"./objects/VerifyChallengeOutput.js\";\nimport { CoopExitFeeEstimate } from \"./queries/CoopExitFeeEstimate.js\";\nimport { LeavesSwapFeeEstimate } from \"./queries/LeavesSwapFeeEstimate.js\";\nimport { LightningSendFeeEstimate } from \"./queries/LightningSendFeeEstimate.js\";\nimport { UserRequest } from \"./queries/UserRequest.js\";\n\nexport interface SspClientOptions {\n baseUrl: string;\n identityPublicKey: string;\n schemaEndpoint?: string;\n}\n\nexport interface MayHaveSspClientOptions {\n readonly sspClientOptions?: SspClientOptions;\n}\n\nexport interface HasSspClientOptions {\n readonly sspClientOptions: SspClientOptions;\n}\n\nexport default class SspClient {\n private readonly requester: Requester;\n\n private readonly signer: SparkSigner;\n private readonly authProvider: SparkAuthProvider;\n\n constructor(\n config: HasSspClientOptions & {\n signer: SparkSigner;\n },\n ) {\n this.signer = config.signer;\n this.authProvider = new SparkAuthProvider();\n\n const fetchFunction =\n typeof window !== \"undefined\" ? window.fetch.bind(window) : fetch;\n const options = config.sspClientOptions;\n\n this.requester = new Requester(\n new NodeKeyCache(DefaultCrypto),\n options.schemaEndpoint || `graphql/spark/2025-03-19`,\n `spark-sdk/0.0.0`,\n this.authProvider,\n options.baseUrl,\n DefaultCrypto,\n undefined,\n fetchFunction,\n );\n }\n\n async executeRawQuery<T>(\n query: Query<T>,\n needsAuth: boolean = true,\n ): Promise<T | null> {\n if (needsAuth && !(await this.authProvider.isAuthorized())) {\n await this.authenticate();\n }\n\n try {\n return await this.requester.executeQuery(query);\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.toLowerCase().includes(\"unauthorized\")\n ) {\n try {\n await this.authenticate();\n return await this.requester.executeQuery(query);\n } catch (authError) {\n throw new AuthenticationError(\n \"Failed to authenticate after unauthorized response\",\n {\n endpoint: \"graphql\",\n reason: error.message,\n },\n authError as Error,\n );\n }\n }\n throw new NetworkError(\n \"Failed to execute GraphQL query\",\n {\n method: \"POST\",\n },\n error as Error,\n );\n }\n }\n\n async getSwapFeeEstimate(\n amountSats: number,\n ): Promise<LeavesSwapFeeEstimateOutput | null> {\n return await this.executeRawQuery({\n queryPayload: LeavesSwapFeeEstimate,\n variables: {\n total_amount_sats: amountSats,\n },\n constructObject: (response: { leaves_swap_fee_estimate: any }) => {\n return LeavesSwapFeeEstimateOutputFromJson(\n response.leaves_swap_fee_estimate,\n );\n },\n });\n }\n\n async getLightningSendFeeEstimate(\n encodedInvoice: string,\n ): Promise<LightningSendFeeEstimateOutput | null> {\n return await this.executeRawQuery({\n queryPayload: LightningSendFeeEstimate,\n variables: {\n encoded_invoice: encodedInvoice,\n },\n constructObject: (response: { lightning_send_fee_estimate: any }) => {\n return LightningSendFeeEstimateOutputFromJson(\n response.lightning_send_fee_estimate,\n );\n },\n });\n }\n\n async getCoopExitFeeEstimate({\n leafExternalIds,\n withdrawalAddress,\n }: CoopExitFeeEstimatesInput): Promise<CoopExitFeeEstimatesOutput | null> {\n return await this.executeRawQuery({\n queryPayload: CoopExitFeeEstimate,\n variables: {\n leaf_external_ids: leafExternalIds,\n withdrawal_address: withdrawalAddress,\n },\n constructObject: (response: { coop_exit_fee_estimates: any }) => {\n return CoopExitFeeEstimatesOutputFromJson(\n response.coop_exit_fee_estimates,\n );\n },\n });\n }\n\n // TODO: Might not need\n async getCurrentUser() {\n throw new Error(\"Not implemented\");\n }\n\n async completeCoopExit({\n userOutboundTransferExternalId,\n coopExitRequestId,\n }: CompleteCoopExitInput): Promise<CoopExitRequest | null> {\n return await this.executeRawQuery({\n queryPayload: CompleteCoopExit,\n variables: {\n user_outbound_transfer_external_id: userOutboundTransferExternalId,\n coop_exit_request_id: coopExitRequestId,\n },\n constructObject: (response: { complete_coop_exit: any }) => {\n return CoopExitRequestFromJson(response.complete_coop_exit.request);\n },\n });\n }\n\n async requestCoopExit({\n leafExternalIds,\n withdrawalAddress,\n idempotencyKey,\n exitSpeed,\n }: RequestCoopExitInput): Promise<CoopExitRequest | null> {\n return await this.executeRawQuery({\n queryPayload: RequestCoopExit,\n variables: {\n leaf_external_ids: leafExternalIds,\n withdrawal_address: withdrawalAddress,\n idempotency_key: idempotencyKey,\n exit_speed: exitSpeed,\n },\n constructObject: (response: { request_coop_exit: any }) => {\n return CoopExitRequestFromJson(response.request_coop_exit.request);\n },\n });\n }\n\n // TODO: Lets name this better\n async requestLightningReceive({\n amountSats,\n network,\n paymentHash,\n expirySecs,\n memo,\n }: RequestLightningReceiveInput): Promise<LightningReceiveRequest | null> {\n return await this.executeRawQuery({\n queryPayload: RequestLightningReceive,\n variables: {\n amount_sats: amountSats,\n network: network,\n payment_hash: paymentHash,\n expiry_secs: expirySecs,\n memo: memo,\n },\n constructObject: (response: { request_lightning_receive: any }) => {\n return LightningReceiveRequestFromJson(\n response.request_lightning_receive.request,\n );\n },\n });\n }\n\n async requestLightningSend({\n encodedInvoice,\n idempotencyKey,\n }: RequestLightningSendInput): Promise<LightningSendRequest | null> {\n return await this.executeRawQuery({\n queryPayload: RequestLightningSend,\n variables: {\n encoded_invoice: encodedInvoice,\n idempotency_key: idempotencyKey,\n },\n constructObject: (response: { request_lightning_send: any }) => {\n return LightningSendRequestFromJson(\n response.request_lightning_send.request,\n );\n },\n });\n }\n\n async requestLeaveSwap({\n adaptorPubkey,\n totalAmountSats,\n targetAmountSats,\n feeSats,\n userLeaves,\n idempotencyKey,\n }: RequestLeavesSwapInput): Promise<LeavesSwapRequest | null> {\n const query = {\n queryPayload: RequestSwapLeaves,\n variables: {\n adaptor_pubkey: adaptorPubkey,\n total_amount_sats: totalAmountSats,\n target_amount_sats: targetAmountSats,\n fee_sats: feeSats,\n user_leaves: userLeaves,\n idempotency_key: idempotencyKey,\n },\n constructObject: (response: { request_leaves_swap: any }) => {\n if (!response.request_leaves_swap) {\n return null;\n }\n\n return LeavesSwapRequestFromJson(response.request_leaves_swap.request);\n },\n };\n return await this.executeRawQuery(query);\n }\n\n async completeLeaveSwap({\n adaptorSecretKey,\n userOutboundTransferExternalId,\n leavesSwapRequestId,\n }: CompleteLeavesSwapInput): Promise<LeavesSwapRequest | null> {\n return await this.executeRawQuery({\n queryPayload: CompleteLeavesSwap,\n variables: {\n adaptor_secret_key: adaptorSecretKey,\n user_outbound_transfer_external_id: userOutboundTransferExternalId,\n leaves_swap_request_id: leavesSwapRequestId,\n },\n constructObject: (response: { complete_leaves_swap: any }) => {\n return LeavesSwapRequestFromJson(response.complete_leaves_swap.request);\n },\n });\n }\n\n async getLightningReceiveRequest(\n id: string,\n ): Promise<LightningReceiveRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return LightningReceiveRequestFromJson(response.user_request);\n },\n });\n }\n\n async getLightningSendRequest(\n id: string,\n ): Promise<LightningSendRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return LightningSendRequestFromJson(response.user_request);\n },\n });\n }\n\n async getLeaveSwapRequest(id: string): Promise<LeavesSwapRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return LeavesSwapRequestFromJson(response.user_request);\n },\n });\n }\n\n async getCoopExitRequest(id: string): Promise<CoopExitRequest | null> {\n return await this.executeRawQuery({\n queryPayload: UserRequest,\n variables: {\n request_id: id,\n },\n constructObject: (response: { user_request: any }) => {\n if (!response.user_request) {\n return null;\n }\n\n return CoopExitRequestFromJson(response.user_request);\n },\n });\n }\n\n async getChallenge(): Promise<GetChallengeOutput | null> {\n return await this.executeRawQuery(\n {\n queryPayload: GetChallenge,\n variables: {\n public_key: bytesToHex(await this.signer.getIdentityPublicKey()),\n },\n constructObject: (response: { get_challenge: any }) => {\n return GetChallengeOutputFromJson(response.get_challenge);\n },\n },\n false,\n );\n }\n\n async verifyChallenge(\n signature: string,\n protectedChallenge: string,\n ): Promise<VerifyChallengeOutput | null> {\n return await this.executeRawQuery(\n {\n queryPayload: VerifyChallenge,\n variables: {\n protected_challenge: protectedChallenge,\n signature: signature,\n identity_public_key: bytesToHex(\n await this.signer.getIdentityPublicKey(),\n ),\n },\n constructObject: (response: any) => {\n return VerifyChallengeOutputFromJson(response.verify_challenge);\n },\n },\n false,\n );\n }\n\n async authenticate() {\n this.authProvider.removeAuth();\n\n const challenge = await this.getChallenge();\n if (!challenge) {\n throw new Error(\"Failed to get challenge\");\n }\n\n const challengeBytes = Buffer.from(challenge.protectedChallenge, \"base64\");\n const signature = await this.signer.signMessageWithIdentityKey(\n sha256(challengeBytes),\n );\n\n const verifyChallenge = await this.verifyChallenge(\n Buffer.from(signature).toString(\"base64\"),\n challenge.protectedChallenge,\n );\n if (!verifyChallenge) {\n throw new Error(\"Failed to verify challenge\");\n }\n\n this.authProvider.setAuth(\n verifyChallenge.sessionToken,\n new Date(verifyChallenge.validUntil),\n );\n }\n}\n\nclass SparkAuthProvider implements AuthProvider {\n private sessionToken: string | undefined;\n private validUntil: Date | undefined;\n\n async addAuthHeaders(\n headers: Record<string, string>,\n ): Promise<Record<string, string>> {\n const _headers = {\n \"Content-Type\": \"application/json\",\n ...headers,\n };\n\n if (this.sessionToken) {\n _headers[\"Authorization\"] = `Bearer ${this.sessionToken}`;\n }\n\n return Promise.resolve(_headers);\n }\n\n async isAuthorized(): Promise<boolean> {\n return (\n !!this.sessionToken && !!this.validUntil && this.validUntil > new Date()\n );\n }\n\n async addWsConnectionParams(\n params: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n const _params = {\n ...params,\n };\n\n if (this.sessionToken) {\n _params[\"Authorization\"] = `Bearer ${this.sessionToken}`;\n }\n\n return Promise.resolve(_params);\n }\n\n setAuth(sessionToken: string, validUntil: Date) {\n this.sessionToken = sessionToken;\n this.validUntil = validUntil;\n }\n\n removeAuth() {\n this.sessionToken = undefined;\n this.validUntil = undefined;\n }\n}\n","import { FRAGMENT as CompleteCoopExitOutputFragment } from \"../objects/CoopExitRequest.js\";\n\nexport const CompleteCoopExit = `\n mutation CompleteCoopExit(\n $user_outbound_transfer_external_id: UUID!\n $coop_exit_request_id: ID!\n ) {\n complete_coop_exit(input: {\n user_outbound_transfer_external_id: $user_outbound_transfer_external_id\n coop_exit_request_id: $coop_exit_request_id\n }) {\n request {\n ...CoopExitRequestFragment\n }\n }\n }\n \n ${CompleteCoopExitOutputFragment}\n`;\n","import { FRAGMENT as LeavesSwapRequestFragment } from \"../objects/LeavesSwapRequest.js\";\n\nexport const CompleteLeavesSwap = `\n mutation CompleteLeavesSwap(\n $adaptor_secret_key: String!\n $user_outbound_transfer_external_id: UUID!\n $leaves_swap_request_id: ID!\n ) {\n complete_leaves_swap(input: { adaptor_secret_key: $adaptor_secret_key, user_outbound_transfer_external_id: $user_outbound_transfer_external_id, leaves_swap_request_id: $leaves_swap_request_id }) {\n request {\n ...LeavesSwapRequestFragment\n }\n }\n }\n\n ${LeavesSwapRequestFragment}\n`;\n","import { FRAGMENT as GetChallengeOutputFragment } from \"../objects/GetChallengeOutput.js\";\n\nexport const GetChallenge = `\n mutation GetChallenge(\n $public_key: PublicKey!\n ) {\n get_challenge(input: {\n public_key: $public_key\n }) {\n ...GetChallengeOutputFragment\n }\n }\n \n ${GetChallengeOutputFragment}\n`;\n","import { FRAGMENT as RequestCoopExitOutputFragment } from \"../objects/CoopExitRequest.js\";\n\nexport const RequestCoopExit = `\n mutation RequestCoopExit(\n $leaf_external_ids: [UUID!]!\n $withdrawal_address: String!\n $idempotency_key: String!\n $exit_speed: ExitSpeed!\n ) {\n request_coop_exit(\n input: {\n leaf_external_ids: $leaf_external_ids\n withdrawal_address: $withdrawal_address\n idempotency_key: $idempotency_key\n exit_speed: $exit_speed\n }\n ) {\n request {\n ...CoopExitRequestFragment\n }\n }\n }\n ${RequestCoopExitOutputFragment}\n`;\n","import { FRAGMENT as RequestLightningReceiveOutputFragment } from \"../objects/LightningReceiveRequest.js\";\n\nexport const RequestLightningReceive = `\n mutation RequestLightningReceive(\n $network: BitcoinNetwork!\n $amount_sats: Long!\n $payment_hash: Hash32!\n $expiry_secs: Int\n $memo: String\n ) {\n request_lightning_receive(\n input: {\n network: $network\n amount_sats: $amount_sats\n payment_hash: $payment_hash\n expiry_secs: $expiry_secs\n memo: $memo\n }\n ) {\n request {\n ...LightningReceiveRequestFragment\n }\n }\n }\n ${RequestLightningReceiveOutputFragment}\n`;\n","import { FRAGMENT as RequestLightningSendOutputFragment } from \"../objects/LightningSendRequest.js\";\nexport const RequestLightningSend = `\n mutation RequestLightningSend(\n $encoded_invoice: String!\n $idempotency_key: String!\n ) {\n request_lightning_send(input: {\n encoded_invoice: $encoded_invoice\n idempotency_key: $idempotency_key\n }) {\n request {\n ...LightningSendRequestFragment\n }\n }\n }\n ${RequestLightningSendOutputFragment}\n`;\n","import { FRAGMENT as LeavesSwapRequestFragment } from \"../objects/LeavesSwapRequest.js\";\n\nexport const RequestSwapLeaves = `\n mutation RequestSwapLeaves(\n $adaptor_pubkey: PublicKey!\n $total_amount_sats: Long!\n $target_amount_sats: Long!\n $fee_sats: Long!\n $user_leaves: [UserLeafInput!]!\n $idempotency_key: String!\n ) {\n request_leaves_swap(input: {\n adaptor_pubkey: $adaptor_pubkey\n total_amount_sats: $total_amount_sats\n target_amount_sats: $target_amount_sats\n fee_sats: $fee_sats\n user_leaves: $user_leaves\n idempotency_key: $idempotency_key\n }) {\n request {\n ...LeavesSwapRequestFragment\n }\n }\n }\n ${LeavesSwapRequestFragment}\n`;\n","import { FRAGMENT as VerifyChallengeOutputFragment } from \"../objects/VerifyChallengeOutput.js\";\n\nexport const VerifyChallenge = `\n mutation VerifyChallenge(\n $protected_challenge: String!\n $signature: String!\n $identity_public_key: PublicKey!\n $provider: Provider\n ) {\n verify_challenge(input: {\n protected_challenge: $protected_challenge\n signature: $signature\n identity_public_key: $identity_public_key\n provider: $provider\n }) {\n ...VerifyChallengeOutputFragment\n }\n }\n \n ${VerifyChallengeOutputFragment}\n`;\n","import { FRAGMENT as CoopExitFeeEstimatesOutputFragment } from \"../objects/CoopExitFeeEstimatesOutput.js\";\n\nexport const CoopExitFeeEstimate = `\n query CoopExitFeeEstimate(\n $leaf_external_ids: [UUID!]!\n $withdrawal_address: String!\n ) {\n coop_exit_fee_estimates(\n input: {\n leaf_external_ids: $leaf_external_ids\n withdrawal_address: $withdrawal_address\n }\n ) {\n ...CoopExitFeeEstimatesOutputFragment\n }\n }\n ${CoopExitFeeEstimatesOutputFragment}\n`;\n","import { FRAGMENT as LeavesSwapFeeEstimateOutputFragment } from \"../objects/LeavesSwapFeeEstimateOutput.js\";\n\nexport const LeavesSwapFeeEstimate = `\n query LeavesSwapFeeEstimate(\n $total_amount_sats: Int!\n ) {\n leaves_swap_fee_estimate(\n input: {\n total_amount_sats: $total_amount_sats\n }\n ) {\n ...LeavesSwapFeeEstimateOutputFragment\n }\n }\n ${LeavesSwapFeeEstimateOutputFragment}\n`;\n","import { FRAGMENT as LightningSendFeeEstimateOutputFragment } from \"../objects/LightningSendFeeEstimateOutput.js\";\n\nexport const LightningSendFeeEstimate = `\n query LightningSendFeeEstimate(\n $encoded_invoice: String!\n ) {\n lightning_send_fee_estimate(\n input: {\n encoded_invoice: $encoded_invoice\n }\n ) {\n ...LightningSendFeeEstimateOutputFragment\n }\n }\n ${LightningSendFeeEstimateOutputFragment}\n`;\n","import { FRAGMENT as UserRequestFragment } from \"../objects/UserRequest.js\";\n\nexport const UserRequest = `\n query UserRequest($request_id: ID!) {\n user_request(request_id: $request_id) {\n ...UserRequestFragment\n }\n }\n ${UserRequestFragment}\n`;\n","import { Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { uuidv7 } from \"uuidv7\";\nimport { NetworkError, ValidationError } from \"../errors/types.js\";\nimport {\n CooperativeExitResponse,\n LeafRefundTxSigningJob,\n Transfer,\n} from \"../proto/spark.js\";\nimport {\n getP2TRScriptFromPublicKey,\n getTxFromRawTxBytes,\n} from \"../utils/bitcoin.js\";\nimport { getCrypto } from \"../utils/crypto.js\";\nimport { Network } from \"../utils/network.js\";\nimport { getNextTransactionSequence } from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport {\n BaseTransferService,\n LeafKeyTweak,\n LeafRefundSigningData,\n} from \"./transfer.js\";\n\nconst crypto = getCrypto();\n\nexport type GetConnectorRefundSignaturesParams = {\n leaves: LeafKeyTweak[];\n exitTxId: Uint8Array;\n connectorOutputs: TransactionInput[];\n receiverPubKey: Uint8Array;\n};\n\nexport class CoopExitService extends BaseTransferService {\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n super(config, connectionManager);\n }\n\n async getConnectorRefundSignatures({\n leaves,\n exitTxId,\n connectorOutputs,\n receiverPubKey,\n }: GetConnectorRefundSignaturesParams): Promise<{\n transfer: Transfer;\n signaturesMap: Map<string, Uint8Array>;\n }> {\n const { transfer, signaturesMap } = await this.signCoopExitRefunds(\n leaves,\n exitTxId,\n connectorOutputs,\n receiverPubKey,\n );\n const transferTweak = await this.sendTransferTweakKey(\n transfer,\n leaves,\n signaturesMap,\n );\n\n return { transfer: transferTweak, signaturesMap };\n }\n\n private createConnectorRefundTransaction(\n sequence: number,\n nodeOutPoint: TransactionInput,\n connectorOutput: TransactionInput,\n amountSats: bigint,\n receiverPubKey: Uint8Array,\n ): Transaction {\n const refundTx = new Transaction();\n if (!nodeOutPoint.txid || nodeOutPoint.index === undefined) {\n throw new ValidationError(\"Invalid node outpoint\", {\n field: \"nodeOutPoint\",\n value: { txid: nodeOutPoint.txid, index: nodeOutPoint.index },\n expected: \"Both txid and index must be defined\",\n });\n }\n refundTx.addInput({\n txid: nodeOutPoint.txid,\n index: nodeOutPoint.index,\n sequence,\n });\n\n refundTx.addInput(connectorOutput);\n const receiverScript = getP2TRScriptFromPublicKey(\n receiverPubKey,\n this.config.getNetwork(),\n );\n\n refundTx.addOutput({\n script: receiverScript,\n amount: amountSats,\n });\n\n return refundTx;\n }\n private async signCoopExitRefunds(\n leaves: LeafKeyTweak[],\n exitTxId: Uint8Array,\n connectorOutputs: TransactionInput[],\n receiverPubKey: Uint8Array,\n ): Promise<{ transfer: Transfer; signaturesMap: Map<string, Uint8Array> }> {\n if (leaves.length !== connectorOutputs.length) {\n throw new ValidationError(\n \"Mismatch between leaves and connector outputs\",\n {\n field: \"leaves/connectorOutputs\",\n value: {\n leavesCount: leaves.length,\n outputsCount: connectorOutputs.length,\n },\n expected: \"Equal length\",\n },\n );\n }\n\n const signingJobs: LeafRefundTxSigningJob[] = [];\n const leafDataMap: Map<string, LeafRefundSigningData> = new Map();\n\n for (let i = 0; i < leaves.length; i++) {\n const leaf = leaves[i];\n if (!leaf) {\n throw new ValidationError(\"Missing leaf\", {\n field: \"leaf\",\n value: leaf,\n expected: \"Valid leaf object\",\n });\n }\n const connectorOutput = connectorOutputs[i];\n if (!connectorOutput) {\n throw new ValidationError(\"Missing connector output\", {\n field: \"connectorOutput\",\n value: connectorOutput,\n expected: \"Valid connector output\",\n });\n }\n const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n\n const { nextSequence } = getNextTransactionSequence(\n currentRefundTx.getInput(0).sequence,\n );\n\n const refundTx = this.createConnectorRefundTransaction(\n nextSequence,\n currentRefundTx.getInput(0),\n connectorOutput,\n BigInt(leaf.leaf.value),\n receiverPubKey,\n );\n\n const signingNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const signingJob: LeafRefundTxSigningJob = {\n leafId: leaf.leaf.id,\n refundTxSigningJob: {\n signingPublicKey: leaf.signingPubKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: signingNonceCommitment,\n },\n };\n\n signingJobs.push(signingJob);\n const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n leafDataMap.set(leaf.leaf.id, {\n signingPubKey: leaf.signingPubKey,\n refundTx,\n signingNonceCommitment,\n tx,\n vout: leaf.leaf.vout,\n receivingPubkey: receiverPubKey,\n });\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: CooperativeExitResponse;\n try {\n response = await sparkClient.cooperative_exit({\n transfer: {\n transferId: uuidv7(),\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverPubKey,\n expiryTime:\n this.config.getNetwork() == Network.MAINNET\n ? new Date(Date.now() + 2 * 24 * 60 * 60 * 1000 + 5 * 60 * 1000)\n : new Date(Date.now() + 5 * 60 * 1000), // 48 hours 5 min for mainnet, 5 min otherwise\n },\n exitId: uuidv7(),\n exitTxid: exitTxId,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to initiate cooperative exit\",\n {\n operation: \"cooperative_exit\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n if (!response.transfer) {\n throw new NetworkError(\"Failed to initiate cooperative exit\", {\n operation: \"cooperative_exit\",\n errors: \"No transfer in response\",\n });\n }\n\n const signatures = await this.signRefunds(\n leafDataMap,\n response.signingResults,\n );\n\n const signaturesMap: Map<string, Uint8Array> = new Map();\n for (const signature of signatures) {\n signaturesMap.set(signature.nodeId, signature.refundTxSignature);\n }\n\n return { transfer: response.transfer, signaturesMap };\n }\n}\n","import {\n bytesToHex,\n equalBytes,\n hexToBytes,\n numberToBytesBE,\n} from \"@noble/curves/abstract/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport * as ecies from \"eciesjs\";\nimport { uuidv7 } from \"uuidv7\";\nimport {\n NetworkError,\n SparkSDKError,\n ValidationError,\n} from \"../errors/index.js\";\nimport { SignatureIntent } from \"../proto/common.js\";\nimport {\n ClaimLeafKeyTweak,\n ClaimTransferSignRefundsResponse,\n CounterLeafSwapResponse,\n FinalizeTransferResponse,\n LeafRefundTxSigningJob,\n LeafRefundTxSigningResult,\n NodeSignatures,\n QueryTransfersResponse,\n SecretProof,\n SendLeafKeyTweak,\n SigningJob,\n Transfer,\n TransferStatus,\n TransferType,\n TreeNode,\n} from \"../proto/spark.js\";\nimport { SigningCommitment } from \"../signer/signer.js\";\nimport {\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxId,\n} from \"../utils/bitcoin.js\";\nimport { getCrypto } from \"../utils/crypto.js\";\nimport { VerifiableSecretShare } from \"../utils/secret-sharing.js\";\nimport {\n createRefundTx,\n getEphemeralAnchorOutput,\n getNextTransactionSequence,\n getTransactionSequence,\n} from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport { SigningOperator } from \"./wallet-config.js\";\nconst INITIAL_TIME_LOCK = 2000;\n\nconst DEFAULT_EXPIRY_TIME = 10 * 60 * 1000;\n\nfunction initialSequence() {\n return (1 << 30) | INITIAL_TIME_LOCK;\n}\n\nconst crypto = getCrypto();\n\nexport type LeafKeyTweak = {\n leaf: TreeNode;\n signingPubKey: Uint8Array;\n newSigningPubKey: Uint8Array;\n};\n\nexport type ClaimLeafData = {\n signingPubKey: Uint8Array;\n tx?: Transaction;\n refundTx?: Transaction;\n signingNonceCommitment: SigningCommitment;\n vout?: number;\n};\n\nexport type LeafRefundSigningData = {\n signingPubKey: Uint8Array;\n receivingPubkey: Uint8Array;\n tx: Transaction;\n refundTx?: Transaction;\n signingNonceCommitment: SigningCommitment;\n vout: number;\n};\n\nexport class BaseTransferService {\n protected readonly config: WalletConfigService;\n protected readonly connectionManager: ConnectionManager;\n\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n this.config = config;\n this.connectionManager = connectionManager;\n }\n\n async sendTransferTweakKey(\n transfer: Transfer,\n leaves: LeafKeyTweak[],\n refundSignatureMap: Map<string, Uint8Array>,\n ): Promise<Transfer> {\n const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(\n transfer,\n leaves,\n refundSignatureMap,\n );\n\n let updatedTransfer: Transfer | undefined;\n\n const coordinatorOperator =\n this.config.getSigningOperators()[this.config.getCoordinatorIdentifier()];\n if (!coordinatorOperator) {\n throw new ValidationError(\"Coordinator operator not found\", {\n field: \"coordinator\",\n });\n }\n\n for (const [identifier, operator] of Object.entries(\n this.config.getSigningOperators(),\n ).filter(([_, op]) => op.address !== this.config.getCoordinatorAddress())) {\n updatedTransfer = await this.finalizeTransfer(\n operator,\n identifier,\n keyTweakInputMap,\n transfer,\n updatedTransfer,\n );\n }\n\n updatedTransfer = await this.finalizeTransfer(\n coordinatorOperator,\n this.config.getCoordinatorIdentifier(),\n keyTweakInputMap,\n transfer,\n updatedTransfer,\n );\n\n if (!updatedTransfer) {\n throw new ValidationError(\n \"No transfer response received from any operator\",\n {\n field: \"operators\",\n value: Object.keys(this.config.getSigningOperators()).length,\n },\n );\n }\n\n return updatedTransfer;\n }\n\n private async finalizeTransfer(\n operator: SigningOperator,\n identifier: string,\n keyTweakInputMap: Map<string, SendLeafKeyTweak[]>,\n transfer: Transfer,\n updatedTransfer: Transfer | undefined,\n ) {\n const sparkClient = await this.connectionManager.createSparkClient(\n operator.address,\n );\n\n const leavesToSend = keyTweakInputMap.get(identifier);\n if (!leavesToSend) {\n throw new ValidationError(\"No leaves to send for operator\", {\n field: \"operator\",\n value: identifier,\n });\n }\n let transferResp: FinalizeTransferResponse;\n try {\n transferResp = await sparkClient.finalize_transfer({\n transferId: transfer.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n leavesToSend,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to finalize transfer\",\n {\n method: \"POST\",\n },\n error as Error,\n );\n }\n\n if (!updatedTransfer) {\n updatedTransfer = transferResp.transfer;\n } else {\n if (!transferResp.transfer) {\n throw new ValidationError(\"No transfer response from operator\", {\n field: \"transfer\",\n value: transfer.id,\n });\n }\n\n if (!this.compareTransfers(updatedTransfer, transferResp.transfer)) {\n throw new ValidationError(\n \"Inconsistent transfer response from operators\",\n {\n field: \"transfer\",\n value: transfer.id,\n },\n );\n }\n }\n\n return updatedTransfer;\n }\n\n async signRefunds(\n leafDataMap: Map<string, ClaimLeafData>,\n operatorSigningResults: LeafRefundTxSigningResult[],\n adaptorPubKey?: Uint8Array,\n ): Promise<NodeSignatures[]> {\n const nodeSignatures: NodeSignatures[] = [];\n for (const operatorSigningResult of operatorSigningResults) {\n const leafData = leafDataMap.get(operatorSigningResult.leafId);\n if (\n !leafData ||\n !leafData.tx ||\n leafData.vout === undefined ||\n !leafData.refundTx\n ) {\n throw new Error(\n `Leaf data not found for leaf ${operatorSigningResult.leafId}`,\n );\n }\n\n const txOutput = leafData.tx?.getOutput(0);\n if (!txOutput) {\n throw new Error(\n `Output not found for leaf ${operatorSigningResult.leafId}`,\n );\n }\n\n const refundTxSighash = getSigHashFromTx(leafData.refundTx, 0, txOutput);\n\n const userSignature = await this.config.signer.signFrost({\n message: refundTxSighash,\n publicKey: leafData.signingPubKey,\n privateAsPubKey: leafData.signingPubKey,\n selfCommitment: leafData.signingNonceCommitment,\n statechainCommitments:\n operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,\n adaptorPubKey: adaptorPubKey,\n verifyingKey: operatorSigningResult.verifyingKey,\n });\n\n const refundAggregate = await this.config.signer.aggregateFrost({\n message: refundTxSighash,\n statechainSignatures:\n operatorSigningResult.refundTxSigningResult?.signatureShares,\n statechainPublicKeys:\n operatorSigningResult.refundTxSigningResult?.publicKeys,\n verifyingKey: operatorSigningResult.verifyingKey,\n statechainCommitments:\n operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,\n selfCommitment: leafData.signingNonceCommitment,\n publicKey: leafData.signingPubKey,\n selfSignature: userSignature,\n adaptorPubKey: adaptorPubKey,\n });\n\n nodeSignatures.push({\n nodeId: operatorSigningResult.leafId,\n refundTxSignature: refundAggregate,\n nodeTxSignature: new Uint8Array(),\n });\n }\n\n return nodeSignatures;\n }\n\n private async prepareSendTransferKeyTweaks(\n transfer: Transfer,\n leaves: LeafKeyTweak[],\n refundSignatureMap: Map<string, Uint8Array>,\n ): Promise<Map<string, SendLeafKeyTweak[]>> {\n const receiverEciesPubKey = ecies.PublicKey.fromHex(\n bytesToHex(transfer.receiverIdentityPublicKey),\n );\n\n const leavesTweaksMap = new Map<string, SendLeafKeyTweak[]>();\n\n for (const leaf of leaves) {\n const refundSignature = refundSignatureMap.get(leaf.leaf.id);\n const leafTweaksMap = await this.prepareSingleSendTransferKeyTweak(\n transfer.id,\n leaf,\n receiverEciesPubKey,\n refundSignature,\n );\n for (const [identifier, leafTweak] of leafTweaksMap) {\n leavesTweaksMap.set(identifier, [\n ...(leavesTweaksMap.get(identifier) || []),\n leafTweak,\n ]);\n }\n }\n\n return leavesTweaksMap;\n }\n\n private async prepareSingleSendTransferKeyTweak(\n transferID: string,\n leaf: LeafKeyTweak,\n receiverEciesPubKey: ecies.PublicKey,\n refundSignature?: Uint8Array,\n ): Promise<Map<string, SendLeafKeyTweak>> {\n const signingOperators = this.config.getSigningOperators();\n const pubKeyTweak =\n await this.config.signer.subtractPrivateKeysGivenPublicKeys(\n leaf.signingPubKey,\n leaf.newSigningPubKey,\n );\n\n const shares = await this.config.signer.splitSecretWithProofs({\n secret: pubKeyTweak,\n curveOrder: secp256k1.CURVE.n,\n threshold: this.config.getThreshold(),\n numShares: Object.keys(signingOperators).length,\n isSecretPubkey: true,\n });\n\n const pubkeySharesTweak = new Map<string, Uint8Array>();\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n\n const pubkeyTweak = secp256k1.getPublicKey(\n numberToBytesBE(share.share, 32),\n true,\n );\n pubkeySharesTweak.set(identifier, pubkeyTweak);\n }\n\n const secretCipher = await this.config.signer.encryptLeafPrivateKeyEcies(\n receiverEciesPubKey.toBytes(),\n leaf.newSigningPubKey,\n );\n\n const encoder = new TextEncoder();\n const payload = new Uint8Array([\n ...encoder.encode(leaf.leaf.id),\n ...encoder.encode(transferID),\n ...secretCipher,\n ]);\n\n const payloadHash = sha256(payload);\n const signature = await this.config.signer.signMessageWithIdentityKey(\n payloadHash,\n true,\n );\n\n const leafTweaksMap = new Map<string, SendLeafKeyTweak>();\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n\n leafTweaksMap.set(identifier, {\n leafId: leaf.leaf.id,\n secretShareTweak: {\n secretShare: numberToBytesBE(share.share, 32),\n proofs: share.proofs,\n },\n pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),\n secretCipher,\n signature,\n refundSignature: refundSignature ?? new Uint8Array(),\n });\n }\n\n return leafTweaksMap;\n }\n\n protected findShare(shares: VerifiableSecretShare[], operatorID: number) {\n const targetShareIndex = BigInt(operatorID + 1);\n for (const s of shares) {\n if (s.index === targetShareIndex) {\n return s;\n }\n }\n return undefined;\n }\n\n private compareTransfers(transfer1: Transfer, transfer2: Transfer) {\n return (\n transfer1.id === transfer2.id &&\n equalBytes(\n transfer1.senderIdentityPublicKey,\n transfer2.senderIdentityPublicKey,\n ) &&\n transfer1.status === transfer2.status &&\n transfer1.totalValue === transfer2.totalValue &&\n transfer1.expiryTime?.getTime() === transfer2.expiryTime?.getTime() &&\n transfer1.leaves.length === transfer2.leaves.length\n );\n }\n}\n\nexport class TransferService extends BaseTransferService {\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n super(config, connectionManager);\n }\n\n async sendTransfer(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n ): Promise<Transfer> {\n const { transfer, signatureMap } = await this.sendTransferSignRefund(\n leaves,\n receiverIdentityPubkey,\n new Date(Date.now() + DEFAULT_EXPIRY_TIME),\n );\n\n const transferWithTweakedKeys = await this.sendTransferTweakKey(\n transfer,\n leaves,\n signatureMap,\n );\n\n return transferWithTweakedKeys;\n }\n\n async claimTransfer(transfer: Transfer, leaves: LeafKeyTweak[]) {\n let proofMap: Map<string, Uint8Array[]> | undefined;\n if (transfer.status === TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED) {\n proofMap = await this.claimTransferTweakKeys(transfer, leaves);\n }\n const signatures = await this.claimTransferSignRefunds(\n transfer,\n leaves,\n proofMap,\n );\n\n return await this.finalizeNodeSignatures(signatures);\n }\n\n async queryPendingTransfers(): Promise<QueryTransfersResponse> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n let pendingTransfersResp: QueryTransfersResponse;\n try {\n pendingTransfersResp = await sparkClient.query_pending_transfers({\n participant: {\n $case: \"receiverIdentityPublicKey\",\n receiverIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n },\n });\n } catch (error) {\n throw new Error(`Error querying pending transfers: ${error}`);\n }\n return pendingTransfersResp;\n }\n\n async queryAllTransfers(\n limit: number,\n offset: number,\n ): Promise<QueryTransfersResponse> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let allTransfersResp: QueryTransfersResponse;\n try {\n allTransfersResp = await sparkClient.query_all_transfers({\n participant: {\n $case: \"senderOrReceiverIdentityPublicKey\",\n senderOrReceiverIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n },\n limit,\n offset,\n types: [\n TransferType.TRANSFER,\n TransferType.PREIMAGE_SWAP,\n TransferType.COOPERATIVE_EXIT,\n ],\n });\n } catch (error) {\n throw new Error(`Error querying all transfers: ${error}`);\n }\n return allTransfersResp;\n }\n\n async verifyPendingTransfer(\n transfer: Transfer,\n ): Promise<Map<string, Uint8Array>> {\n const leafPubKeyMap = new Map<string, Uint8Array>();\n for (const leaf of transfer.leaves) {\n if (!leaf.leaf) {\n throw new Error(\"Leaf is undefined\");\n }\n\n const encoder = new TextEncoder();\n const leafIdBytes = encoder.encode(leaf.leaf.id);\n const transferIdBytes = encoder.encode(transfer.id);\n\n const payload = new Uint8Array([\n ...leafIdBytes,\n ...transferIdBytes,\n ...leaf.secretCipher,\n ]);\n\n const payloadHash = sha256(payload);\n if (\n !secp256k1.verify(\n leaf.signature,\n payloadHash,\n transfer.senderIdentityPublicKey,\n )\n ) {\n throw new Error(\"Signature verification failed\");\n }\n\n const leafSecret = await this.config.signer.decryptEcies(\n leaf.secretCipher,\n );\n\n leafPubKeyMap.set(leaf.leaf.id, leafSecret);\n }\n return leafPubKeyMap;\n }\n\n async sendTransferSignRefund(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n }> {\n const { transfer, signatureMap, leafDataMap } =\n await this.sendTransferSignRefundInternal(\n leaves,\n receiverIdentityPubkey,\n expiryTime,\n false,\n );\n\n return {\n transfer,\n signatureMap,\n leafDataMap,\n };\n }\n\n async startSwapSignRefund(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n }> {\n const { transfer, signatureMap, leafDataMap } =\n await this.sendTransferSignRefundInternal(\n leaves,\n receiverIdentityPubkey,\n expiryTime,\n true,\n );\n\n return {\n transfer,\n signatureMap,\n leafDataMap,\n };\n }\n\n async counterSwapSignRefund(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n adaptorPubKey?: Uint8Array,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n signingResults: LeafRefundTxSigningResult[];\n }> {\n return this.sendTransferSignRefundInternal(\n leaves,\n receiverIdentityPubkey,\n expiryTime,\n true,\n adaptorPubKey,\n );\n }\n\n async sendTransferSignRefundInternal(\n leaves: LeafKeyTweak[],\n receiverIdentityPubkey: Uint8Array,\n expiryTime: Date,\n forSwap: boolean,\n adaptorPubKey?: Uint8Array,\n ): Promise<{\n transfer: Transfer;\n signatureMap: Map<string, Uint8Array>;\n leafDataMap: Map<string, LeafRefundSigningData>;\n signingResults: LeafRefundTxSigningResult[];\n }> {\n const transferId = uuidv7();\n const leafDataMap = new Map<string, LeafRefundSigningData>();\n for (const leaf of leaves) {\n const signingNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n\n const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n leafDataMap.set(leaf.leaf.id, {\n signingPubKey: leaf.signingPubKey,\n receivingPubkey: receiverIdentityPubkey,\n signingNonceCommitment,\n tx,\n refundTx,\n vout: leaf.leaf.vout,\n });\n }\n\n const signingJobs = this.prepareRefundSoSigningJobs(leaves, leafDataMap);\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: CounterLeafSwapResponse;\n try {\n if (adaptorPubKey !== undefined) {\n response = await sparkClient.counter_leaf_swap({\n transfer: {\n transferId,\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: expiryTime,\n },\n swapId: uuidv7(),\n adaptorPublicKey: adaptorPubKey || new Uint8Array(),\n });\n } else if (forSwap) {\n response = await sparkClient.start_leaf_swap({\n transferId,\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: expiryTime,\n });\n } else {\n response = await sparkClient.start_transfer({\n transferId,\n leavesToSend: signingJobs,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: expiryTime,\n });\n }\n } catch (error) {\n throw new Error(`Error starting send transfer: ${error}`);\n }\n\n if (!response.transfer) {\n throw new Error(\"No transfer response from coordinator\");\n }\n\n const signatures = await this.signRefunds(\n leafDataMap,\n response.signingResults,\n adaptorPubKey,\n );\n\n const signatureMap = new Map<string, Uint8Array>();\n for (const signature of signatures) {\n signatureMap.set(signature.nodeId, signature.refundTxSignature);\n }\n\n return {\n transfer: response.transfer,\n signatureMap,\n leafDataMap,\n signingResults: response.signingResults,\n };\n }\n\n private prepareRefundSoSigningJobs(\n leaves: LeafKeyTweak[],\n leafDataMap: Map<string, LeafRefundSigningData>,\n isForClaim?: boolean,\n ): LeafRefundTxSigningJob[] {\n const signingJobs: LeafRefundTxSigningJob[] = [];\n for (const leaf of leaves) {\n const refundSigningData = leafDataMap.get(leaf.leaf.id);\n if (!refundSigningData) {\n throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);\n }\n\n const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n const nodeOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(nodeTx)),\n index: 0,\n };\n\n const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n const nextSequence = isForClaim\n ? getTransactionSequence(currRefundTx.getInput(0).sequence)\n : getNextTransactionSequence(currRefundTx.getInput(0).sequence)\n .nextSequence;\n\n const amountSats = currRefundTx.getOutput(0).amount;\n if (amountSats === undefined) {\n throw new Error(\"Amount not found in signRefunds\");\n }\n\n const refundTx = createRefundTx(\n nextSequence,\n nodeOutPoint,\n amountSats,\n refundSigningData.receivingPubkey,\n this.config.getNetwork(),\n );\n\n refundSigningData.refundTx = refundTx;\n\n const refundNonceCommitmentProto =\n refundSigningData.signingNonceCommitment;\n\n signingJobs.push({\n leafId: leaf.leaf.id,\n refundTxSigningJob: {\n signingPublicKey: refundSigningData.signingPubKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: refundNonceCommitmentProto,\n },\n });\n }\n\n return signingJobs;\n }\n\n async claimTransferTweakKeys(\n transfer: Transfer,\n leaves: LeafKeyTweak[],\n ): Promise<Map<string, Uint8Array[]>> {\n const { leafDataMap: leavesTweaksMap, proofMap } =\n await this.prepareClaimLeavesKeyTweaks(leaves);\n\n const errors: Error[] = [];\n\n const promises = Object.entries(this.config.getSigningOperators()).map(\n async ([identifier, operator]) => {\n const sparkClient = await this.connectionManager.createSparkClient(\n operator.address,\n );\n\n const leavesToReceive = leavesTweaksMap.get(identifier);\n if (!leavesToReceive) {\n errors.push(\n new ValidationError(\"No leaves to receive for operator\", {\n field: \"operator\",\n value: identifier,\n }) as SparkSDKError,\n );\n return;\n }\n\n try {\n await sparkClient.claim_transfer_tweak_keys({\n transferId: transfer.id,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n leavesToReceive,\n });\n } catch (error) {\n errors.push(\n new NetworkError(\n \"Failed to claim transfer tweak keys\",\n {\n method: \"POST\",\n },\n error as Error,\n ) as SparkSDKError,\n );\n return;\n }\n },\n );\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n throw new NetworkError(\n \"Failed to claim transfer tweak keys\",\n {\n method: \"POST\",\n errorCount: errors.length,\n errors: errors.map((e) => e.message).join(\", \"),\n },\n errors[0],\n );\n }\n\n return proofMap;\n }\n\n private async prepareClaimLeavesKeyTweaks(leaves: LeafKeyTweak[]): Promise<{\n leafDataMap: Map<string, ClaimLeafKeyTweak[]>;\n proofMap: Map<string, Uint8Array[]>;\n }> {\n const leafDataMap = new Map<string, ClaimLeafKeyTweak[]>();\n const proofMap = new Map<string, Uint8Array[]>();\n for (const leaf of leaves) {\n const { leafKeyTweaks: leafData, proofs } =\n await this.prepareClaimLeafKeyTweaks(leaf);\n proofMap.set(leaf.leaf.id, proofs);\n\n for (const [identifier, leafTweak] of leafData) {\n leafDataMap.set(identifier, [\n ...(leafDataMap.get(identifier) || []),\n leafTweak,\n ]);\n }\n }\n return { leafDataMap, proofMap };\n }\n\n private async prepareClaimLeafKeyTweaks(leaf: LeafKeyTweak): Promise<{\n leafKeyTweaks: Map<string, ClaimLeafKeyTweak>;\n proofs: Uint8Array[];\n }> {\n const signingOperators = this.config.getSigningOperators();\n\n const pubKeyTweak =\n await this.config.signer.subtractPrivateKeysGivenPublicKeys(\n leaf.signingPubKey,\n leaf.newSigningPubKey,\n );\n\n const shares = await this.config.signer.splitSecretWithProofs({\n secret: pubKeyTweak,\n curveOrder: secp256k1.CURVE.n,\n threshold: this.config.getThreshold(),\n numShares: Object.keys(signingOperators).length,\n isSecretPubkey: true,\n });\n\n const pubkeySharesTweak = new Map<string, Uint8Array>();\n\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n const pubkeyTweak = secp256k1.getPublicKey(\n numberToBytesBE(share.share, 32),\n );\n pubkeySharesTweak.set(identifier, pubkeyTweak);\n }\n\n const leafTweaksMap = new Map<string, ClaimLeafKeyTweak>();\n for (const [identifier, operator] of Object.entries(signingOperators)) {\n const share = this.findShare(shares, operator.id);\n if (!share) {\n throw new Error(`Share not found for operator ${operator.id}`);\n }\n\n leafTweaksMap.set(identifier, {\n leafId: leaf.leaf.id,\n secretShareTweak: {\n secretShare: numberToBytesBE(share.share, 32),\n proofs: share.proofs,\n },\n pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),\n });\n }\n\n if (!shares[0]?.proofs) {\n throw new ValidationError(\"Proofs not found\", {\n field: \"proofs\",\n value: shares[0]?.proofs,\n }) as SparkSDKError;\n }\n\n return { leafKeyTweaks: leafTweaksMap, proofs: shares[0].proofs };\n }\n\n async claimTransferSignRefunds(\n transfer: Transfer,\n leafKeys: LeafKeyTweak[],\n proofMap?: Map<string, Uint8Array[]>,\n ): Promise<NodeSignatures[]> {\n const leafDataMap: Map<string, LeafRefundSigningData> = new Map();\n for (const leafKey of leafKeys) {\n const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);\n leafDataMap.set(leafKey.leaf.id, {\n signingPubKey: leafKey.newSigningPubKey,\n receivingPubkey: leafKey.newSigningPubKey,\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n tx,\n vout: leafKey.leaf.vout,\n });\n }\n\n const signingJobs = this.prepareRefundSoSigningJobs(\n leafKeys,\n leafDataMap,\n true,\n );\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n let resp: ClaimTransferSignRefundsResponse;\n\n const secretProofMap: { [key: string]: SecretProof } = {};\n if (proofMap) {\n for (const [leafId, proof] of proofMap.entries()) {\n secretProofMap[leafId] = {\n proofs: proof,\n };\n }\n }\n try {\n resp = await sparkClient.claim_transfer_sign_refunds({\n transferId: transfer.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n signingJobs,\n keyTweakProofs: secretProofMap,\n });\n } catch (error) {\n throw new Error(`Error claiming transfer sign refunds: ${error}`);\n }\n return this.signRefunds(leafDataMap, resp.signingResults);\n }\n\n private async finalizeNodeSignatures(nodeSignatures: NodeSignatures[]) {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n try {\n return await sparkClient.finalize_node_signatures({\n intent: SignatureIntent.TRANSFER,\n nodeSignatures,\n });\n } catch (error) {\n throw new Error(`Error finalizing node signatures in transfer: ${error}`);\n }\n }\n\n async cancelTransfer(\n transfer: Transfer,\n operatorAddress: string,\n ): Promise<Transfer | undefined> {\n const sparkClient =\n await this.connectionManager.createSparkClient(operatorAddress);\n\n try {\n const response = await sparkClient.cancel_transfer({\n transferId: transfer.id,\n senderIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n });\n\n return response.transfer;\n } catch (error) {\n throw new NetworkError(\n \"Failed to cancel transfer\",\n {\n method: \"POST\",\n },\n error as Error,\n );\n }\n }\n\n async queryPendingTransfersBySender(\n operatorAddress: string,\n ): Promise<QueryTransfersResponse> {\n const sparkClient =\n await this.connectionManager.createSparkClient(operatorAddress);\n try {\n return await sparkClient.query_pending_transfers({\n participant: {\n $case: \"senderIdentityPublicKey\",\n senderIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n },\n });\n } catch (error) {\n throw new Error(`Error querying pending transfers by sender: ${error}`);\n }\n }\n\n async refreshTimelockNodes(\n nodes: TreeNode[],\n parentNode: TreeNode,\n signingPubKey: Uint8Array,\n ) {\n if (nodes.length === 0) {\n throw Error(\"no nodes to refresh\");\n }\n\n const signingJobs: SigningJob[] = [];\n const newNodeTxs: Transaction[] = [];\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node) {\n throw Error(\"could not get node\");\n }\n const nodeTx = getTxFromRawTxBytes(node?.nodeTx);\n const input = nodeTx.getInput(0);\n\n if (!input) {\n throw Error(\"Could not fetch tx input\");\n }\n\n const newTx = new Transaction({ allowUnknownOutputs: true });\n for (let j = 0; j < nodeTx.outputsLength; j++) {\n newTx.addOutput(nodeTx.getOutput(j));\n }\n if (i === 0) {\n const currSequence = input.sequence;\n\n newTx.addInput({\n ...input,\n sequence: getNextTransactionSequence(currSequence).nextSequence,\n });\n } else {\n newTx.addInput({\n ...input,\n sequence: initialSequence(),\n txid: newNodeTxs[i - 1]?.id,\n });\n }\n\n signingJobs.push({\n signingPublicKey: signingPubKey,\n rawTx: newTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n });\n newNodeTxs[i] = newTx;\n }\n\n const leaf = nodes[nodes.length - 1];\n if (!leaf?.refundTx) {\n throw Error(\"leaf does not have refund tx\");\n }\n const refundTx = getTxFromRawTxBytes(leaf?.refundTx);\n const newRefundTx = new Transaction({ allowUnknownOutputs: true });\n\n for (let j = 0; j < refundTx.outputsLength; j++) {\n newRefundTx.addOutput(refundTx.getOutput(j));\n }\n\n const refundTxInput = refundTx.getInput(0);\n if (!refundTxInput) {\n throw Error(\"refund tx doesn't have input\");\n }\n\n if (!newNodeTxs[newNodeTxs.length - 1]) {\n throw Error(\"Could not get last node tx\");\n }\n newRefundTx.addInput({\n ...refundTxInput,\n sequence: initialSequence(),\n txid: getTxId(newNodeTxs[newNodeTxs.length - 1]!),\n });\n\n const refundSigningJob = {\n signingPublicKey: signingPubKey,\n rawTx: newRefundTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n };\n\n signingJobs.push(refundSigningJob);\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const response = await sparkClient.refresh_timelock({\n leafId: leaf.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n signingJobs,\n });\n\n if (signingJobs.length !== response.signingResults.length) {\n throw Error(\n `number of signing jobs and signing results do not match: ${signingJobs.length} !== ${response.signingResults.length}`,\n );\n }\n\n let nodeSignatures: NodeSignatures[] = [];\n let leafSignature: Uint8Array | undefined;\n let refundSignature: Uint8Array | undefined;\n let leafNodeId: string | undefined;\n for (let i = 0; i < response.signingResults.length; i++) {\n const signingResult = response.signingResults[i];\n const signingJob = signingJobs[i];\n if (!signingJob || !signingResult) {\n throw Error(\"Signing job does not exist\");\n }\n\n if (!signingJob.signingNonceCommitment) {\n throw Error(\"nonce commitment does not exist\");\n }\n const rawTx = getTxFromRawTxBytes(signingJob.rawTx);\n\n let parentTx: Transaction | undefined;\n let nodeId: string | undefined;\n let vout: number | undefined;\n\n if (i === nodes.length) {\n nodeId = nodes[i - 1]?.id;\n parentTx = newNodeTxs[i - 1];\n vout = 0;\n } else if (i === 0) {\n nodeId = nodes[i]?.id;\n parentTx = getTxFromRawTxBytes(parentNode.nodeTx);\n vout = nodes[i]?.vout;\n } else {\n nodeId = nodes[i]?.id;\n parentTx = newNodeTxs[i - 1];\n vout = nodes[i]?.vout;\n }\n\n if (!parentTx || !nodeId || vout === undefined) {\n throw Error(\"Could not parse signing results\");\n }\n\n const txOut = parentTx.getOutput(vout);\n\n const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);\n\n const userSignature = await this.config.signer.signFrost({\n message: rawTxSighash,\n privateAsPubKey: signingPubKey,\n publicKey: signingPubKey,\n verifyingKey: signingResult.verifyingKey,\n selfCommitment: signingJob.signingNonceCommitment,\n statechainCommitments:\n signingResult.signingResult?.signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n });\n\n const signature = await this.config.signer.aggregateFrost({\n message: rawTxSighash,\n statechainSignatures: signingResult.signingResult?.signatureShares,\n statechainPublicKeys: signingResult.signingResult?.publicKeys,\n verifyingKey: signingResult.verifyingKey,\n statechainCommitments:\n signingResult.signingResult?.signingNonceCommitments,\n selfCommitment: signingJob.signingNonceCommitment,\n publicKey: signingPubKey,\n selfSignature: userSignature,\n adaptorPubKey: new Uint8Array(),\n });\n\n if (i !== nodes.length && i !== nodes.length - 1) {\n nodeSignatures.push({\n nodeId: nodeId,\n nodeTxSignature: signature,\n refundTxSignature: new Uint8Array(),\n });\n } else if (i === nodes.length) {\n refundSignature = signature;\n } else if (i === nodes.length - 1) {\n leafNodeId = nodeId;\n leafSignature = signature;\n }\n }\n\n if (!leafSignature || !refundSignature || !leafNodeId) {\n throw Error(\"leaf or refund signature does not exist\");\n }\n\n nodeSignatures.push({\n nodeId: leafNodeId,\n nodeTxSignature: leafSignature,\n refundTxSignature: refundSignature,\n });\n\n return await sparkClient.finalize_node_signatures({\n intent: SignatureIntent.REFRESH,\n nodeSignatures,\n });\n }\n\n async extendTimelock(node: TreeNode, signingPubKey: Uint8Array) {\n const nodeTx = getTxFromRawTxBytes(node.nodeTx);\n const refundTx = getTxFromRawTxBytes(node.refundTx);\n\n const refundSequence = refundTx.getInput(0).sequence || 0;\n const newNodeOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(nodeTx)),\n index: 0,\n };\n\n const { nextSequence: newNodeSequence } =\n getNextTransactionSequence(refundSequence);\n const newNodeTx = new Transaction({ allowUnknownOutputs: true });\n newNodeTx.addInput({ ...newNodeOutPoint, sequence: newNodeSequence });\n newNodeTx.addOutput(nodeTx.getOutput(0));\n newNodeTx.addOutput(getEphemeralAnchorOutput());\n\n const newRefundOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(newNodeTx)!),\n index: 0,\n };\n\n const amountSats = refundTx.getOutput(0).amount;\n if (amountSats === undefined) {\n throw new Error(\"Amount not found in extendTimelock\");\n }\n\n const newRefundTx = createRefundTx(\n initialSequence(),\n newRefundOutPoint,\n amountSats,\n signingPubKey,\n this.config.getNetwork(),\n );\n\n const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));\n const refundSighash = getSigHashFromTx(newRefundTx, 0, nodeTx.getOutput(0));\n\n const newNodeSigningJob = {\n signingPublicKey: signingPubKey,\n rawTx: newNodeTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n };\n\n const newRefundSigningJob = {\n signingPublicKey: signingPubKey,\n rawTx: newRefundTx.toBytes(),\n signingNonceCommitment:\n await this.config.signer.getRandomSigningCommitment(),\n };\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const response = await sparkClient.extend_leaf({\n leafId: node.id,\n ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n nodeTxSigningJob: newNodeSigningJob,\n refundTxSigningJob: newRefundSigningJob,\n });\n\n if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {\n throw new Error(\"Signing result does not exist\");\n }\n\n const nodeUserSig = await this.config.signer.signFrost({\n message: nodeSighash,\n privateAsPubKey: signingPubKey,\n publicKey: signingPubKey,\n verifyingKey: response.nodeTxSigningResult.verifyingKey,\n selfCommitment: newNodeSigningJob.signingNonceCommitment,\n statechainCommitments:\n response.nodeTxSigningResult.signingResult?.signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n });\n\n const refundUserSig = await this.config.signer.signFrost({\n message: refundSighash,\n privateAsPubKey: signingPubKey,\n publicKey: signingPubKey,\n verifyingKey: response.refundTxSigningResult.verifyingKey,\n selfCommitment: newRefundSigningJob.signingNonceCommitment,\n statechainCommitments:\n response.refundTxSigningResult.signingResult?.signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n });\n\n const nodeSig = await this.config.signer.aggregateFrost({\n message: nodeSighash,\n statechainSignatures:\n response.nodeTxSigningResult.signingResult?.signatureShares,\n statechainPublicKeys:\n response.nodeTxSigningResult.signingResult?.publicKeys,\n verifyingKey: response.nodeTxSigningResult.verifyingKey,\n statechainCommitments:\n response.nodeTxSigningResult.signingResult?.signingNonceCommitments,\n selfCommitment: newNodeSigningJob.signingNonceCommitment,\n publicKey: signingPubKey,\n selfSignature: nodeUserSig,\n adaptorPubKey: new Uint8Array(),\n });\n\n const refundSig = await this.config.signer.aggregateFrost({\n message: refundSighash,\n statechainSignatures:\n response.refundTxSigningResult.signingResult?.signatureShares,\n statechainPublicKeys:\n response.refundTxSigningResult.signingResult?.publicKeys,\n verifyingKey: response.refundTxSigningResult.verifyingKey,\n statechainCommitments:\n response.refundTxSigningResult.signingResult?.signingNonceCommitments,\n selfCommitment: newRefundSigningJob.signingNonceCommitment,\n publicKey: signingPubKey,\n selfSignature: refundUserSig,\n adaptorPubKey: new Uint8Array(),\n });\n\n return await sparkClient.finalize_node_signatures({\n intent: SignatureIntent.EXTEND,\n nodeSignatures: [\n {\n nodeId: response.leafId,\n nodeTxSignature: nodeSig,\n refundTxSignature: refundSig,\n },\n ],\n });\n }\n}\n","import {\n bytesToNumberBE,\n hexToBytes,\n numberToBytesBE,\n} from \"@noble/curves/abstract/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { TransactionInput } from \"@scure/btc-signer/psbt\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport { decode } from \"light-bolt11-decoder\";\nimport { uuidv7 } from \"uuidv7\";\nimport { NetworkError, ValidationError } from \"../errors/types.js\";\nimport LightningReceiveRequest from \"../graphql/objects/LightningReceiveRequest.js\";\nimport {\n GetSigningCommitmentsResponse,\n InitiatePreimageSwapRequest_Reason,\n InitiatePreimageSwapResponse,\n ProvidePreimageResponse,\n QueryUserSignedRefundsResponse,\n RequestedSigningCommitments,\n Transfer,\n UserSignedRefund,\n UserSignedTxSigningJob,\n} from \"../proto/spark.js\";\nimport {\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxId,\n} from \"../utils/bitcoin.js\";\nimport { getCrypto } from \"../utils/crypto.js\";\nimport {\n createRefundTx,\n getNextTransactionSequence,\n} from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport { LeafKeyTweak } from \"./transfer.js\";\n\nconst crypto = getCrypto();\n\nexport type CreateLightningInvoiceParams = {\n invoiceCreator: (\n amountSats: number,\n paymentHash: Uint8Array,\n memo?: string,\n ) => Promise<LightningReceiveRequest | null>;\n amountSats: number;\n memo?: string;\n};\n\nexport type CreateLightningInvoiceWithPreimageParams = {\n preimage: Uint8Array;\n} & CreateLightningInvoiceParams;\n\nexport type SwapNodesForPreimageParams = {\n leaves: LeafKeyTweak[];\n receiverIdentityPubkey: Uint8Array;\n paymentHash: Uint8Array;\n invoiceString?: string;\n isInboundPayment: boolean;\n feeSats?: number;\n};\n\nexport class LightningService {\n private readonly config: WalletConfigService;\n private readonly connectionManager: ConnectionManager;\n\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n this.config = config;\n this.connectionManager = connectionManager;\n }\n\n async createLightningInvoice({\n invoiceCreator,\n amountSats,\n memo,\n }: CreateLightningInvoiceParams): Promise<LightningReceiveRequest> {\n const randBytes = crypto.getRandomValues(new Uint8Array(32));\n const preimage = numberToBytesBE(\n bytesToNumberBE(randBytes) % secp256k1.CURVE.n,\n 32,\n );\n return await this.createLightningInvoiceWithPreImage({\n invoiceCreator,\n amountSats,\n memo,\n preimage,\n });\n }\n\n async createLightningInvoiceWithPreImage({\n invoiceCreator,\n amountSats,\n memo,\n preimage,\n }: CreateLightningInvoiceWithPreimageParams): Promise<LightningReceiveRequest> {\n const paymentHash = sha256(preimage);\n const invoice = await invoiceCreator(amountSats, paymentHash, memo);\n if (!invoice) {\n throw new ValidationError(\"Failed to create lightning invoice\", {\n field: \"invoice\",\n value: null,\n expected: \"Non-null invoice\",\n });\n }\n\n const shares = await this.config.signer.splitSecretWithProofs({\n secret: preimage,\n curveOrder: secp256k1.CURVE.n,\n threshold: this.config.getThreshold(),\n numShares: Object.keys(this.config.getSigningOperators()).length,\n });\n\n const errors: Error[] = [];\n const promises = Object.entries(this.config.getSigningOperators()).map(\n async ([_, operator]) => {\n const share = shares[operator.id];\n if (!share) {\n throw new ValidationError(\"Share not found for operator\", {\n field: \"share\",\n value: operator.id,\n expected: \"Non-null share\",\n });\n }\n\n const sparkClient = await this.connectionManager.createSparkClient(\n operator.address,\n );\n\n try {\n await sparkClient.store_preimage_share({\n paymentHash,\n preimageShare: {\n secretShare: numberToBytesBE(share.share, 32),\n proofs: share.proofs,\n },\n threshold: this.config.getThreshold(),\n invoiceString: invoice.invoice.encodedInvoice,\n userIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n });\n } catch (e: any) {\n errors.push(e);\n }\n },\n );\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n throw new NetworkError(\n \"Failed to store preimage shares\",\n {\n operation: \"store_preimage_share\",\n errorCount: errors.length,\n errors: errors.map((e) => e.message).join(\", \"),\n },\n errors[0],\n );\n }\n\n return invoice;\n }\n\n async swapNodesForPreimage({\n leaves,\n receiverIdentityPubkey,\n paymentHash,\n invoiceString,\n isInboundPayment,\n feeSats = 0,\n }: SwapNodesForPreimageParams): Promise<InitiatePreimageSwapResponse> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let signingCommitments: GetSigningCommitmentsResponse;\n try {\n signingCommitments = await sparkClient.get_signing_commitments({\n nodeIds: leaves.map((leaf) => leaf.leaf.id),\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to get signing commitments\",\n {\n operation: \"get_signing_commitments\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n const leafSigningJobs = await this.signRefunds(\n leaves,\n signingCommitments.signingCommitments,\n receiverIdentityPubkey,\n );\n\n const transferId = uuidv7();\n let bolt11String = \"\";\n let amountSats: number = 0;\n if (invoiceString) {\n const decodedInvoice = decode(invoiceString);\n let amountMsats = 0;\n try {\n amountMsats = Number(\n decodedInvoice.sections.find((section) => section.name === \"amount\")\n ?.value,\n );\n } catch (error) {\n console.error(\"Error decoding invoice\", error);\n }\n\n amountSats = amountMsats / 1000;\n bolt11String = invoiceString;\n }\n\n const reason = isInboundPayment\n ? InitiatePreimageSwapRequest_Reason.REASON_RECEIVE\n : InitiatePreimageSwapRequest_Reason.REASON_SEND;\n\n let response: InitiatePreimageSwapResponse;\n try {\n response = await sparkClient.initiate_preimage_swap({\n paymentHash,\n invoiceAmount: {\n invoiceAmountProof: {\n bolt11Invoice: bolt11String,\n },\n valueSats: amountSats,\n },\n reason,\n transfer: {\n transferId,\n ownerIdentityPublicKey:\n await this.config.signer.getIdentityPublicKey(),\n leavesToSend: leafSigningJobs,\n receiverIdentityPublicKey: receiverIdentityPubkey,\n expiryTime: new Date(Date.now() + 2 * 60 * 1000),\n },\n receiverIdentityPublicKey: receiverIdentityPubkey,\n feeSats,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to initiate preimage swap\",\n {\n operation: \"initiate_preimage_swap\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n return response;\n }\n\n async queryUserSignedRefunds(\n paymentHash: Uint8Array,\n ): Promise<UserSignedRefund[]> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: QueryUserSignedRefundsResponse;\n try {\n response = await sparkClient.query_user_signed_refunds({\n paymentHash,\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to query user signed refunds\",\n {\n operation: \"query_user_signed_refunds\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n return response.userSignedRefunds;\n }\n\n validateUserSignedRefund(userSignedRefund: UserSignedRefund): bigint {\n const refundTx = getTxFromRawTxBytes(userSignedRefund.refundTx);\n // TODO: Should we assert that the amount is always defined here?\n return refundTx.getOutput(0).amount || 0n;\n }\n\n async providePreimage(preimage: Uint8Array): Promise<Transfer> {\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const paymentHash = sha256(preimage);\n let response: ProvidePreimageResponse;\n try {\n response = await sparkClient.provide_preimage({\n preimage,\n paymentHash,\n identityPublicKey: await this.config.signer.getIdentityPublicKey(),\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to provide preimage\",\n {\n operation: \"provide_preimage\",\n errorCount: 1,\n errors: error instanceof Error ? error.message : String(error),\n },\n error as Error,\n );\n }\n\n if (!response.transfer) {\n throw new ValidationError(\"No transfer returned from coordinator\", {\n field: \"transfer\",\n value: response,\n expected: \"Non-null transfer\",\n });\n }\n\n return response.transfer;\n }\n\n private async signRefunds(\n leaves: LeafKeyTweak[],\n signingCommitments: RequestedSigningCommitments[],\n receiverIdentityPubkey: Uint8Array,\n ): Promise<UserSignedTxSigningJob[]> {\n const leafSigningJobs: UserSignedTxSigningJob[] = [];\n for (let i = 0; i < leaves.length; i++) {\n const leaf = leaves[i];\n if (!leaf?.leaf) {\n throw new ValidationError(\"Leaf not found in signRefunds\", {\n field: \"leaf\",\n value: leaf,\n expected: \"Non-null leaf\",\n });\n }\n\n const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);\n const nodeOutPoint: TransactionInput = {\n txid: hexToBytes(getTxId(nodeTx)),\n index: 0,\n };\n\n const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);\n const { nextSequence } = getNextTransactionSequence(\n currRefundTx.getInput(0).sequence,\n );\n const amountSats = currRefundTx.getOutput(0).amount;\n if (amountSats === undefined) {\n throw new ValidationError(\"Invalid refund transaction\", {\n field: \"amount\",\n value: currRefundTx.getOutput(0),\n expected: \"Non-null amount\",\n });\n }\n\n const refundTx = createRefundTx(\n nextSequence,\n nodeOutPoint,\n amountSats,\n receiverIdentityPubkey,\n this.config.getNetwork(),\n );\n\n const sighash = getSigHashFromTx(refundTx, 0, nodeTx.getOutput(0));\n\n const signingCommitment =\n await this.config.signer.getRandomSigningCommitment();\n\n const signingNonceCommitments =\n signingCommitments[i]?.signingNonceCommitments;\n if (!signingNonceCommitments) {\n throw new ValidationError(\"Invalid signing commitments\", {\n field: \"signingNonceCommitments\",\n value: signingCommitments[i],\n expected: \"Non-null signing nonce commitments\",\n });\n }\n const signingResult = await this.config.signer.signFrost({\n message: sighash,\n publicKey: leaf.signingPubKey,\n privateAsPubKey: leaf.signingPubKey,\n selfCommitment: signingCommitment,\n statechainCommitments: signingNonceCommitments,\n adaptorPubKey: new Uint8Array(),\n verifyingKey: leaf.leaf.verifyingPublicKey,\n });\n\n leafSigningJobs.push({\n leafId: leaf.leaf.id,\n signingPublicKey: leaf.signingPubKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: signingCommitment,\n userSignature: signingResult,\n signingCommitments: {\n signingCommitments: signingNonceCommitments,\n },\n });\n }\n\n return leafSigningJobs;\n }\n}\n","import { Address, OutScript, Transaction } from \"@scure/btc-signer\";\nimport { sha256 } from \"@scure/btc-signer/utils\";\nimport {\n AddressNode,\n AddressRequestNode,\n CreateTreeRequest,\n CreateTreeResponse,\n CreationNode,\n CreationResponseNode,\n FinalizeNodeSignaturesResponse,\n NodeSignatures,\n PrepareTreeAddressRequest,\n PrepareTreeAddressResponse,\n SigningJob,\n TreeNode,\n} from \"../proto/spark.js\";\nimport { SigningCommitment } from \"../signer/signer.js\";\nimport {\n getP2TRAddressFromPublicKey,\n getSigHashFromTx,\n getTxFromRawTxBytes,\n getTxId,\n} from \"../utils/bitcoin.js\";\nimport { getNetwork, Network } from \"../utils/network.js\";\nimport { getEphemeralAnchorOutput } from \"../utils/transaction.js\";\nimport { WalletConfigService } from \"./config.js\";\nimport { ConnectionManager } from \"./connection.js\";\nimport { NetworkError, ValidationError } from \"../errors/index.js\";\n\nexport type DepositAddressTree = {\n address?: string | undefined;\n signingPublicKey: Uint8Array;\n verificationKey?: Uint8Array | undefined;\n children: DepositAddressTree[];\n};\n\nexport type CreationNodeWithNonces = CreationNode & {\n nodeTxSigningCommitment?: SigningCommitment | undefined;\n refundTxSigningCommitment?: SigningCommitment | undefined;\n};\n\nconst INITIAL_TIME_LOCK = 2000;\n\nexport class TreeCreationService {\n private readonly config: WalletConfigService;\n private readonly connectionManager: ConnectionManager;\n\n constructor(\n config: WalletConfigService,\n connectionManager: ConnectionManager,\n ) {\n this.config = config;\n this.connectionManager = connectionManager;\n }\n\n async generateDepositAddressForTree(\n vout: number,\n parentSigningPublicKey: Uint8Array,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ): Promise<DepositAddressTree> {\n if (!parentTx && !parentNode) {\n throw new Error(\"No parent tx or parent node provided\");\n }\n\n const id = parentNode?.id ?? getTxId(parentTx!);\n\n const tree = await this.createDepositAddressTree(\n parentSigningPublicKey,\n id,\n );\n\n const addressRequestNodes =\n this.createAddressRequestNodeFromTreeNodes(tree);\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n const request: PrepareTreeAddressRequest = {\n userIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n node: undefined,\n };\n if (parentNode) {\n if (!parentNode.parentNodeId) {\n throw new Error(\"Parent node ID is undefined\");\n }\n request.source = {\n $case: \"parentNodeOutput\",\n parentNodeOutput: {\n nodeId: parentNode.parentNodeId,\n vout: vout,\n },\n };\n } else if (parentTx) {\n request.source = {\n $case: \"onChainUtxo\",\n onChainUtxo: {\n vout: vout,\n rawTx: parentTx.toBytes(),\n network: this.config.getNetworkProto(),\n },\n };\n } else {\n throw new Error(\"No parent node or parent tx provided\");\n }\n\n request.node = {\n userPublicKey: parentSigningPublicKey,\n children: addressRequestNodes,\n };\n\n const root: DepositAddressTree = {\n address: undefined,\n signingPublicKey: parentSigningPublicKey,\n children: tree,\n };\n\n let response: PrepareTreeAddressResponse;\n try {\n response = await sparkClient.prepare_tree_address(request);\n } catch (error) {\n throw new Error(`Error preparing tree address: ${error}`);\n }\n\n if (!response.node) {\n throw new Error(\"No node found in response\");\n }\n\n this.applyAddressNodesToTree([root], [response.node]);\n\n return root;\n }\n\n async createTree(\n vout: number,\n root: DepositAddressTree,\n createLeaves: boolean,\n parentTx?: Transaction,\n parentNode?: TreeNode,\n ): Promise<FinalizeNodeSignaturesResponse> {\n const request: CreateTreeRequest = {\n userIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),\n node: undefined,\n };\n\n let tx: Transaction | undefined;\n if (parentTx) {\n tx = parentTx;\n request.source = {\n $case: \"onChainUtxo\",\n onChainUtxo: {\n vout: vout,\n rawTx: parentTx.toBytes(),\n network: this.config.getNetworkProto(),\n },\n };\n } else if (parentNode) {\n tx = getTxFromRawTxBytes(parentNode.nodeTx);\n if (!parentNode.parentNodeId) {\n throw new Error(\"Parent node ID is undefined\");\n }\n request.source = {\n $case: \"parentNodeOutput\",\n parentNodeOutput: {\n nodeId: parentNode.parentNodeId,\n vout: vout,\n },\n };\n } else {\n throw new Error(\"No parent node or parent tx provided\");\n }\n\n const rootCreationNode = await this.buildCreationNodesFromTree(\n vout,\n createLeaves,\n this.config.getNetwork(),\n root,\n tx,\n );\n\n request.node = rootCreationNode;\n\n const sparkClient = await this.connectionManager.createSparkClient(\n this.config.getCoordinatorAddress(),\n );\n\n let response: CreateTreeResponse;\n try {\n response = await sparkClient.create_tree(request);\n } catch (error) {\n throw new Error(`Error creating tree: ${error}`);\n }\n\n if (!response.node) {\n throw new Error(\"No node found in response\");\n }\n\n const creationResultTreeRoot = response.node;\n\n const nodeSignatures = await this.signTreeCreation(\n tx,\n vout,\n root,\n rootCreationNode,\n creationResultTreeRoot,\n );\n\n let finalizeResp: FinalizeNodeSignaturesResponse;\n try {\n finalizeResp = await sparkClient.finalize_node_signatures({\n nodeSignatures: nodeSignatures,\n });\n } catch (error) {\n throw new NetworkError(\n \"Failed to finalize node signatures\",\n {\n operation: \"finalize_node_signatures\",\n nodeSignaturesCount: nodeSignatures.length,\n },\n error as Error,\n );\n }\n\n return finalizeResp;\n }\n\n private async createDepositAddressTree(\n targetSigningPublicKey: Uint8Array,\n nodeId: string,\n ): Promise<DepositAddressTree[]> {\n const leftKey = await this.config.signer.generatePublicKey(sha256(nodeId));\n const leftNode: DepositAddressTree = {\n signingPublicKey: leftKey,\n children: [],\n };\n\n const rightKey =\n await this.config.signer.subtractPrivateKeysGivenPublicKeys(\n targetSigningPublicKey,\n leftKey,\n );\n\n const rightNode: DepositAddressTree = {\n signingPublicKey: rightKey,\n children: [],\n };\n return [leftNode, rightNode];\n }\n\n private createAddressRequestNodeFromTreeNodes(\n treeNodes: DepositAddressTree[],\n ): AddressRequestNode[] {\n const results: AddressRequestNode[] = [];\n for (const node of treeNodes) {\n const result: AddressRequestNode = {\n userPublicKey: node.signingPublicKey,\n children: this.createAddressRequestNodeFromTreeNodes(node.children),\n };\n results.push(result);\n }\n return results;\n }\n\n private applyAddressNodesToTree(\n tree: DepositAddressTree[],\n addressNodes: AddressNode[],\n ) {\n for (let i = 0; i < tree.length; i++) {\n if (!tree[i]) {\n throw new ValidationError(\"Tree node is undefined\", {\n index: i,\n treeLength: tree.length,\n });\n }\n if (!addressNodes[i]) {\n throw new ValidationError(\"Address node is undefined\", {\n index: i,\n addressNodesLength: addressNodes.length,\n });\n }\n // @ts-ignore\n tree[i].address = addressNodes[i].address?.address;\n // @ts-ignore\n tree[i].verificationKey = addressNodes[i].address?.verifyingKey;\n // @ts-ignore\n this.applyAddressNodesToTree(tree[i].children, addressNodes[i].children);\n }\n }\n\n private async buildChildCreationNode(\n node: DepositAddressTree,\n parentTx: Transaction,\n vout: number,\n network: Network,\n ): Promise<CreationNodeWithNonces> {\n // internal node\n const internalCreationNode: CreationNodeWithNonces = {\n nodeTxSigningJob: undefined,\n refundTxSigningJob: undefined,\n children: [],\n };\n\n const tx = new Transaction();\n tx.addInput({\n txid: getTxId(parentTx),\n index: vout,\n });\n\n const parentTxOut = parentTx.getOutput(vout);\n if (!parentTxOut?.script || !parentTxOut?.amount) {\n throw new Error(\"parentTxOut is undefined\");\n }\n\n tx.addOutput({\n script: parentTxOut.script,\n amount: parentTxOut.amount,\n });\n\n // Add ephemeral anchor\n tx.addOutput(getEphemeralAnchorOutput());\n\n const signingNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const signingJob: SigningJob = {\n signingPublicKey: node.signingPublicKey,\n rawTx: tx.toBytes(),\n signingNonceCommitment: signingNonceCommitment,\n };\n\n internalCreationNode.nodeTxSigningCommitment = signingNonceCommitment;\n internalCreationNode.nodeTxSigningJob = signingJob;\n\n // leaf node\n const sequence = (1 << 30) | INITIAL_TIME_LOCK;\n\n const childCreationNode: CreationNodeWithNonces = {\n nodeTxSigningJob: undefined,\n refundTxSigningJob: undefined,\n children: [],\n };\n\n const childTx = new Transaction();\n childTx.addInput({\n txid: getTxId(tx),\n index: 0,\n sequence,\n });\n\n childTx.addOutput({\n script: parentTxOut.script,\n amount: parentTxOut.amount,\n });\n\n // Add ephemeral anchor\n childTx.addOutput(getEphemeralAnchorOutput());\n\n const childSigningNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const childSigningJob: SigningJob = {\n signingPublicKey: node.signingPublicKey,\n rawTx: childTx.toBytes(),\n signingNonceCommitment: childSigningNonceCommitment,\n };\n\n childCreationNode.nodeTxSigningCommitment = childSigningNonceCommitment;\n childCreationNode.nodeTxSigningJob = childSigningJob;\n\n const refundTx = new Transaction();\n refundTx.addInput({\n txid: getTxId(childTx),\n index: 0,\n sequence,\n });\n\n const refundP2trAddress = getP2TRAddressFromPublicKey(\n node.signingPublicKey,\n network,\n );\n const refundAddress = Address(getNetwork(network)).decode(\n refundP2trAddress,\n );\n const refundPkScript = OutScript.encode(refundAddress);\n refundTx.addOutput({\n script: refundPkScript,\n amount: parentTxOut.amount,\n });\n\n const refundSigningNonceCommitment =\n await this.config.signer.getRandomSigningCommitment();\n\n const refundSigningJob: SigningJob = {\n signingPublicKey: node.signingPublicKey,\n rawTx: refundTx.toBytes(),\n signingNonceCommitment: refundSigningNonceCommitment,\n };\n childCreationNode.refundTxSigningCommitment = refundSigningNonceCommitment;\n childCreationNode.refundTxSigningJob = refundSigningJob;\n\n internalCreationNode.children.push(childCreationNode);\n\n return internalCreationNode;\n }\n\n private async buildCreationNodesFromTree(\n vout: number,\n createLeaves: boolean,\n network: Network,\n root: DepositAddressTree,\n parentTx: Transaction,\n ): Promise<CreationNodeWithNonces> {\n const parentTxOutput = parentTx.getOutput(vout);\n if (!parentTxOutput?.script || !parentTxOutput?.amount) {\n throw new Error(\"parentTxOutput is undefined\");\n }\n const rootNodeTx = new Transaction();\n rootNodeTx.addInput({\n txid: getTxId(parentTx),\n index: vout,\n });\n\n for (let i = 0; i < root.children.length; i++) {\n const child = root.children[i];\n if (!child || !child.address) {\n throw new Error(\"child address is undefined\");\n }\n const childAddress = Address(getNetwork(network)).decode(child.address);\n const childPkScript = OutScript.encode(childAddress);\n rootNodeTx.addOutput({\n script: childPkScript,\n amount: parentTxOutput.amount / 2n,\n });\n }\n\n // Add ephemeral anchor output\n const anchor = getEphemeralAnchorOutput();\n rootNodeTx.addOutput(anchor);\n\n const rootNodeSigningCommitment =\n await this.config.signer.getRandomSigningCommitment();\n const rootNodeSigningJob: SigningJob = {\n signingPublicKey: root.signingPublicKey,\n rawTx: rootNodeTx.toBytes(),\n signingNonceCommitment: rootNodeSigningCommitment,\n };\n const rootCreationNode: CreationNodeWithNonces = {\n nodeTxSigningJob: rootNodeSigningJob,\n refundTxSigningJob: undefined,\n children: [],\n };\n rootCreationNode.nodeTxSigningCommitment = rootNodeSigningCommitment;\n\n const leftChild = root.children[0];\n const rightChild = root.children[1];\n if (!leftChild || !rightChild) {\n throw new Error(\"Root children are undefined\");\n }\n\n const leftChildCreationNode = await this.buildChildCreationNode(\n leftChild,\n rootNodeTx,\n 0,\n network,\n );\n const rightChildCreationNode = await this.buildChildCreationNode(\n rightChild,\n rootNodeTx,\n 1,\n network,\n );\n\n rootCreationNode.children.push(leftChildCreationNode);\n rootCreationNode.children.push(rightChildCreationNode);\n\n return rootCreationNode;\n }\n\n private async signNodeCreation(\n parentTx: Transaction,\n vout: number,\n internalNode: DepositAddressTree,\n creationNode: CreationNodeWithNonces,\n creationResponseNode: CreationResponseNode,\n ): Promise<{ tx: Transaction; signature: NodeSignatures }> {\n if (\n !creationNode.nodeTxSigningJob?.signingPublicKey ||\n !internalNode.verificationKey\n ) {\n throw new Error(\"signingPublicKey or verificationKey is undefined\");\n }\n\n const parentTxOutput = parentTx.getOutput(vout);\n if (!parentTxOutput) {\n throw new Error(\"parentTxOutput is undefined\");\n }\n\n const tx = getTxFromRawTxBytes(creationNode.nodeTxSigningJob.rawTx);\n const txSighash = getSigHashFromTx(tx, 0, parentTxOutput);\n\n let nodeTxSignature: Uint8Array = new Uint8Array();\n if (creationNode.nodeTxSigningCommitment) {\n const userSignature = await this.config.signer.signFrost({\n message: txSighash,\n publicKey: creationNode.nodeTxSigningJob.signingPublicKey,\n privateAsPubKey: internalNode.signingPublicKey,\n selfCommitment: creationNode.nodeTxSigningCommitment,\n statechainCommitments:\n creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,\n verifyingKey: internalNode.verificationKey,\n });\n\n nodeTxSignature = await this.config.signer.aggregateFrost({\n message: txSighash,\n statechainSignatures:\n creationResponseNode.nodeTxSigningResult?.signatureShares,\n statechainPublicKeys:\n creationResponseNode.nodeTxSigningResult?.publicKeys,\n verifyingKey: internalNode.verificationKey,\n statechainCommitments:\n creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,\n selfCommitment: creationNode.nodeTxSigningCommitment,\n selfSignature: userSignature,\n publicKey: internalNode.signingPublicKey,\n });\n }\n\n let refundTxSignature: Uint8Array = new Uint8Array();\n if (creationNode.refundTxSigningCommitment) {\n const rawTx = creationNode.refundTxSigningJob?.rawTx;\n if (!rawTx) {\n throw new Error(\"rawTx is undefined\");\n }\n if (!creationNode.refundTxSigningJob?.signingPublicKey) {\n throw new Error(\"signingPublicKey is undefined\");\n }\n const refundTx = getTxFromRawTxBytes(rawTx);\n const refundTxSighash = getSigHashFromTx(refundTx, 0, parentTxOutput);\n\n const refundSigningResponse = await this.config.signer.signFrost({\n message: refundTxSighash,\n publicKey: creationNode.refundTxSigningJob.signingPublicKey,\n privateAsPubKey: internalNode.signingPublicKey,\n selfCommitment: creationNode.refundTxSigningCommitment,\n statechainCommitments:\n creationResponseNode.refundTxSigningResult?.signingNonceCommitments,\n verifyingKey: internalNode.verificationKey,\n });\n\n refundTxSignature = await this.config.signer.aggregateFrost({\n message: refundTxSighash,\n statechainSignatures:\n creationResponseNode.refundTxSigningResult?.signatureShares,\n statechainPublicKeys:\n creationResponseNode.refundTxSigningResult?.publicKeys,\n verifyingKey: internalNode.verificationKey,\n statechainCommitments:\n creationResponseNode.refundTxSigningResult?.signingNonceCommitments,\n selfCommitment: creationNode.refundTxSigningCommitment,\n selfSignature: refundSigningResponse,\n publicKey: internalNode.signingPublicKey,\n });\n }\n\n return {\n tx: tx,\n signature: {\n nodeId: creationResponseNode.nodeId,\n nodeTxSignature: nodeTxSignature,\n refundTxSignature: refundTxSignature,\n },\n };\n }\n\n private async signTreeCreation(\n tx: Transaction,\n vout: number,\n root: DepositAddressTree,\n rootCreationNode: CreationNodeWithNonces,\n creationResultTreeRoot: CreationResponseNode,\n ): Promise<NodeSignatures[]> {\n const rootSignature = await this.signNodeCreation(\n tx,\n vout,\n root,\n rootCreationNode,\n creationResultTreeRoot,\n );\n\n const firstRootChild = root.children[0];\n const secondRootChild = root.children[1];\n const firstRootChildCreationNode = rootCreationNode.children[0];\n const secondRootChildCreationNode = rootCreationNode.children[1];\n const firstRootChildCreationResult = creationResultTreeRoot.children[0];\n const secondRootChildCreationResult = creationResultTreeRoot.children[1];\n if (!firstRootChild || !secondRootChild) {\n throw new Error(\"Root children are undefined\");\n }\n\n if (!firstRootChildCreationNode || !secondRootChildCreationNode) {\n throw new Error(\"Root child creation nodes are undefined\");\n }\n\n if (!firstRootChildCreationResult || !secondRootChildCreationResult) {\n throw new Error(\"Root child creation results are undefined\");\n }\n\n const leftChildSignature = await this.signNodeCreation(\n rootSignature.tx,\n 0,\n firstRootChild,\n firstRootChildCreationNode,\n firstRootChildCreationResult,\n );\n\n const rightChildSignature = await this.signNodeCreation(\n rootSignature.tx,\n 1,\n secondRootChild,\n secondRootChildCreationNode,\n secondRootChildCreationResult,\n );\n\n const signatures = [\n rootSignature.signature,\n leftChildSignature.signature,\n rightChildSignature.signature,\n ];\n\n return signatures;\n }\n}\n","import { bytesToHex, hexToBytes } from \"@noble/curves/abstract/utils\";\nimport { schnorr, secp256k1 } from \"@noble/curves/secp256k1\";\nimport * as btc from \"@scure/btc-signer\";\nimport { Address, OutScript, SigHash, Transaction } from \"@scure/btc-signer\";\nimport { TransactionInput, TransactionOutput } from \"@scure/btc-signer/psbt\";\nimport { taprootTweakPrivKey } from \"@scure/btc-signer/utils\";\nimport { RPCError } from \"../../errors/index.js\";\nimport {\n getP2TRAddressFromPublicKey,\n getP2TRScriptFromPublicKey,\n} from \"../../utils/bitcoin.js\";\nimport { getNetwork, Network } from \"../../utils/network.js\";\n\n// Static keys for deterministic testing\n// P2TRAddress: bcrt1p2uy9zw5ltayucsuzl4tet6ckelzawp08qrtunacscsszflye907q62uqhl\nconst STATIC_FAUCET_KEY = hexToBytes(\n \"deadbeef1337cafe4242424242424242deadbeef1337cafe4242424242424242\",\n);\n\n// P2TRAddress: bcrt1pwr5k38p68ceyrnm2tvrp50dvmg3grh6uvayjl3urwtxejhd3dw4swz6p58\nconst STATIC_MINING_KEY = hexToBytes(\n \"1337cafe4242deadbeef4242424242421337cafe4242deadbeef424242424242\",\n);\nconst SATS_PER_BTC = 100_000_000;\n\nexport type FaucetCoin = {\n key: Uint8Array;\n outpoint: TransactionInput;\n txout: TransactionOutput;\n};\n\n// The amount of satoshis to put in each faucet coin to be used in tests\nconst COIN_AMOUNT = 10_000_000n;\nconst FEE_AMOUNT = 1000n;\nconst TARGET_NUM_COINS = 20;\n\nexport class BitcoinFaucet {\n private coins: FaucetCoin[] = [];\n private static instance: BitcoinFaucet | null = null;\n private miningAddress: string;\n private lock: Promise<void> = Promise.resolve();\n\n private constructor(\n private url: string = \"http://127.0.0.1:8332\",\n private username: string = \"testutil\",\n private password: string = \"testutilpassword\",\n ) {\n this.miningAddress = getP2TRAddressFromPublicKey(\n secp256k1.getPublicKey(STATIC_MINING_KEY),\n Network.LOCAL,\n );\n }\n\n static getInstance(\n url: string = \"http://127.0.0.1:8332\",\n username: string = \"testutil\",\n password: string = \"testutilpassword\",\n ): BitcoinFaucet {\n if (!BitcoinFaucet.instance) {\n BitcoinFaucet.instance = new BitcoinFaucet(url, username, password);\n }\n return BitcoinFaucet.instance;\n }\n\n private async withLock<T>(operation: () => Promise<T>): Promise<T> {\n const current = this.lock;\n let resolve: () => void;\n this.lock = new Promise<void>((r) => (resolve = r));\n await current;\n try {\n return await operation();\n } finally {\n resolve!();\n }\n }\n\n async fund(): Promise<FaucetCoin> {\n return this.withLock(async () => {\n if (this.coins.length === 0) {\n await this.refill();\n }\n\n const coin = this.coins[0];\n if (!coin) {\n throw new Error(\"Failed to get coin from faucet\");\n }\n this.coins = this.coins.slice(1);\n return coin;\n });\n }\n\n private async refill(): Promise<void> {\n const minerPubKey = secp256k1.getPublicKey(STATIC_MINING_KEY);\n const address = getP2TRAddressFromPublicKey(minerPubKey, Network.LOCAL);\n\n // Use scantxoutset to find UTXOs\n const scanResult = await this.call(\"scantxoutset\", [\n \"start\",\n [`addr(${address})`],\n ]);\n\n let selectedUtxo;\n let selectedUtxoAmountSats;\n if (!scanResult.success || scanResult.unspents.length === 0) {\n const blockHash = await this.generateToAddress(1, address);\n const block = await this.getBlock(blockHash[0]);\n const fundingTx = Transaction.fromRaw(hexToBytes(block.tx[0].hex), {\n allowUnknownOutputs: true,\n });\n\n await this.generateToAddress(100, this.miningAddress);\n\n selectedUtxo = {\n txid: block.tx[0].txid,\n vout: 0,\n amount: fundingTx.getOutput(0)!.amount!, // Already in sats\n };\n selectedUtxoAmountSats = BigInt(selectedUtxo.amount);\n } else {\n selectedUtxo = scanResult.unspents.find((utxo) => {\n const isValueEnough =\n BigInt(Math.floor(utxo.amount * SATS_PER_BTC)) >=\n COIN_AMOUNT + FEE_AMOUNT;\n const isMature = scanResult.height - utxo.height >= 100;\n return isValueEnough && isMature;\n });\n\n if (!selectedUtxo) {\n throw new Error(\"No UTXO large enough to create even one faucet coin\");\n }\n selectedUtxoAmountSats = BigInt(\n Math.floor(selectedUtxo.amount * SATS_PER_BTC),\n );\n }\n\n const maxPossibleCoins = Number(\n (selectedUtxoAmountSats - FEE_AMOUNT) / COIN_AMOUNT,\n );\n const numCoinsToCreate = Math.min(maxPossibleCoins, TARGET_NUM_COINS);\n\n if (numCoinsToCreate < 1) {\n throw new Error(\n `Selected UTXO (${selectedUtxoAmountSats} sats) is too small to create even one faucet coin of ${COIN_AMOUNT} sats`,\n );\n }\n\n const splitTx = new Transaction();\n splitTx.addInput({\n txid: selectedUtxo.txid,\n index: selectedUtxo.vout,\n });\n\n const faucetPubKey = secp256k1.getPublicKey(STATIC_FAUCET_KEY);\n const script = getP2TRScriptFromPublicKey(faucetPubKey, Network.LOCAL);\n for (let i = 0; i < numCoinsToCreate; i++) {\n splitTx.addOutput({\n script,\n amount: COIN_AMOUNT,\n });\n }\n\n const remainingValue =\n selectedUtxoAmountSats -\n COIN_AMOUNT * BigInt(numCoinsToCreate) -\n FEE_AMOUNT;\n const minerScript = getP2TRScriptFromPublicKey(minerPubKey, Network.LOCAL);\n if (remainingValue > 0n) {\n splitTx.addOutput({\n script: minerScript,\n amount: remainingValue,\n });\n }\n\n const signedSplitTx = await this.signFaucetCoin(\n splitTx,\n {\n amount: selectedUtxoAmountSats,\n script: minerScript,\n },\n STATIC_MINING_KEY,\n );\n\n await this.broadcastTx(bytesToHex(signedSplitTx.extract()));\n\n const splitTxId = signedSplitTx.id;\n for (let i = 0; i < numCoinsToCreate; i++) {\n this.coins.push({\n key: STATIC_FAUCET_KEY,\n outpoint: {\n txid: hexToBytes(splitTxId),\n index: i,\n },\n txout: signedSplitTx.getOutput(i)!,\n });\n }\n }\n\n async sendFaucetCoinToP2WPKHAddress(pubKey: Uint8Array) {\n const sendToPubKeyTx = new Transaction();\n\n // For P2WPKH, we need to hash the public key\n\n // Create a P2WPKH address\n const p2wpkhAddress = btc.p2wpkh(pubKey, getNetwork(Network.LOCAL)).address;\n if (!p2wpkhAddress) {\n throw new Error(\"Invalid P2WPKH address\");\n }\n\n // Get the coin to spend\n const coinToSend = await this.fund();\n if (!coinToSend) {\n throw new Error(\"No coins available\");\n }\n\n // Add the input\n sendToPubKeyTx.addInput(coinToSend.outpoint);\n\n // Add the output using the address directly, but subtract FEE_AMOUNT to ensure there's a fee\n sendToPubKeyTx.addOutputAddress(\n p2wpkhAddress,\n COIN_AMOUNT - FEE_AMOUNT,\n getNetwork(Network.LOCAL),\n );\n\n // Sign the transaction and get the signed result\n const signedTx = await this.signFaucetCoin(\n sendToPubKeyTx,\n coinToSend.txout,\n coinToSend.key,\n );\n\n // Broadcast the signed transaction\n await this.broadcastTx(bytesToHex(signedTx.extract()));\n }\n\n async signFaucetCoin(\n unsignedTx: Transaction,\n fundingTxOut: TransactionOutput,\n key: Uint8Array,\n ): Promise<Transaction> {\n const pubKey = secp256k1.getPublicKey(key);\n const internalKey = pubKey.slice(1); // Remove the 0x02/0x03 prefix\n\n const script = getP2TRScriptFromPublicKey(pubKey, Network.LOCAL);\n\n unsignedTx.updateInput(0, {\n tapInternalKey: internalKey,\n witnessUtxo: {\n script,\n amount: fundingTxOut.amount!,\n },\n });\n\n const sighash = unsignedTx.preimageWitnessV1(\n 0,\n new Array(unsignedTx.inputsLength).fill(script),\n SigHash.DEFAULT,\n new Array(unsignedTx.inputsLength).fill(fundingTxOut.amount!),\n );\n\n const merkleRoot = new Uint8Array();\n const tweakedKey = taprootTweakPrivKey(key, merkleRoot);\n if (!tweakedKey)\n throw new Error(\"Invalid private key for taproot tweaking\");\n\n const signature = schnorr.sign(sighash, tweakedKey);\n\n unsignedTx.updateInput(0, {\n tapKeySig: signature,\n });\n\n unsignedTx.finalize();\n\n return unsignedTx;\n }\n\n // MineBlocks mines the specified number of blocks to a random address\n // and returns the block hashes.\n async mineBlocks(numBlocks: number) {\n return await this.generateToAddress(numBlocks, this.miningAddress);\n }\n\n private async call(method: string, params: any[]) {\n try {\n const response = await fetch(this.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Basic \" + btoa(`${this.username}:${this.password}`),\n },\n body: JSON.stringify({\n jsonrpc: \"1.0\",\n id: \"spark-js\",\n method,\n params,\n }),\n });\n\n const data = await response.json();\n if (data.error) {\n console.error(`RPC Error for method ${method}:`, data.error);\n throw new RPCError(`Bitcoin RPC error: ${data.error.message}`, {\n method,\n params,\n code: data.error.code,\n });\n }\n\n return data.result;\n } catch (error) {\n if (error instanceof RPCError) {\n throw error;\n }\n throw new RPCError(\n \"Failed to call Bitcoin RPC\",\n {\n method,\n params,\n },\n error as Error,\n );\n }\n }\n\n async generateToAddress(numBlocks: number, address: string) {\n return await this.call(\"generatetoaddress\", [numBlocks, address]);\n }\n\n async getBlock(blockHash: string) {\n return await this.call(\"getblock\", [blockHash, 2]);\n }\n\n async broadcastTx(txHex: string) {\n let response = await this.call(\"sendrawtransaction\", [txHex, 0]);\n return response;\n }\n\n async getNewAddress(): Promise<string> {\n const key = secp256k1.utils.randomPrivateKey();\n const pubKey = secp256k1.getPublicKey(key);\n return getP2TRAddressFromPublicKey(pubKey, Network.LOCAL);\n }\n\n async sendToAddress(address: string, amount: bigint): Promise<Transaction> {\n const coin = await this.fund();\n if (!coin) {\n throw new Error(\"No coins available\");\n }\n\n const tx = new Transaction();\n tx.addInput(coin.outpoint);\n\n const availableAmount = COIN_AMOUNT - FEE_AMOUNT;\n\n const destinationAddress = Address(getNetwork(Network.LOCAL)).decode(\n address,\n );\n const destinationScript = OutScript.encode(destinationAddress);\n tx.addOutput({\n script: destinationScript,\n amount: amount,\n });\n\n const changeAmount = availableAmount - amount;\n if (changeAmount > 0) {\n const changeKey = secp256k1.utils.randomPrivateKey();\n const changePubKey = secp256k1.getPublicKey(changeKey);\n const changeScript = getP2TRScriptFromPublicKey(\n changePubKey,\n Network.LOCAL,\n );\n tx.addOutput({\n script: changeScript,\n amount: changeAmount,\n });\n }\n\n const signedTx = await this.signFaucetCoin(tx, coin.txout, coin.key);\n const txHex = bytesToHex(signedTx.extract());\n await this.broadcastTx(txHex);\n\n await this.generateToAddress(1, address);\n\n return signedTx;\n }\n\n async getRawTransaction(txid: string) {\n return await this.call(\"getrawtransaction\", [txid, 2]);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,oCAAoC;AAE7C,SAAS,QAAQ,yBAAyB;AAC1C;AAAA,EACE,cAAAA;AAAA,EACA,mBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,OACK;AACP,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,wBAAwB;AACjC,SAAS,gBAAgB;AACzB,SAAS,WAAAC,UAAS,aAAAC,kBAA8B;AAEhD,SAAS,UAAAC,eAAc;AACvB,SAAS,aAAa;AACtB,SAAS,UAAAC,eAAc;AACvB,SAAS,UAAAC,eAAc;;;ACjBvB;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,cAAc;;;ACNhB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAe5B,QAA8B;AAAA;;;ACf3B,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAa9BC,SAAyB;AAAA;;;ACbtB,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWtBC,SAA0B;AAAA;;;ACXzB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAoB3B,QAA6B;AAAA;;;ACpB1B,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAsBnCC,SAAqC;AAAA;;;ACvBlC,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAchCC,SAAkC;AAAA;;;ACb/B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAsB7BC,SAAyB;AAAA;;;ACtBtB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiBzBC,SAA6B;AAAA;;;ACjB5B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAc/BC,SAAkC;AAAA;;;ACd/B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYjCC,SAAmC;AAAA;;;ACZhC,IAAM,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYpCC,SAAsC;AAAA;;;ACZnC,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMvBC,UAAmB;AAAA;;;AZ8DvB,IAAqB,YAArB,MAA+B;AAAA,EACZ;AAAA,EAEA;AAAA,EACA;AAAA,EAEjB,YACE,QAGA;AACA,SAAK,SAAS,OAAO;AACrB,SAAK,eAAe,IAAI,kBAAkB;AAE1C,UAAM,gBACJ,OAAO,WAAW,cAAc,OAAO,MAAM,KAAK,MAAM,IAAI;AAC9D,UAAM,UAAU,OAAO;AAEvB,SAAK,YAAY,IAAI;AAAA,MACnB,IAAI,aAAa,aAAa;AAAA,MAC9B,QAAQ,kBAAkB;AAAA,MAC1B;AAAA,MACA,KAAK;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,OACA,YAAqB,MACF;AACnB,QAAI,aAAa,CAAE,MAAM,KAAK,aAAa,aAAa,GAAI;AAC1D,YAAM,KAAK,aAAa;AAAA,IAC1B;AAEA,QAAI;AACF,aAAO,MAAM,KAAK,UAAU,aAAa,KAAK;AAAA,IAChD,SAAS,OAAO;AACd,UACE,iBAAiB,SACjB,MAAM,QAAQ,YAAY,EAAE,SAAS,cAAc,GACnD;AACA,YAAI;AACF,gBAAM,KAAK,aAAa;AACxB,iBAAO,MAAM,KAAK,UAAU,aAAa,KAAK;AAAA,QAChD,SAAS,WAAW;AAClB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,cACE,UAAU;AAAA,cACV,QAAQ,MAAM;AAAA,YAChB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,YAC6C;AAC7C,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,mBAAmB;AAAA,MACrB;AAAA,MACA,iBAAiB,CAAC,aAAgD;AAChE,eAAO;AAAA,UACL,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,4BACJ,gBACgD;AAChD,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,iBAAiB;AAAA,MACnB;AAAA,MACA,iBAAiB,CAAC,aAAmD;AACnE,eAAO;AAAA,UACL,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,EACF,GAA0E;AACxE,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,mBAAmB;AAAA,QACnB,oBAAoB;AAAA,MACtB;AAAA,MACA,iBAAiB,CAAC,aAA+C;AAC/D,eAAO;AAAA,UACL,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,iBAAiB;AACrB,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AAAA,EAEA,MAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,EACF,GAA2D;AACzD,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,oCAAoC;AAAA,QACpC,sBAAsB;AAAA,MACxB;AAAA,MACA,iBAAiB,CAAC,aAA0C;AAC1D,eAAO,wBAAwB,SAAS,mBAAmB,OAAO;AAAA,MACpE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA0D;AACxD,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,mBAAmB;AAAA,QACnB,oBAAoB;AAAA,QACpB,iBAAiB;AAAA,QACjB,YAAY;AAAA,MACd;AAAA,MACA,iBAAiB,CAAC,aAAyC;AACzD,eAAO,wBAAwB,SAAS,kBAAkB,OAAO;AAAA,MACnE;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,wBAAwB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA0E;AACxE,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,aAAa;AAAA,QACb;AAAA,QACA,cAAc;AAAA,QACd,aAAa;AAAA,QACb;AAAA,MACF;AAAA,MACA,iBAAiB,CAAC,aAAiD;AACjE,eAAO;AAAA,UACL,SAAS,0BAA0B;AAAA,QACrC;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,EACF,GAAoE;AAClE,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,MACnB;AAAA,MACA,iBAAiB,CAAC,aAA8C;AAC9D,eAAO;AAAA,UACL,SAAS,uBAAuB;AAAA,QAClC;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA8D;AAC5D,UAAM,QAAQ;AAAA,MACZ,cAAc;AAAA,MACd,WAAW;AAAA,QACT,gBAAgB;AAAA,QAChB,mBAAmB;AAAA,QACnB,oBAAoB;AAAA,QACpB,UAAU;AAAA,QACV,aAAa;AAAA,QACb,iBAAiB;AAAA,MACnB;AAAA,MACA,iBAAiB,CAAC,aAA2C;AAC3D,YAAI,CAAC,SAAS,qBAAqB;AACjC,iBAAO;AAAA,QACT;AAEA,eAAO,0BAA0B,SAAS,oBAAoB,OAAO;AAAA,MACvE;AAAA,IACF;AACA,WAAO,MAAM,KAAK,gBAAgB,KAAK;AAAA,EACzC;AAAA,EAEA,MAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA+D;AAC7D,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,oCAAoC;AAAA,QACpC,wBAAwB;AAAA,MAC1B;AAAA,MACA,iBAAiB,CAAC,aAA4C;AAC5D,eAAO,0BAA0B,SAAS,qBAAqB,OAAO;AAAA,MACxE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,2BACJ,IACyC;AACzC,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,iBAAiB,CAAC,aAAoC;AACpD,YAAI,CAAC,SAAS,cAAc;AAC1B,iBAAO;AAAA,QACT;AAEA,eAAO,gCAAgC,SAAS,YAAY;AAAA,MAC9D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,wBACJ,IACsC;AACtC,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,iBAAiB,CAAC,aAAoC;AACpD,YAAI,CAAC,SAAS,cAAc;AAC1B,iBAAO;AAAA,QACT;AAEA,eAAO,6BAA6B,SAAS,YAAY;AAAA,MAC3D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,oBAAoB,IAA+C;AACvE,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,iBAAiB,CAAC,aAAoC;AACpD,YAAI,CAAC,SAAS,cAAc;AAC1B,iBAAO;AAAA,QACT;AAEA,eAAO,0BAA0B,SAAS,YAAY;AAAA,MACxD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,mBAAmB,IAA6C;AACpE,WAAO,MAAM,KAAK,gBAAgB;AAAA,MAChC,cAAc;AAAA,MACd,WAAW;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,iBAAiB,CAAC,aAAoC;AACpD,YAAI,CAAC,SAAS,cAAc;AAC1B,iBAAO;AAAA,QACT;AAEA,eAAO,wBAAwB,SAAS,YAAY;AAAA,MACtD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eAAmD;AACvD,WAAO,MAAM,KAAK;AAAA,MAChB;AAAA,QACE,cAAc;AAAA,QACd,WAAW;AAAA,UACT,YAAY,WAAW,MAAM,KAAK,OAAO,qBAAqB,CAAC;AAAA,QACjE;AAAA,QACA,iBAAiB,CAAC,aAAqC;AACrD,iBAAO,2BAA2B,SAAS,aAAa;AAAA,QAC1D;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,WACA,oBACuC;AACvC,WAAO,MAAM,KAAK;AAAA,MAChB;AAAA,QACE,cAAc;AAAA,QACd,WAAW;AAAA,UACT,qBAAqB;AAAA,UACrB;AAAA,UACA,qBAAqB;AAAA,YACnB,MAAM,KAAK,OAAO,qBAAqB;AAAA,UACzC;AAAA,QACF;AAAA,QACA,iBAAiB,CAAC,aAAkB;AAClC,iBAAO,8BAA8B,SAAS,gBAAgB;AAAA,QAChE;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe;AACnB,SAAK,aAAa,WAAW;AAE7B,UAAM,YAAY,MAAM,KAAK,aAAa;AAC1C,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,iBAAiB,OAAO,KAAK,UAAU,oBAAoB,QAAQ;AACzE,UAAM,YAAY,MAAM,KAAK,OAAO;AAAA,MAClC,OAAO,cAAc;AAAA,IACvB;AAEA,UAAM,kBAAkB,MAAM,KAAK;AAAA,MACjC,OAAO,KAAK,SAAS,EAAE,SAAS,QAAQ;AAAA,MACxC,UAAU;AAAA,IACZ;AACA,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,SAAK,aAAa;AAAA,MAChB,gBAAgB;AAAA,MAChB,IAAI,KAAK,gBAAgB,UAAU;AAAA,IACrC;AAAA,EACF;AACF;AAEA,IAAM,oBAAN,MAAgD;AAAA,EACtC;AAAA,EACA;AAAA,EAER,MAAM,eACJ,SACiC;AACjC,UAAM,WAAW;AAAA,MACf,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACL;AAEA,QAAI,KAAK,cAAc;AACrB,eAAS,eAAe,IAAI,UAAU,KAAK,YAAY;AAAA,IACzD;AAEA,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EACjC;AAAA,EAEA,MAAM,eAAiC;AACrC,WACE,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,KAAK,cAAc,KAAK,aAAa,oBAAI,KAAK;AAAA,EAE3E;AAAA,EAEA,MAAM,sBACJ,QACkC;AAClC,UAAM,UAAU;AAAA,MACd,GAAG;AAAA,IACL;AAEA,QAAI,KAAK,cAAc;AACrB,cAAQ,eAAe,IAAI,UAAU,KAAK,YAAY;AAAA,IACxD;AAEA,WAAO,QAAQ,QAAQ,OAAO;AAAA,EAChC;AAAA,EAEA,QAAQ,cAAsB,YAAkB;AAC9C,SAAK,eAAe;AACpB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,aAAa;AACX,SAAK,eAAe;AACpB,SAAK,aAAa;AAAA,EACpB;AACF;;;AarfA,SAAS,eAAAC,oBAAmB;AAE5B,SAAS,UAAAC,eAAc;;;ACFvB;AAAA,EACE,cAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAE5B,SAAS,UAAAC,eAAc;AACvB,YAAY,WAAW;AACvB,SAAS,cAAc;AAyCvB,IAAM,oBAAoB;AAE1B,IAAM,sBAAsB,KAAK,KAAK;AAEtC,SAAS,kBAAkB;AACzB,SAAQ,KAAK,KAAM;AACrB;AAEA,IAAM,SAAS,UAAU;AAyBlB,IAAM,sBAAN,MAA0B;AAAA,EACZ;AAAA,EACA;AAAA,EAEnB,YACE,QACA,mBACA;AACA,SAAK,SAAS;AACd,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,MAAM,qBACJ,UACA,QACA,oBACmB;AACnB,UAAM,mBAAmB,MAAM,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AAEJ,UAAM,sBACJ,KAAK,OAAO,oBAAoB,EAAE,KAAK,OAAO,yBAAyB,CAAC;AAC1E,QAAI,CAAC,qBAAqB;AACxB,YAAM,IAAI,gBAAgB,kCAAkC;AAAA,QAC1D,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,eAAW,CAAC,YAAY,QAAQ,KAAK,OAAO;AAAA,MAC1C,KAAK,OAAO,oBAAoB;AAAA,IAClC,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,KAAK,OAAO,sBAAsB,CAAC,GAAG;AACzE,wBAAkB,MAAM,KAAK;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,sBAAkB,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA,KAAK,OAAO,yBAAyB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO,OAAO,KAAK,KAAK,OAAO,oBAAoB,CAAC,EAAE;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,iBACZ,UACA,YACA,kBACA,UACA,iBACA;AACA,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,SAAS;AAAA,IACX;AAEA,UAAM,eAAe,iBAAiB,IAAI,UAAU;AACpD,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,gBAAgB,kCAAkC;AAAA,QAC1D,OAAO;AAAA,QACP,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,QAAI;AACJ,QAAI;AACF,qBAAe,MAAM,YAAY,kBAAkB;AAAA,QACjD,YAAY,SAAS;AAAA,QACrB,wBAAwB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QACtE;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB;AACpB,wBAAkB,aAAa;AAAA,IACjC,OAAO;AACL,UAAI,CAAC,aAAa,UAAU;AAC1B,cAAM,IAAI,gBAAgB,sCAAsC;AAAA,UAC9D,OAAO;AAAA,UACP,OAAO,SAAS;AAAA,QAClB,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,iBAAiB,iBAAiB,aAAa,QAAQ,GAAG;AAClE,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO,SAAS;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YACJ,aACA,wBACA,eAC2B;AAC3B,UAAM,iBAAmC,CAAC;AAC1C,eAAW,yBAAyB,wBAAwB;AAC1D,YAAM,WAAW,YAAY,IAAI,sBAAsB,MAAM;AAC7D,UACE,CAAC,YACD,CAAC,SAAS,MACV,SAAS,SAAS,UAClB,CAAC,SAAS,UACV;AACA,cAAM,IAAI;AAAA,UACR,gCAAgC,sBAAsB,MAAM;AAAA,QAC9D;AAAA,MACF;AAEA,YAAM,WAAW,SAAS,IAAI,UAAU,CAAC;AACzC,UAAI,CAAC,UAAU;AACb,cAAM,IAAI;AAAA,UACR,6BAA6B,sBAAsB,MAAM;AAAA,QAC3D;AAAA,MACF;AAEA,YAAM,kBAAkB,iBAAiB,SAAS,UAAU,GAAG,QAAQ;AAEvE,YAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,QACvD,SAAS;AAAA,QACT,WAAW,SAAS;AAAA,QACpB,iBAAiB,SAAS;AAAA,QAC1B,gBAAgB,SAAS;AAAA,QACzB,uBACE,sBAAsB,uBAAuB;AAAA,QAC/C;AAAA,QACA,cAAc,sBAAsB;AAAA,MACtC,CAAC;AAED,YAAM,kBAAkB,MAAM,KAAK,OAAO,OAAO,eAAe;AAAA,QAC9D,SAAS;AAAA,QACT,sBACE,sBAAsB,uBAAuB;AAAA,QAC/C,sBACE,sBAAsB,uBAAuB;AAAA,QAC/C,cAAc,sBAAsB;AAAA,QACpC,uBACE,sBAAsB,uBAAuB;AAAA,QAC/C,gBAAgB,SAAS;AAAA,QACzB,WAAW,SAAS;AAAA,QACpB,eAAe;AAAA,QACf;AAAA,MACF,CAAC;AAED,qBAAe,KAAK;AAAA,QAClB,QAAQ,sBAAsB;AAAA,QAC9B,mBAAmB;AAAA,QACnB,iBAAiB,IAAI,WAAW;AAAA,MAClC,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,6BACZ,UACA,QACA,oBAC0C;AAC1C,UAAM,sBAA4B,gBAAU;AAAA,MAC1CC,YAAW,SAAS,yBAAyB;AAAA,IAC/C;AAEA,UAAM,kBAAkB,oBAAI,IAAgC;AAE5D,eAAW,QAAQ,QAAQ;AACzB,YAAM,kBAAkB,mBAAmB,IAAI,KAAK,KAAK,EAAE;AAC3D,YAAM,gBAAgB,MAAM,KAAK;AAAA,QAC/B,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,iBAAW,CAAC,YAAY,SAAS,KAAK,eAAe;AACnD,wBAAgB,IAAI,YAAY;AAAA,UAC9B,GAAI,gBAAgB,IAAI,UAAU,KAAK,CAAC;AAAA,UACxC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,kCACZ,YACA,MACA,qBACA,iBACwC;AACxC,UAAM,mBAAmB,KAAK,OAAO,oBAAoB;AACzD,UAAM,cACJ,MAAM,KAAK,OAAO,OAAO;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEF,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO,sBAAsB;AAAA,MAC5D,QAAQ;AAAA,MACR,YAAY,UAAU,MAAM;AAAA,MAC5B,WAAW,KAAK,OAAO,aAAa;AAAA,MACpC,WAAW,OAAO,KAAK,gBAAgB,EAAE;AAAA,MACzC,gBAAgB;AAAA,IAClB,CAAC;AAED,UAAM,oBAAoB,oBAAI,IAAwB;AACtD,eAAW,CAAC,YAAY,QAAQ,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACrE,YAAM,QAAQ,KAAK,UAAU,QAAQ,SAAS,EAAE;AAChD,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,gCAAgC,SAAS,EAAE,EAAE;AAAA,MAC/D;AAEA,YAAM,cAAc,UAAU;AAAA,QAC5B,gBAAgB,MAAM,OAAO,EAAE;AAAA,QAC/B;AAAA,MACF;AACA,wBAAkB,IAAI,YAAY,WAAW;AAAA,IAC/C;AAEA,UAAM,eAAe,MAAM,KAAK,OAAO,OAAO;AAAA,MAC5C,oBAAoB,QAAQ;AAAA,MAC5B,KAAK;AAAA,IACP;AAEA,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,UAAU,IAAI,WAAW;AAAA,MAC7B,GAAG,QAAQ,OAAO,KAAK,KAAK,EAAE;AAAA,MAC9B,GAAG,QAAQ,OAAO,UAAU;AAAA,MAC5B,GAAG;AAAA,IACL,CAAC;AAED,UAAM,cAAcC,QAAO,OAAO;AAClC,UAAM,YAAY,MAAM,KAAK,OAAO,OAAO;AAAA,MACzC;AAAA,MACA;AAAA,IACF;AAEA,UAAM,gBAAgB,oBAAI,IAA8B;AACxD,eAAW,CAAC,YAAY,QAAQ,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACrE,YAAM,QAAQ,KAAK,UAAU,QAAQ,SAAS,EAAE;AAChD,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,gCAAgC,SAAS,EAAE,EAAE;AAAA,MAC/D;AAEA,oBAAc,IAAI,YAAY;AAAA,QAC5B,QAAQ,KAAK,KAAK;AAAA,QAClB,kBAAkB;AAAA,UAChB,aAAa,gBAAgB,MAAM,OAAO,EAAE;AAAA,UAC5C,QAAQ,MAAM;AAAA,QAChB;AAAA,QACA,mBAAmB,OAAO,YAAY,iBAAiB;AAAA,QACvD;AAAA,QACA;AAAA,QACA,iBAAiB,mBAAmB,IAAI,WAAW;AAAA,MACrD,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEU,UAAU,QAAiC,YAAoB;AACvE,UAAM,mBAAmB,OAAO,aAAa,CAAC;AAC9C,eAAW,KAAK,QAAQ;AACtB,UAAI,EAAE,UAAU,kBAAkB;AAChC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,WAAqB,WAAqB;AACjE,WACE,UAAU,OAAO,UAAU,MAC3B;AAAA,MACE,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,KACA,UAAU,WAAW,UAAU,UAC/B,UAAU,eAAe,UAAU,cACnC,UAAU,YAAY,QAAQ,MAAM,UAAU,YAAY,QAAQ,KAClE,UAAU,OAAO,WAAW,UAAU,OAAO;AAAA,EAEjD;AACF;AAEO,IAAM,kBAAN,cAA8B,oBAAoB;AAAA,EACvD,YACE,QACA,mBACA;AACA,UAAM,QAAQ,iBAAiB;AAAA,EACjC;AAAA,EAEA,MAAM,aACJ,QACA,wBACmB;AACnB,UAAM,EAAE,UAAU,aAAa,IAAI,MAAM,KAAK;AAAA,MAC5C;AAAA,MACA;AAAA,MACA,IAAI,KAAK,KAAK,IAAI,IAAI,mBAAmB;AAAA,IAC3C;AAEA,UAAM,0BAA0B,MAAM,KAAK;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,UAAoB,QAAwB;AAC9D,QAAI;AACJ,QAAI,SAAS,uDAA8D;AACzE,iBAAW,MAAM,KAAK,uBAAuB,UAAU,MAAM;AAAA,IAC/D;AACA,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,uBAAuB,UAAU;AAAA,EACrD;AAAA,EAEA,MAAM,wBAAyD;AAC7D,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AACA,QAAI;AACJ,QAAI;AACF,6BAAuB,MAAM,YAAY,wBAAwB;AAAA,QAC/D,aAAa;AAAA,UACX,OAAO;AAAA,UACP,2BACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QAClD;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,qCAAqC,KAAK,EAAE;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,kBACJ,OACA,QACiC;AACjC,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI;AACF,yBAAmB,MAAM,YAAY,oBAAoB;AAAA,QACvD,aAAa;AAAA,UACX,OAAO;AAAA,UACP,mCACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QAClD;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA;AAAA;AAAA;AAAA,QAIP;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,iCAAiC,KAAK,EAAE;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,sBACJ,UACkC;AAClC,UAAM,gBAAgB,oBAAI,IAAwB;AAClD,eAAW,QAAQ,SAAS,QAAQ;AAClC,UAAI,CAAC,KAAK,MAAM;AACd,cAAM,IAAI,MAAM,mBAAmB;AAAA,MACrC;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,YAAM,cAAc,QAAQ,OAAO,KAAK,KAAK,EAAE;AAC/C,YAAM,kBAAkB,QAAQ,OAAO,SAAS,EAAE;AAElD,YAAM,UAAU,IAAI,WAAW;AAAA,QAC7B,GAAG;AAAA,QACH,GAAG;AAAA,QACH,GAAG,KAAK;AAAA,MACV,CAAC;AAED,YAAM,cAAcA,QAAO,OAAO;AAClC,UACE,CAAC,UAAU;AAAA,QACT,KAAK;AAAA,QACL;AAAA,QACA,SAAS;AAAA,MACX,GACA;AACA,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,YAAM,aAAa,MAAM,KAAK,OAAO,OAAO;AAAA,QAC1C,KAAK;AAAA,MACP;AAEA,oBAAc,IAAI,KAAK,KAAK,IAAI,UAAU;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,uBACJ,QACA,wBACA,YAKC;AACD,UAAM,EAAE,UAAU,cAAc,YAAY,IAC1C,MAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEF,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,oBACJ,QACA,wBACA,YAKC;AACD,UAAM,EAAE,UAAU,cAAc,YAAY,IAC1C,MAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEF,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,sBACJ,QACA,wBACA,YACA,eAMC;AACD,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,+BACJ,QACA,wBACA,YACA,SACA,eAMC;AACD,UAAM,aAAa,OAAO;AAC1B,UAAM,cAAc,oBAAI,IAAmC;AAC3D,eAAW,QAAQ,QAAQ;AACzB,YAAM,yBACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAEtD,YAAM,KAAK,oBAAoB,KAAK,KAAK,MAAM;AAC/C,YAAM,WAAW,oBAAoB,KAAK,KAAK,QAAQ;AACvD,kBAAY,IAAI,KAAK,KAAK,IAAI;AAAA,QAC5B,eAAe,KAAK;AAAA,QACpB,iBAAiB;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,KAAK,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,KAAK,2BAA2B,QAAQ,WAAW;AAEvE,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI;AACF,UAAI,kBAAkB,QAAW;AAC/B,mBAAW,MAAM,YAAY,kBAAkB;AAAA,UAC7C,UAAU;AAAA,YACR;AAAA,YACA,cAAc;AAAA,YACd,wBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,YAChD,2BAA2B;AAAA,YAC3B;AAAA,UACF;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,kBAAkB,iBAAiB,IAAI,WAAW;AAAA,QACpD,CAAC;AAAA,MACH,WAAW,SAAS;AAClB,mBAAW,MAAM,YAAY,gBAAgB;AAAA,UAC3C;AAAA,UACA,cAAc;AAAA,UACd,wBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,UAChD,2BAA2B;AAAA,UAC3B;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,mBAAW,MAAM,YAAY,eAAe;AAAA,UAC1C;AAAA,UACA,cAAc;AAAA,UACd,wBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,UAChD,2BAA2B;AAAA,UAC3B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,iCAAiC,KAAK,EAAE;AAAA,IAC1D;AAEA,QAAI,CAAC,SAAS,UAAU;AACtB,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAEA,UAAM,eAAe,oBAAI,IAAwB;AACjD,eAAW,aAAa,YAAY;AAClC,mBAAa,IAAI,UAAU,QAAQ,UAAU,iBAAiB;AAAA,IAChE;AAEA,WAAO;AAAA,MACL,UAAU,SAAS;AAAA,MACnB;AAAA,MACA;AAAA,MACA,gBAAgB,SAAS;AAAA,IAC3B;AAAA,EACF;AAAA,EAEQ,2BACN,QACA,aACA,YAC0B;AAC1B,UAAM,cAAwC,CAAC;AAC/C,eAAW,QAAQ,QAAQ;AACzB,YAAM,oBAAoB,YAAY,IAAI,KAAK,KAAK,EAAE;AACtD,UAAI,CAAC,mBAAmB;AACtB,cAAM,IAAI,MAAM,gCAAgC,KAAK,KAAK,EAAE,EAAE;AAAA,MAChE;AAEA,YAAM,SAAS,oBAAoB,KAAK,KAAK,MAAM;AACnD,YAAM,eAAiC;AAAA,QACrC,MAAM,WAAW,QAAQ,MAAM,CAAC;AAAA,QAChC,OAAO;AAAA,MACT;AAEA,YAAM,eAAe,oBAAoB,KAAK,KAAK,QAAQ;AAC3D,YAAM,eAAe,aACjB,uBAAuB,aAAa,SAAS,CAAC,EAAE,QAAQ,IACxD,2BAA2B,aAAa,SAAS,CAAC,EAAE,QAAQ,EACzD;AAEP,YAAM,aAAa,aAAa,UAAU,CAAC,EAAE;AAC7C,UAAI,eAAe,QAAW;AAC5B,cAAM,IAAI,MAAM,iCAAiC;AAAA,MACnD;AAEA,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB;AAAA,QAClB,KAAK,OAAO,WAAW;AAAA,MACzB;AAEA,wBAAkB,WAAW;AAE7B,YAAM,6BACJ,kBAAkB;AAEpB,kBAAY,KAAK;AAAA,QACf,QAAQ,KAAK,KAAK;AAAA,QAClB,oBAAoB;AAAA,UAClB,kBAAkB,kBAAkB;AAAA,UACpC,OAAO,SAAS,QAAQ;AAAA,UACxB,wBAAwB;AAAA,QAC1B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,uBACJ,UACA,QACoC;AACpC,UAAM,EAAE,aAAa,iBAAiB,SAAS,IAC7C,MAAM,KAAK,4BAA4B,MAAM;AAE/C,UAAM,SAAkB,CAAC;AAEzB,UAAM,WAAW,OAAO,QAAQ,KAAK,OAAO,oBAAoB,CAAC,EAAE;AAAA,MACjE,OAAO,CAAC,YAAY,QAAQ,MAAM;AAChC,cAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,UAC/C,SAAS;AAAA,QACX;AAEA,cAAM,kBAAkB,gBAAgB,IAAI,UAAU;AACtD,YAAI,CAAC,iBAAiB;AACpB,iBAAO;AAAA,YACL,IAAI,gBAAgB,qCAAqC;AAAA,cACvD,OAAO;AAAA,cACP,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AACA;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,YAAY,0BAA0B;AAAA,YAC1C,YAAY,SAAS;AAAA,YACrB,wBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,YAChD;AAAA,UACF,CAAC;AAAA,QACH,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,IAAI;AAAA,cACF;AAAA,cACA;AAAA,gBACE,QAAQ;AAAA,cACV;AAAA,cACA;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,QAAQ;AAE1B,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,YAAY,OAAO;AAAA,UACnB,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;AAAA,QAChD;AAAA,QACA,OAAO,CAAC;AAAA,MACV;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,4BAA4B,QAGvC;AACD,UAAM,cAAc,oBAAI,IAAiC;AACzD,UAAM,WAAW,oBAAI,IAA0B;AAC/C,eAAW,QAAQ,QAAQ;AACzB,YAAM,EAAE,eAAe,UAAU,OAAO,IACtC,MAAM,KAAK,0BAA0B,IAAI;AAC3C,eAAS,IAAI,KAAK,KAAK,IAAI,MAAM;AAEjC,iBAAW,CAAC,YAAY,SAAS,KAAK,UAAU;AAC9C,oBAAY,IAAI,YAAY;AAAA,UAC1B,GAAI,YAAY,IAAI,UAAU,KAAK,CAAC;AAAA,UACpC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,EAAE,aAAa,SAAS;AAAA,EACjC;AAAA,EAEA,MAAc,0BAA0B,MAGrC;AACD,UAAM,mBAAmB,KAAK,OAAO,oBAAoB;AAEzD,UAAM,cACJ,MAAM,KAAK,OAAO,OAAO;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEF,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO,sBAAsB;AAAA,MAC5D,QAAQ;AAAA,MACR,YAAY,UAAU,MAAM;AAAA,MAC5B,WAAW,KAAK,OAAO,aAAa;AAAA,MACpC,WAAW,OAAO,KAAK,gBAAgB,EAAE;AAAA,MACzC,gBAAgB;AAAA,IAClB,CAAC;AAED,UAAM,oBAAoB,oBAAI,IAAwB;AAEtD,eAAW,CAAC,YAAY,QAAQ,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACrE,YAAM,QAAQ,KAAK,UAAU,QAAQ,SAAS,EAAE;AAChD,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,gCAAgC,SAAS,EAAE,EAAE;AAAA,MAC/D;AACA,YAAM,cAAc,UAAU;AAAA,QAC5B,gBAAgB,MAAM,OAAO,EAAE;AAAA,MACjC;AACA,wBAAkB,IAAI,YAAY,WAAW;AAAA,IAC/C;AAEA,UAAM,gBAAgB,oBAAI,IAA+B;AACzD,eAAW,CAAC,YAAY,QAAQ,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACrE,YAAM,QAAQ,KAAK,UAAU,QAAQ,SAAS,EAAE;AAChD,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,gCAAgC,SAAS,EAAE,EAAE;AAAA,MAC/D;AAEA,oBAAc,IAAI,YAAY;AAAA,QAC5B,QAAQ,KAAK,KAAK;AAAA,QAClB,kBAAkB;AAAA,UAChB,aAAa,gBAAgB,MAAM,OAAO,EAAE;AAAA,UAC5C,QAAQ,MAAM;AAAA,QAChB;AAAA,QACA,mBAAmB,OAAO,YAAY,iBAAiB;AAAA,MACzD,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,OAAO,CAAC,GAAG,QAAQ;AACtB,YAAM,IAAI,gBAAgB,oBAAoB;AAAA,QAC5C,OAAO;AAAA,QACP,OAAO,OAAO,CAAC,GAAG;AAAA,MACpB,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,eAAe,eAAe,QAAQ,OAAO,CAAC,EAAE,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,yBACJ,UACA,UACA,UAC2B;AAC3B,UAAM,cAAkD,oBAAI,IAAI;AAChE,eAAW,WAAW,UAAU;AAC9B,YAAM,KAAK,oBAAoB,QAAQ,KAAK,MAAM;AAClD,kBAAY,IAAI,QAAQ,KAAK,IAAI;AAAA,QAC/B,eAAe,QAAQ;AAAA,QACvB,iBAAiB,QAAQ;AAAA,QACzB,wBACE,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAAA,QACtD;AAAA,QACA,MAAM,QAAQ,KAAK;AAAA,MACrB,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AACA,QAAI;AAEJ,UAAM,iBAAiD,CAAC;AACxD,QAAI,UAAU;AACZ,iBAAW,CAAC,QAAQ,KAAK,KAAK,SAAS,QAAQ,GAAG;AAChD,uBAAe,MAAM,IAAI;AAAA,UACvB,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AACA,QAAI;AACF,aAAO,MAAM,YAAY,4BAA4B;AAAA,QACnD,YAAY,SAAS;AAAA,QACrB,wBAAwB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QACtE;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,yCAAyC,KAAK,EAAE;AAAA,IAClE;AACA,WAAO,KAAK,YAAY,aAAa,KAAK,cAAc;AAAA,EAC1D;AAAA,EAEA,MAAc,uBAAuB,gBAAkC;AACrE,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AACA,QAAI;AACF,aAAO,MAAM,YAAY,yBAAyB;AAAA,QAChD;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,iDAAiD,KAAK,EAAE;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,UACA,iBAC+B;AAC/B,UAAM,cACJ,MAAM,KAAK,kBAAkB,kBAAkB,eAAe;AAEhE,QAAI;AACF,YAAM,WAAW,MAAM,YAAY,gBAAgB;AAAA,QACjD,YAAY,SAAS;AAAA,QACrB,yBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MAClD,CAAC;AAED,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,8BACJ,iBACiC;AACjC,UAAM,cACJ,MAAM,KAAK,kBAAkB,kBAAkB,eAAe;AAChE,QAAI;AACF,aAAO,MAAM,YAAY,wBAAwB;AAAA,QAC/C,aAAa;AAAA,UACX,OAAO;AAAA,UACP,yBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QAClD;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,+CAA+C,KAAK,EAAE;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,qBACJ,OACA,YACA,eACA;AACA,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,MAAM,qBAAqB;AAAA,IACnC;AAEA,UAAM,cAA4B,CAAC;AACnC,UAAM,aAA4B,CAAC;AAEnC,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,CAAC,MAAM;AACT,cAAM,MAAM,oBAAoB;AAAA,MAClC;AACA,YAAM,SAAS,oBAAoB,MAAM,MAAM;AAC/C,YAAM,QAAQ,OAAO,SAAS,CAAC;AAE/B,UAAI,CAAC,OAAO;AACV,cAAM,MAAM,0BAA0B;AAAA,MACxC;AAEA,YAAM,QAAQ,IAAI,YAAY,EAAE,qBAAqB,KAAK,CAAC;AAC3D,eAAS,IAAI,GAAG,IAAI,OAAO,eAAe,KAAK;AAC7C,cAAM,UAAU,OAAO,UAAU,CAAC,CAAC;AAAA,MACrC;AACA,UAAI,MAAM,GAAG;AACX,cAAM,eAAe,MAAM;AAE3B,cAAM,SAAS;AAAA,UACb,GAAG;AAAA,UACH,UAAU,2BAA2B,YAAY,EAAE;AAAA,QACrD,CAAC;AAAA,MACH,OAAO;AACL,cAAM,SAAS;AAAA,UACb,GAAG;AAAA,UACH,UAAU,gBAAgB;AAAA,UAC1B,MAAM,WAAW,IAAI,CAAC,GAAG;AAAA,QAC3B,CAAC;AAAA,MACH;AAEA,kBAAY,KAAK;AAAA,QACf,kBAAkB;AAAA,QAClB,OAAO,MAAM,QAAQ;AAAA,QACrB,wBACE,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAAA,MACxD,CAAC;AACD,iBAAW,CAAC,IAAI;AAAA,IAClB;AAEA,UAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,QAAI,CAAC,MAAM,UAAU;AACnB,YAAM,MAAM,8BAA8B;AAAA,IAC5C;AACA,UAAM,WAAW,oBAAoB,MAAM,QAAQ;AACnD,UAAM,cAAc,IAAI,YAAY,EAAE,qBAAqB,KAAK,CAAC;AAEjE,aAAS,IAAI,GAAG,IAAI,SAAS,eAAe,KAAK;AAC/C,kBAAY,UAAU,SAAS,UAAU,CAAC,CAAC;AAAA,IAC7C;AAEA,UAAM,gBAAgB,SAAS,SAAS,CAAC;AACzC,QAAI,CAAC,eAAe;AAClB,YAAM,MAAM,8BAA8B;AAAA,IAC5C;AAEA,QAAI,CAAC,WAAW,WAAW,SAAS,CAAC,GAAG;AACtC,YAAM,MAAM,4BAA4B;AAAA,IAC1C;AACA,gBAAY,SAAS;AAAA,MACnB,GAAG;AAAA,MACH,UAAU,gBAAgB;AAAA,MAC1B,MAAM,QAAQ,WAAW,WAAW,SAAS,CAAC,CAAE;AAAA,IAClD,CAAC;AAED,UAAM,mBAAmB;AAAA,MACvB,kBAAkB;AAAA,MAClB,OAAO,YAAY,QAAQ;AAAA,MAC3B,wBACE,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAAA,IACxD;AAEA,gBAAY,KAAK,gBAAgB;AAEjC,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,UAAM,WAAW,MAAM,YAAY,iBAAiB;AAAA,MAClD,QAAQ,KAAK;AAAA,MACb,wBAAwB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACtE;AAAA,IACF,CAAC;AAED,QAAI,YAAY,WAAW,SAAS,eAAe,QAAQ;AACzD,YAAM;AAAA,QACJ,4DAA4D,YAAY,MAAM,QAAQ,SAAS,eAAe,MAAM;AAAA,MACtH;AAAA,IACF;AAEA,QAAI,iBAAmC,CAAC;AACxC,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,aAAS,IAAI,GAAG,IAAI,SAAS,eAAe,QAAQ,KAAK;AACvD,YAAM,gBAAgB,SAAS,eAAe,CAAC;AAC/C,YAAM,aAAa,YAAY,CAAC;AAChC,UAAI,CAAC,cAAc,CAAC,eAAe;AACjC,cAAM,MAAM,4BAA4B;AAAA,MAC1C;AAEA,UAAI,CAAC,WAAW,wBAAwB;AACtC,cAAM,MAAM,iCAAiC;AAAA,MAC/C;AACA,YAAM,QAAQ,oBAAoB,WAAW,KAAK;AAElD,UAAI;AACJ,UAAI;AACJ,UAAI;AAEJ,UAAI,MAAM,MAAM,QAAQ;AACtB,iBAAS,MAAM,IAAI,CAAC,GAAG;AACvB,mBAAW,WAAW,IAAI,CAAC;AAC3B,eAAO;AAAA,MACT,WAAW,MAAM,GAAG;AAClB,iBAAS,MAAM,CAAC,GAAG;AACnB,mBAAW,oBAAoB,WAAW,MAAM;AAChD,eAAO,MAAM,CAAC,GAAG;AAAA,MACnB,OAAO;AACL,iBAAS,MAAM,CAAC,GAAG;AACnB,mBAAW,WAAW,IAAI,CAAC;AAC3B,eAAO,MAAM,CAAC,GAAG;AAAA,MACnB;AAEA,UAAI,CAAC,YAAY,CAAC,UAAU,SAAS,QAAW;AAC9C,cAAM,MAAM,iCAAiC;AAAA,MAC/C;AAEA,YAAM,QAAQ,SAAS,UAAU,IAAI;AAErC,YAAM,eAAe,iBAAiB,OAAO,GAAG,KAAK;AAErD,YAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,QACvD,SAAS;AAAA,QACT,iBAAiB;AAAA,QACjB,WAAW;AAAA,QACX,cAAc,cAAc;AAAA,QAC5B,gBAAgB,WAAW;AAAA,QAC3B,uBACE,cAAc,eAAe;AAAA,QAC/B,eAAe,IAAI,WAAW;AAAA,MAChC,CAAC;AAED,YAAM,YAAY,MAAM,KAAK,OAAO,OAAO,eAAe;AAAA,QACxD,SAAS;AAAA,QACT,sBAAsB,cAAc,eAAe;AAAA,QACnD,sBAAsB,cAAc,eAAe;AAAA,QACnD,cAAc,cAAc;AAAA,QAC5B,uBACE,cAAc,eAAe;AAAA,QAC/B,gBAAgB,WAAW;AAAA,QAC3B,WAAW;AAAA,QACX,eAAe;AAAA,QACf,eAAe,IAAI,WAAW;AAAA,MAChC,CAAC;AAED,UAAI,MAAM,MAAM,UAAU,MAAM,MAAM,SAAS,GAAG;AAChD,uBAAe,KAAK;AAAA,UAClB;AAAA,UACA,iBAAiB;AAAA,UACjB,mBAAmB,IAAI,WAAW;AAAA,QACpC,CAAC;AAAA,MACH,WAAW,MAAM,MAAM,QAAQ;AAC7B,0BAAkB;AAAA,MACpB,WAAW,MAAM,MAAM,SAAS,GAAG;AACjC,qBAAa;AACb,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,YAAY;AACrD,YAAM,MAAM,yCAAyC;AAAA,IACvD;AAEA,mBAAe,KAAK;AAAA,MAClB,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,IACrB,CAAC;AAED,WAAO,MAAM,YAAY,yBAAyB;AAAA,MAChD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eAAe,MAAgB,eAA2B;AAC9D,UAAM,SAAS,oBAAoB,KAAK,MAAM;AAC9C,UAAM,WAAW,oBAAoB,KAAK,QAAQ;AAElD,UAAM,iBAAiB,SAAS,SAAS,CAAC,EAAE,YAAY;AACxD,UAAM,kBAAoC;AAAA,MACxC,MAAM,WAAW,QAAQ,MAAM,CAAC;AAAA,MAChC,OAAO;AAAA,IACT;AAEA,UAAM,EAAE,cAAc,gBAAgB,IACpC,2BAA2B,cAAc;AAC3C,UAAM,YAAY,IAAI,YAAY,EAAE,qBAAqB,KAAK,CAAC;AAC/D,cAAU,SAAS,EAAE,GAAG,iBAAiB,UAAU,gBAAgB,CAAC;AACpE,cAAU,UAAU,OAAO,UAAU,CAAC,CAAC;AACvC,cAAU,UAAU,yBAAyB,CAAC;AAE9C,UAAM,oBAAsC;AAAA,MAC1C,MAAM,WAAW,QAAQ,SAAS,CAAE;AAAA,MACpC,OAAO;AAAA,IACT;AAEA,UAAM,aAAa,SAAS,UAAU,CAAC,EAAE;AACzC,QAAI,eAAe,QAAW;AAC5B,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AAEA,UAAM,cAAc;AAAA,MAClB,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,OAAO,WAAW;AAAA,IACzB;AAEA,UAAM,cAAc,iBAAiB,WAAW,GAAG,OAAO,UAAU,CAAC,CAAC;AACtE,UAAM,gBAAgB,iBAAiB,aAAa,GAAG,OAAO,UAAU,CAAC,CAAC;AAE1E,UAAM,oBAAoB;AAAA,MACxB,kBAAkB;AAAA,MAClB,OAAO,UAAU,QAAQ;AAAA,MACzB,wBACE,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAAA,IACxD;AAEA,UAAM,sBAAsB;AAAA,MAC1B,kBAAkB;AAAA,MAClB,OAAO,YAAY,QAAQ;AAAA,MAC3B,wBACE,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAAA,IACxD;AAEA,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,UAAM,WAAW,MAAM,YAAY,YAAY;AAAA,MAC7C,QAAQ,KAAK;AAAA,MACb,wBAAwB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACtE,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,IACtB,CAAC;AAED,QAAI,CAAC,SAAS,uBAAuB,CAAC,SAAS,uBAAuB;AACpE,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AAEA,UAAM,cAAc,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,MACrD,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,WAAW;AAAA,MACX,cAAc,SAAS,oBAAoB;AAAA,MAC3C,gBAAgB,kBAAkB;AAAA,MAClC,uBACE,SAAS,oBAAoB,eAAe;AAAA,MAC9C,eAAe,IAAI,WAAW;AAAA,IAChC,CAAC;AAED,UAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,MACvD,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,WAAW;AAAA,MACX,cAAc,SAAS,sBAAsB;AAAA,MAC7C,gBAAgB,oBAAoB;AAAA,MACpC,uBACE,SAAS,sBAAsB,eAAe;AAAA,MAChD,eAAe,IAAI,WAAW;AAAA,IAChC,CAAC;AAED,UAAM,UAAU,MAAM,KAAK,OAAO,OAAO,eAAe;AAAA,MACtD,SAAS;AAAA,MACT,sBACE,SAAS,oBAAoB,eAAe;AAAA,MAC9C,sBACE,SAAS,oBAAoB,eAAe;AAAA,MAC9C,cAAc,SAAS,oBAAoB;AAAA,MAC3C,uBACE,SAAS,oBAAoB,eAAe;AAAA,MAC9C,gBAAgB,kBAAkB;AAAA,MAClC,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe,IAAI,WAAW;AAAA,IAChC,CAAC;AAED,UAAM,YAAY,MAAM,KAAK,OAAO,OAAO,eAAe;AAAA,MACxD,SAAS;AAAA,MACT,sBACE,SAAS,sBAAsB,eAAe;AAAA,MAChD,sBACE,SAAS,sBAAsB,eAAe;AAAA,MAChD,cAAc,SAAS,sBAAsB;AAAA,MAC7C,uBACE,SAAS,sBAAsB,eAAe;AAAA,MAChD,gBAAgB,oBAAoB;AAAA,MACpC,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe,IAAI,WAAW;AAAA,IAChC,CAAC;AAED,WAAO,MAAM,YAAY,yBAAyB;AAAA,MAChD;AAAA,MACA,gBAAgB;AAAA,QACd;AAAA,UACE,QAAQ,SAAS;AAAA,UACjB,iBAAiB;AAAA,UACjB,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ADhyCA,IAAMC,UAAS,UAAU;AASlB,IAAM,kBAAN,cAA8B,oBAAoB;AAAA,EACvD,YACE,QACA,mBACA;AACA,UAAM,QAAQ,iBAAiB;AAAA,EACjC;AAAA,EAEA,MAAM,6BAA6B;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAGG;AACD,UAAM,EAAE,UAAU,cAAc,IAAI,MAAM,KAAK;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,gBAAgB,MAAM,KAAK;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,eAAe,cAAc;AAAA,EAClD;AAAA,EAEQ,iCACN,UACA,cACA,iBACA,YACA,gBACa;AACb,UAAM,WAAW,IAAIC,aAAY;AACjC,QAAI,CAAC,aAAa,QAAQ,aAAa,UAAU,QAAW;AAC1D,YAAM,IAAI,gBAAgB,yBAAyB;AAAA,QACjD,OAAO;AAAA,QACP,OAAO,EAAE,MAAM,aAAa,MAAM,OAAO,aAAa,MAAM;AAAA,QAC5D,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AACA,aAAS,SAAS;AAAA,MAChB,MAAM,aAAa;AAAA,MACnB,OAAO,aAAa;AAAA,MACpB;AAAA,IACF,CAAC;AAED,aAAS,SAAS,eAAe;AACjC,UAAM,iBAAiB;AAAA,MACrB;AAAA,MACA,KAAK,OAAO,WAAW;AAAA,IACzB;AAEA,aAAS,UAAU;AAAA,MACjB,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EACA,MAAc,oBACZ,QACA,UACA,kBACA,gBACyE;AACzE,QAAI,OAAO,WAAW,iBAAiB,QAAQ;AAC7C,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,YACL,aAAa,OAAO;AAAA,YACpB,cAAc,iBAAiB;AAAA,UACjC;AAAA,UACA,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAwC,CAAC;AAC/C,UAAM,cAAkD,oBAAI,IAAI;AAEhE,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,gBAAgB,gBAAgB;AAAA,UACxC,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AACA,YAAM,kBAAkB,iBAAiB,CAAC;AAC1C,UAAI,CAAC,iBAAiB;AACpB,cAAM,IAAI,gBAAgB,4BAA4B;AAAA,UACpD,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AACA,YAAM,kBAAkB,oBAAoB,KAAK,KAAK,QAAQ;AAE9D,YAAM,EAAE,aAAa,IAAI;AAAA,QACvB,gBAAgB,SAAS,CAAC,EAAE;AAAA,MAC9B;AAEA,YAAM,WAAW,KAAK;AAAA,QACpB;AAAA,QACA,gBAAgB,SAAS,CAAC;AAAA,QAC1B;AAAA,QACA,OAAO,KAAK,KAAK,KAAK;AAAA,QACtB;AAAA,MACF;AAEA,YAAM,yBACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AACtD,YAAM,aAAqC;AAAA,QACzC,QAAQ,KAAK,KAAK;AAAA,QAClB,oBAAoB;AAAA,UAClB,kBAAkB,KAAK;AAAA,UACvB,OAAO,SAAS,QAAQ;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAEA,kBAAY,KAAK,UAAU;AAC3B,YAAM,KAAK,oBAAoB,KAAK,KAAK,MAAM;AAC/C,kBAAY,IAAI,KAAK,KAAK,IAAI;AAAA,QAC5B,eAAe,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,KAAK,KAAK;AAAA,QAChB,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,iBAAiB;AAAA,QAC5C,UAAU;AAAA,UACR,YAAYC,QAAO;AAAA,UACnB,cAAc;AAAA,UACd,wBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,UAChD,2BAA2B;AAAA,UAC3B,YACE,KAAK,OAAO,WAAW,uBACnB,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,MAAO,IAAI,KAAK,GAAI,IAC7D,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAI;AAAA;AAAA,QAC3C;AAAA,QACA,QAAQA,QAAO;AAAA,QACf,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC/D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,UAAU;AACtB,YAAM,IAAI,aAAa,uCAAuC;AAAA,QAC5D,WAAW;AAAA,QACX,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B;AAAA,MACA,SAAS;AAAA,IACX;AAEA,UAAM,gBAAyC,oBAAI,IAAI;AACvD,eAAW,aAAa,YAAY;AAClC,oBAAc,IAAI,UAAU,QAAQ,UAAU,iBAAiB;AAAA,IACjE;AAEA,WAAO,EAAE,UAAU,SAAS,UAAU,cAAc;AAAA,EACtD;AACF;;;AEpOA;AAAA,EACE;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAC;AAAA,OACK;AACP,SAAS,aAAAC,kBAAiB;AAE1B,SAAS,UAAAC,eAAc;AACvB,SAAS,cAAc;AACvB,SAAS,UAAAC,eAAc;AA4BvB,IAAMC,UAAS,UAAU;AAyBlB,IAAM,mBAAN,MAAuB;AAAA,EACX;AAAA,EACA;AAAA,EAEjB,YACE,QACA,mBACA;AACA,SAAK,SAAS;AACd,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,MAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAmE;AACjE,UAAM,YAAYA,QAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;AAC3D,UAAM,WAAWC;AAAA,MACf,gBAAgB,SAAS,IAAIC,WAAU,MAAM;AAAA,MAC7C;AAAA,IACF;AACA,WAAO,MAAM,KAAK,mCAAmC;AAAA,MACnD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,mCAAmC;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA+E;AAC7E,UAAM,cAAcC,QAAO,QAAQ;AACnC,UAAM,UAAU,MAAM,eAAe,YAAY,aAAa,IAAI;AAClE,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO,sBAAsB;AAAA,MAC5D,QAAQ;AAAA,MACR,YAAYD,WAAU,MAAM;AAAA,MAC5B,WAAW,KAAK,OAAO,aAAa;AAAA,MACpC,WAAW,OAAO,KAAK,KAAK,OAAO,oBAAoB,CAAC,EAAE;AAAA,IAC5D,CAAC;AAED,UAAM,SAAkB,CAAC;AACzB,UAAM,WAAW,OAAO,QAAQ,KAAK,OAAO,oBAAoB,CAAC,EAAE;AAAA,MACjE,OAAO,CAAC,GAAG,QAAQ,MAAM;AACvB,cAAM,QAAQ,OAAO,SAAS,EAAE;AAChC,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,gBAAgB,gCAAgC;AAAA,YACxD,OAAO;AAAA,YACP,OAAO,SAAS;AAAA,YAChB,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAEA,cAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,UAC/C,SAAS;AAAA,QACX;AAEA,YAAI;AACF,gBAAM,YAAY,qBAAqB;AAAA,YACrC;AAAA,YACA,eAAe;AAAA,cACb,aAAaD,iBAAgB,MAAM,OAAO,EAAE;AAAA,cAC5C,QAAQ,MAAM;AAAA,YAChB;AAAA,YACA,WAAW,KAAK,OAAO,aAAa;AAAA,YACpC,eAAe,QAAQ,QAAQ;AAAA,YAC/B,uBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,UAClD,CAAC;AAAA,QACH,SAAS,GAAQ;AACf,iBAAO,KAAK,CAAC;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,QAAQ;AAE1B,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,YAAY,OAAO;AAAA,UACnB,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;AAAA,QAChD;AAAA,QACA,OAAO,CAAC;AAAA,MACV;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ,GAAsE;AACpE,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI;AACF,2BAAqB,MAAM,YAAY,wBAAwB;AAAA,QAC7D,SAAS,OAAO,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE;AAAA,MAC5C,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC/D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAkB,MAAM,KAAK;AAAA,MACjC;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA,IACF;AAEA,UAAM,aAAaG,QAAO;AAC1B,QAAI,eAAe;AACnB,QAAI,aAAqB;AACzB,QAAI,eAAe;AACjB,YAAM,iBAAiB,OAAO,aAAa;AAC3C,UAAI,cAAc;AAClB,UAAI;AACF,sBAAc;AAAA,UACZ,eAAe,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,QAAQ,GAC/D;AAAA,QACN;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,0BAA0B,KAAK;AAAA,MAC/C;AAEA,mBAAa,cAAc;AAC3B,qBAAe;AAAA,IACjB;AAEA,UAAM,SAAS;AAIf,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,uBAAuB;AAAA,QAClD;AAAA,QACA,eAAe;AAAA,UACb,oBAAoB;AAAA,YAClB,eAAe;AAAA,UACjB;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA;AAAA,QACA,UAAU;AAAA,UACR;AAAA,UACA,wBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,UAChD,cAAc;AAAA,UACd,2BAA2B;AAAA,UAC3B,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAI;AAAA,QACjD;AAAA,QACA,2BAA2B;AAAA,QAC3B;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC/D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,uBACJ,aAC6B;AAC7B,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,0BAA0B;AAAA,QACrD;AAAA,QACA,mBAAmB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACnE,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC/D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,yBAAyB,kBAA4C;AACnE,UAAM,WAAW,oBAAoB,iBAAiB,QAAQ;AAE9D,WAAO,SAAS,UAAU,CAAC,EAAE,UAAU;AAAA,EACzC;AAAA,EAEA,MAAM,gBAAgB,UAAyC;AAC7D,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,UAAM,cAAcD,QAAO,QAAQ;AACnC,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,iBAAiB;AAAA,QAC5C;AAAA,QACA;AAAA,QACA,mBAAmB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACnE,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC/D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,UAAU;AACtB,YAAM,IAAI,gBAAgB,yCAAyC;AAAA,QACjE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,MAAc,YACZ,QACA,oBACA,wBACmC;AACnC,UAAM,kBAA4C,CAAC;AACnD,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,CAAC,MAAM,MAAM;AACf,cAAM,IAAI,gBAAgB,iCAAiC;AAAA,UACzD,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAEA,YAAM,SAAS,oBAAoB,KAAK,KAAK,MAAM;AACnD,YAAM,eAAiC;AAAA,QACrC,MAAME,YAAW,QAAQ,MAAM,CAAC;AAAA,QAChC,OAAO;AAAA,MACT;AAEA,YAAM,eAAe,oBAAoB,KAAK,KAAK,QAAQ;AAC3D,YAAM,EAAE,aAAa,IAAI;AAAA,QACvB,aAAa,SAAS,CAAC,EAAE;AAAA,MAC3B;AACA,YAAM,aAAa,aAAa,UAAU,CAAC,EAAE;AAC7C,UAAI,eAAe,QAAW;AAC5B,cAAM,IAAI,gBAAgB,8BAA8B;AAAA,UACtD,OAAO;AAAA,UACP,OAAO,aAAa,UAAU,CAAC;AAAA,UAC/B,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAEA,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,OAAO,WAAW;AAAA,MACzB;AAEA,YAAM,UAAU,iBAAiB,UAAU,GAAG,OAAO,UAAU,CAAC,CAAC;AAEjE,YAAM,oBACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAEtD,YAAM,0BACJ,mBAAmB,CAAC,GAAG;AACzB,UAAI,CAAC,yBAAyB;AAC5B,cAAM,IAAI,gBAAgB,+BAA+B;AAAA,UACvD,OAAO;AAAA,UACP,OAAO,mBAAmB,CAAC;AAAA,UAC3B,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AACA,YAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,QACvD,SAAS;AAAA,QACT,WAAW,KAAK;AAAA,QAChB,iBAAiB,KAAK;AAAA,QACtB,gBAAgB;AAAA,QAChB,uBAAuB;AAAA,QACvB,eAAe,IAAI,WAAW;AAAA,QAC9B,cAAc,KAAK,KAAK;AAAA,MAC1B,CAAC;AAED,sBAAgB,KAAK;AAAA,QACnB,QAAQ,KAAK,KAAK;AAAA,QAClB,kBAAkB,KAAK;AAAA,QACvB,OAAO,SAAS,QAAQ;AAAA,QACxB,wBAAwB;AAAA,QACxB,eAAe;AAAA,QACf,oBAAoB;AAAA,UAClB,oBAAoB;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AACF;;;AC5ZA,SAAS,SAAS,WAAW,eAAAC,oBAAmB;AAChD,SAAS,UAAAC,eAAc;AAwCvB,IAAMC,qBAAoB;AAEnB,IAAM,sBAAN,MAA0B;AAAA,EACd;AAAA,EACA;AAAA,EAEjB,YACE,QACA,mBACA;AACA,SAAK,SAAS;AACd,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,MAAM,8BACJ,MACA,wBACA,UACA,YAC6B;AAC7B,QAAI,CAAC,YAAY,CAAC,YAAY;AAC5B,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAEA,UAAM,KAAK,YAAY,MAAM,QAAQ,QAAS;AAE9C,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAEA,UAAM,sBACJ,KAAK,sCAAsC,IAAI;AACjD,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,UAAM,UAAqC;AAAA,MACzC,uBAAuB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACrE,MAAM;AAAA,IACR;AACA,QAAI,YAAY;AACd,UAAI,CAAC,WAAW,cAAc;AAC5B,cAAM,IAAI,MAAM,6BAA6B;AAAA,MAC/C;AACA,cAAQ,SAAS;AAAA,QACf,OAAO;AAAA,QACP,kBAAkB;AAAA,UAChB,QAAQ,WAAW;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,UAAU;AACnB,cAAQ,SAAS;AAAA,QACf,OAAO;AAAA,QACP,aAAa;AAAA,UACX;AAAA,UACA,OAAO,SAAS,QAAQ;AAAA,UACxB,SAAS,KAAK,OAAO,gBAAgB;AAAA,QACvC;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAEA,YAAQ,OAAO;AAAA,MACb,eAAe;AAAA,MACf,UAAU;AAAA,IACZ;AAEA,UAAM,OAA2B;AAAA,MAC/B,SAAS;AAAA,MACT,kBAAkB;AAAA,MAClB,UAAU;AAAA,IACZ;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,qBAAqB,OAAO;AAAA,IAC3D,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,iCAAiC,KAAK,EAAE;AAAA,IAC1D;AAEA,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAEA,SAAK,wBAAwB,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,CAAC;AAEpD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MACA,MACA,cACA,UACA,YACyC;AACzC,UAAM,UAA6B;AAAA,MACjC,uBAAuB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACrE,MAAM;AAAA,IACR;AAEA,QAAI;AACJ,QAAI,UAAU;AACZ,WAAK;AACL,cAAQ,SAAS;AAAA,QACf,OAAO;AAAA,QACP,aAAa;AAAA,UACX;AAAA,UACA,OAAO,SAAS,QAAQ;AAAA,UACxB,SAAS,KAAK,OAAO,gBAAgB;AAAA,QACvC;AAAA,MACF;AAAA,IACF,WAAW,YAAY;AACrB,WAAK,oBAAoB,WAAW,MAAM;AAC1C,UAAI,CAAC,WAAW,cAAc;AAC5B,cAAM,IAAI,MAAM,6BAA6B;AAAA,MAC/C;AACA,cAAQ,SAAS;AAAA,QACf,OAAO;AAAA,QACP,kBAAkB;AAAA,UAChB,QAAQ,WAAW;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAEA,UAAM,mBAAmB,MAAM,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,MACA,KAAK,OAAO,WAAW;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,OAAO;AAEf,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,YAAY,OAAO;AAAA,IAClD,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,wBAAwB,KAAK,EAAE;AAAA,IACjD;AAEA,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAEA,UAAM,yBAAyB,SAAS;AAExC,UAAM,iBAAiB,MAAM,KAAK;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,qBAAe,MAAM,YAAY,yBAAyB;AAAA,QACxD;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,qBAAqB,eAAe;AAAA,QACtC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,yBACZ,wBACA,QAC+B;AAC/B,UAAM,UAAU,MAAM,KAAK,OAAO,OAAO,kBAAkBC,QAAO,MAAM,CAAC;AACzE,UAAM,WAA+B;AAAA,MACnC,kBAAkB;AAAA,MAClB,UAAU,CAAC;AAAA,IACb;AAEA,UAAM,WACJ,MAAM,KAAK,OAAO,OAAO;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAEF,UAAM,YAAgC;AAAA,MACpC,kBAAkB;AAAA,MAClB,UAAU,CAAC;AAAA,IACb;AACA,WAAO,CAAC,UAAU,SAAS;AAAA,EAC7B;AAAA,EAEQ,sCACN,WACsB;AACtB,UAAM,UAAgC,CAAC;AACvC,eAAW,QAAQ,WAAW;AAC5B,YAAM,SAA6B;AAAA,QACjC,eAAe,KAAK;AAAA,QACpB,UAAU,KAAK,sCAAsC,KAAK,QAAQ;AAAA,MACpE;AACA,cAAQ,KAAK,MAAM;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,wBACN,MACA,cACA;AACA,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAI,CAAC,KAAK,CAAC,GAAG;AACZ,cAAM,IAAI,gBAAgB,0BAA0B;AAAA,UAClD,OAAO;AAAA,UACP,YAAY,KAAK;AAAA,QACnB,CAAC;AAAA,MACH;AACA,UAAI,CAAC,aAAa,CAAC,GAAG;AACpB,cAAM,IAAI,gBAAgB,6BAA6B;AAAA,UACrD,OAAO;AAAA,UACP,oBAAoB,aAAa;AAAA,QACnC,CAAC;AAAA,MACH;AAEA,WAAK,CAAC,EAAE,UAAU,aAAa,CAAC,EAAE,SAAS;AAE3C,WAAK,CAAC,EAAE,kBAAkB,aAAa,CAAC,EAAE,SAAS;AAEnD,WAAK,wBAAwB,KAAK,CAAC,EAAE,UAAU,aAAa,CAAC,EAAE,QAAQ;AAAA,IACzE;AAAA,EACF;AAAA,EAEA,MAAc,uBACZ,MACA,UACA,MACA,SACiC;AAEjC,UAAM,uBAA+C;AAAA,MACnD,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,UAAU,CAAC;AAAA,IACb;AAEA,UAAM,KAAK,IAAIC,aAAY;AAC3B,OAAG,SAAS;AAAA,MACV,MAAM,QAAQ,QAAQ;AAAA,MACtB,OAAO;AAAA,IACT,CAAC;AAED,UAAM,cAAc,SAAS,UAAU,IAAI;AAC3C,QAAI,CAAC,aAAa,UAAU,CAAC,aAAa,QAAQ;AAChD,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,OAAG,UAAU;AAAA,MACX,QAAQ,YAAY;AAAA,MACpB,QAAQ,YAAY;AAAA,IACtB,CAAC;AAGD,OAAG,UAAU,yBAAyB,CAAC;AAEvC,UAAM,yBACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AACtD,UAAM,aAAyB;AAAA,MAC7B,kBAAkB,KAAK;AAAA,MACvB,OAAO,GAAG,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,yBAAqB,0BAA0B;AAC/C,yBAAqB,mBAAmB;AAGxC,UAAM,WAAY,KAAK,KAAMF;AAE7B,UAAM,oBAA4C;AAAA,MAChD,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,UAAU,CAAC;AAAA,IACb;AAEA,UAAM,UAAU,IAAIE,aAAY;AAChC,YAAQ,SAAS;AAAA,MACf,MAAM,QAAQ,EAAE;AAAA,MAChB,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAED,YAAQ,UAAU;AAAA,MAChB,QAAQ,YAAY;AAAA,MACpB,QAAQ,YAAY;AAAA,IACtB,CAAC;AAGD,YAAQ,UAAU,yBAAyB,CAAC;AAE5C,UAAM,8BACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AACtD,UAAM,kBAA8B;AAAA,MAClC,kBAAkB,KAAK;AAAA,MACvB,OAAO,QAAQ,QAAQ;AAAA,MACvB,wBAAwB;AAAA,IAC1B;AAEA,sBAAkB,0BAA0B;AAC5C,sBAAkB,mBAAmB;AAErC,UAAM,WAAW,IAAIA,aAAY;AACjC,aAAS,SAAS;AAAA,MAChB,MAAM,QAAQ,OAAO;AAAA,MACrB,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAED,UAAM,oBAAoB;AAAA,MACxB,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,gBAAgB,QAAQ,WAAW,OAAO,CAAC,EAAE;AAAA,MACjD;AAAA,IACF;AACA,UAAM,iBAAiB,UAAU,OAAO,aAAa;AACrD,aAAS,UAAU;AAAA,MACjB,QAAQ;AAAA,MACR,QAAQ,YAAY;AAAA,IACtB,CAAC;AAED,UAAM,+BACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AAEtD,UAAM,mBAA+B;AAAA,MACnC,kBAAkB,KAAK;AAAA,MACvB,OAAO,SAAS,QAAQ;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AACA,sBAAkB,4BAA4B;AAC9C,sBAAkB,qBAAqB;AAEvC,yBAAqB,SAAS,KAAK,iBAAiB;AAEpD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,2BACZ,MACA,cACA,SACA,MACA,UACiC;AACjC,UAAM,iBAAiB,SAAS,UAAU,IAAI;AAC9C,QAAI,CAAC,gBAAgB,UAAU,CAAC,gBAAgB,QAAQ;AACtD,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,UAAM,aAAa,IAAIA,aAAY;AACnC,eAAW,SAAS;AAAA,MAClB,MAAM,QAAQ,QAAQ;AAAA,MACtB,OAAO;AAAA,IACT,CAAC;AAED,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,YAAM,QAAQ,KAAK,SAAS,CAAC;AAC7B,UAAI,CAAC,SAAS,CAAC,MAAM,SAAS;AAC5B,cAAM,IAAI,MAAM,4BAA4B;AAAA,MAC9C;AACA,YAAM,eAAe,QAAQ,WAAW,OAAO,CAAC,EAAE,OAAO,MAAM,OAAO;AACtE,YAAM,gBAAgB,UAAU,OAAO,YAAY;AACnD,iBAAW,UAAU;AAAA,QACnB,QAAQ;AAAA,QACR,QAAQ,eAAe,SAAS;AAAA,MAClC,CAAC;AAAA,IACH;AAGA,UAAM,SAAS,yBAAyB;AACxC,eAAW,UAAU,MAAM;AAE3B,UAAM,4BACJ,MAAM,KAAK,OAAO,OAAO,2BAA2B;AACtD,UAAM,qBAAiC;AAAA,MACrC,kBAAkB,KAAK;AAAA,MACvB,OAAO,WAAW,QAAQ;AAAA,MAC1B,wBAAwB;AAAA,IAC1B;AACA,UAAM,mBAA2C;AAAA,MAC/C,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,UAAU,CAAC;AAAA,IACb;AACA,qBAAiB,0BAA0B;AAE3C,UAAM,YAAY,KAAK,SAAS,CAAC;AACjC,UAAM,aAAa,KAAK,SAAS,CAAC;AAClC,QAAI,CAAC,aAAa,CAAC,YAAY;AAC7B,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,wBAAwB,MAAM,KAAK;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,yBAAyB,MAAM,KAAK;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,qBAAiB,SAAS,KAAK,qBAAqB;AACpD,qBAAiB,SAAS,KAAK,sBAAsB;AAErD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,iBACZ,UACA,MACA,cACA,cACA,sBACyD;AACzD,QACE,CAAC,aAAa,kBAAkB,oBAChC,CAAC,aAAa,iBACd;AACA,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACpE;AAEA,UAAM,iBAAiB,SAAS,UAAU,IAAI;AAC9C,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,KAAK,oBAAoB,aAAa,iBAAiB,KAAK;AAClE,UAAM,YAAY,iBAAiB,IAAI,GAAG,cAAc;AAExD,QAAI,kBAA8B,IAAI,WAAW;AACjD,QAAI,aAAa,yBAAyB;AACxC,YAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,QACvD,SAAS;AAAA,QACT,WAAW,aAAa,iBAAiB;AAAA,QACzC,iBAAiB,aAAa;AAAA,QAC9B,gBAAgB,aAAa;AAAA,QAC7B,uBACE,qBAAqB,qBAAqB;AAAA,QAC5C,cAAc,aAAa;AAAA,MAC7B,CAAC;AAED,wBAAkB,MAAM,KAAK,OAAO,OAAO,eAAe;AAAA,QACxD,SAAS;AAAA,QACT,sBACE,qBAAqB,qBAAqB;AAAA,QAC5C,sBACE,qBAAqB,qBAAqB;AAAA,QAC5C,cAAc,aAAa;AAAA,QAC3B,uBACE,qBAAqB,qBAAqB;AAAA,QAC5C,gBAAgB,aAAa;AAAA,QAC7B,eAAe;AAAA,QACf,WAAW,aAAa;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,QAAI,oBAAgC,IAAI,WAAW;AACnD,QAAI,aAAa,2BAA2B;AAC1C,YAAM,QAAQ,aAAa,oBAAoB;AAC/C,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AACA,UAAI,CAAC,aAAa,oBAAoB,kBAAkB;AACtD,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AACA,YAAM,WAAW,oBAAoB,KAAK;AAC1C,YAAM,kBAAkB,iBAAiB,UAAU,GAAG,cAAc;AAEpE,YAAM,wBAAwB,MAAM,KAAK,OAAO,OAAO,UAAU;AAAA,QAC/D,SAAS;AAAA,QACT,WAAW,aAAa,mBAAmB;AAAA,QAC3C,iBAAiB,aAAa;AAAA,QAC9B,gBAAgB,aAAa;AAAA,QAC7B,uBACE,qBAAqB,uBAAuB;AAAA,QAC9C,cAAc,aAAa;AAAA,MAC7B,CAAC;AAED,0BAAoB,MAAM,KAAK,OAAO,OAAO,eAAe;AAAA,QAC1D,SAAS;AAAA,QACT,sBACE,qBAAqB,uBAAuB;AAAA,QAC9C,sBACE,qBAAqB,uBAAuB;AAAA,QAC9C,cAAc,aAAa;AAAA,QAC3B,uBACE,qBAAqB,uBAAuB;AAAA,QAC9C,gBAAgB,aAAa;AAAA,QAC7B,eAAe;AAAA,QACf,WAAW,aAAa;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA,WAAW;AAAA,QACT,QAAQ,qBAAqB;AAAA,QAC7B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,IACA,MACA,MACA,kBACA,wBAC2B;AAC3B,UAAM,gBAAgB,MAAM,KAAK;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,iBAAiB,KAAK,SAAS,CAAC;AACtC,UAAM,kBAAkB,KAAK,SAAS,CAAC;AACvC,UAAM,6BAA6B,iBAAiB,SAAS,CAAC;AAC9D,UAAM,8BAA8B,iBAAiB,SAAS,CAAC;AAC/D,UAAM,+BAA+B,uBAAuB,SAAS,CAAC;AACtE,UAAM,gCAAgC,uBAAuB,SAAS,CAAC;AACvE,QAAI,CAAC,kBAAkB,CAAC,iBAAiB;AACvC,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,QAAI,CAAC,8BAA8B,CAAC,6BAA6B;AAC/D,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,QAAI,CAAC,gCAAgC,CAAC,+BAA+B;AACnE,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,UAAM,qBAAqB,MAAM,KAAK;AAAA,MACpC,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,sBAAsB,MAAM,KAAK;AAAA,MACrC,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,aAAa;AAAA,MACjB,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,IACtB;AAEA,WAAO;AAAA,EACT;AACF;;;AjB5hBA,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;;;AkB1F7B,SAAS,cAAAC,aAAY,cAAAC,mBAAkB;AACvC,SAAS,SAAS,aAAAC,kBAAiB;AACnC,YAAY,SAAS;AACrB,SAAS,WAAAC,UAAS,aAAAC,YAAW,SAAS,eAAAC,oBAAmB;AAEzD,SAAS,2BAA2B;AAUpC,IAAM,oBAAoBC;AAAA,EACxB;AACF;AAGA,IAAM,oBAAoBA;AAAA,EACxB;AACF;AACA,IAAM,eAAe;AASrB,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,mBAAmB;AAElB,IAAM,gBAAN,MAAM,eAAc;AAAA,EAMjB,YACE,MAAc,yBACd,WAAmB,YACnB,WAAmB,oBAC3B;AAHQ;AACA;AACA;AAER,SAAK,gBAAgB;AAAA,MACnBC,WAAU,aAAa,iBAAiB;AAAA;AAAA,IAE1C;AAAA,EACF;AAAA,EAdQ,QAAsB,CAAC;AAAA,EAC/B,OAAe,WAAiC;AAAA,EACxC;AAAA,EACA,OAAsB,QAAQ,QAAQ;AAAA,EAa9C,OAAO,YACL,MAAc,yBACd,WAAmB,YACnB,WAAmB,oBACJ;AACf,QAAI,CAAC,eAAc,UAAU;AAC3B,qBAAc,WAAW,IAAI,eAAc,KAAK,UAAU,QAAQ;AAAA,IACpE;AACA,WAAO,eAAc;AAAA,EACvB;AAAA,EAEA,MAAc,SAAY,WAAyC;AACjE,UAAM,UAAU,KAAK;AACrB,QAAI;AACJ,SAAK,OAAO,IAAI,QAAc,CAAC,MAAO,UAAU,CAAE;AAClD,UAAM;AACN,QAAI;AACF,aAAO,MAAM,UAAU;AAAA,IACzB,UAAE;AACA,cAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,OAA4B;AAChC,WAAO,KAAK,SAAS,YAAY;AAC/B,UAAI,KAAK,MAAM,WAAW,GAAG;AAC3B,cAAM,KAAK,OAAO;AAAA,MACpB;AAEA,YAAM,OAAO,KAAK,MAAM,CAAC;AACzB,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AACA,WAAK,QAAQ,KAAK,MAAM,MAAM,CAAC;AAC/B,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,SAAwB;AACpC,UAAM,cAAcA,WAAU,aAAa,iBAAiB;AAC5D,UAAM,UAAU,4BAA4B,0BAA0B;AAGtE,UAAM,aAAa,MAAM,KAAK,KAAK,gBAAgB;AAAA,MACjD;AAAA,MACA,CAAC,QAAQ,OAAO,GAAG;AAAA,IACrB,CAAC;AAED,QAAI;AACJ,QAAI;AACJ,QAAI,CAAC,WAAW,WAAW,WAAW,SAAS,WAAW,GAAG;AAC3D,YAAM,YAAY,MAAM,KAAK,kBAAkB,GAAG,OAAO;AACzD,YAAM,QAAQ,MAAM,KAAK,SAAS,UAAU,CAAC,CAAC;AAC9C,YAAM,YAAYC,aAAY,QAAQF,YAAW,MAAM,GAAG,CAAC,EAAE,GAAG,GAAG;AAAA,QACjE,qBAAqB;AAAA,MACvB,CAAC;AAED,YAAM,KAAK,kBAAkB,KAAK,KAAK,aAAa;AAEpD,qBAAe;AAAA,QACb,MAAM,MAAM,GAAG,CAAC,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,QAAQ,UAAU,UAAU,CAAC,EAAG;AAAA;AAAA,MAClC;AACA,+BAAyB,OAAO,aAAa,MAAM;AAAA,IACrD,OAAO;AACL,qBAAe,WAAW,SAAS,KAAK,CAAC,SAAS;AAChD,cAAM,gBACJ,OAAO,KAAK,MAAM,KAAK,SAAS,YAAY,CAAC,KAC7C,cAAc;AAChB,cAAM,WAAW,WAAW,SAAS,KAAK,UAAU;AACpD,eAAO,iBAAiB;AAAA,MAC1B,CAAC;AAED,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,MAAM,qDAAqD;AAAA,MACvE;AACA,+BAAyB;AAAA,QACvB,KAAK,MAAM,aAAa,SAAS,YAAY;AAAA,MAC/C;AAAA,IACF;AAEA,UAAM,mBAAmB;AAAA,OACtB,yBAAyB,cAAc;AAAA,IAC1C;AACA,UAAM,mBAAmB,KAAK,IAAI,kBAAkB,gBAAgB;AAEpE,QAAI,mBAAmB,GAAG;AACxB,YAAM,IAAI;AAAA,QACR,kBAAkB,sBAAsB,yDAAyD,WAAW;AAAA,MAC9G;AAAA,IACF;AAEA,UAAM,UAAU,IAAIE,aAAY;AAChC,YAAQ,SAAS;AAAA,MACf,MAAM,aAAa;AAAA,MACnB,OAAO,aAAa;AAAA,IACtB,CAAC;AAED,UAAM,eAAeD,WAAU,aAAa,iBAAiB;AAC7D,UAAM,SAAS,2BAA2B,2BAA2B;AACrE,aAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AACzC,cAAQ,UAAU;AAAA,QAChB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,UAAM,iBACJ,yBACA,cAAc,OAAO,gBAAgB,IACrC;AACF,UAAM,cAAc,2BAA2B,0BAA0B;AACzE,QAAI,iBAAiB,IAAI;AACvB,cAAQ,UAAU;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,MAAM,KAAK;AAAA,MAC/B;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAEA,UAAM,KAAK,YAAYE,YAAW,cAAc,QAAQ,CAAC,CAAC;AAE1D,UAAM,YAAY,cAAc;AAChC,aAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AACzC,WAAK,MAAM,KAAK;AAAA,QACd,KAAK;AAAA,QACL,UAAU;AAAA,UACR,MAAMH,YAAW,SAAS;AAAA,UAC1B,OAAO;AAAA,QACT;AAAA,QACA,OAAO,cAAc,UAAU,CAAC;AAAA,MAClC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,8BAA8B,QAAoB;AACtD,UAAM,iBAAiB,IAAIE,aAAY;AAKvC,UAAM,gBAAoB,WAAO,QAAQ,wBAAwB,CAAC,EAAE;AACpE,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAGA,UAAM,aAAa,MAAM,KAAK,KAAK;AACnC,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC;AAGA,mBAAe,SAAS,WAAW,QAAQ;AAG3C,mBAAe;AAAA,MACb;AAAA,MACA,cAAc;AAAA,MACd,wBAAwB;AAAA,IAC1B;AAGA,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAGA,UAAM,KAAK,YAAYC,YAAW,SAAS,QAAQ,CAAC,CAAC;AAAA,EACvD;AAAA,EAEA,MAAM,eACJ,YACA,cACA,KACsB;AACtB,UAAM,SAASF,WAAU,aAAa,GAAG;AACzC,UAAM,cAAc,OAAO,MAAM,CAAC;AAElC,UAAM,SAAS,2BAA2B,qBAAqB;AAE/D,eAAW,YAAY,GAAG;AAAA,MACxB,gBAAgB;AAAA,MAChB,aAAa;AAAA,QACX;AAAA,QACA,QAAQ,aAAa;AAAA,MACvB;AAAA,IACF,CAAC;AAED,UAAM,UAAU,WAAW;AAAA,MACzB;AAAA,MACA,IAAI,MAAM,WAAW,YAAY,EAAE,KAAK,MAAM;AAAA,MAC9C,QAAQ;AAAA,MACR,IAAI,MAAM,WAAW,YAAY,EAAE,KAAK,aAAa,MAAO;AAAA,IAC9D;AAEA,UAAM,aAAa,IAAI,WAAW;AAClC,UAAM,aAAa,oBAAoB,KAAK,UAAU;AACtD,QAAI,CAAC;AACH,YAAM,IAAI,MAAM,0CAA0C;AAE5D,UAAM,YAAY,QAAQ,KAAK,SAAS,UAAU;AAElD,eAAW,YAAY,GAAG;AAAA,MACxB,WAAW;AAAA,IACb,CAAC;AAED,eAAW,SAAS;AAEpB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,MAAM,WAAW,WAAmB;AAClC,WAAO,MAAM,KAAK,kBAAkB,WAAW,KAAK,aAAa;AAAA,EACnE;AAAA,EAEA,MAAc,KAAK,QAAgB,QAAe;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,KAAK;AAAA,QACrC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,WAAW,KAAK,GAAG,KAAK,QAAQ,IAAI,KAAK,QAAQ,EAAE;AAAA,QACpE;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS;AAAA,UACT,IAAI;AAAA,UACJ;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAED,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAI,KAAK,OAAO;AACd,gBAAQ,MAAM,wBAAwB,MAAM,KAAK,KAAK,KAAK;AAC3D,cAAM,IAAI,SAAS,sBAAsB,KAAK,MAAM,OAAO,IAAI;AAAA,UAC7D;AAAA,UACA;AAAA,UACA,MAAM,KAAK,MAAM;AAAA,QACnB,CAAC;AAAA,MACH;AAEA,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,UAAI,iBAAiB,UAAU;AAC7B,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,WAAmB,SAAiB;AAC1D,WAAO,MAAM,KAAK,KAAK,qBAAqB,CAAC,WAAW,OAAO,CAAC;AAAA,EAClE;AAAA,EAEA,MAAM,SAAS,WAAmB;AAChC,WAAO,MAAM,KAAK,KAAK,YAAY,CAAC,WAAW,CAAC,CAAC;AAAA,EACnD;AAAA,EAEA,MAAM,YAAY,OAAe;AAC/B,QAAI,WAAW,MAAM,KAAK,KAAK,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAC/D,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBAAiC;AACrC,UAAM,MAAMA,WAAU,MAAM,iBAAiB;AAC7C,UAAM,SAASA,WAAU,aAAa,GAAG;AACzC,WAAO,4BAA4B,qBAAqB;AAAA,EAC1D;AAAA,EAEA,MAAM,cAAc,SAAiB,QAAsC;AACzE,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC;AAEA,UAAM,KAAK,IAAIC,aAAY;AAC3B,OAAG,SAAS,KAAK,QAAQ;AAEzB,UAAM,kBAAkB,cAAc;AAEtC,UAAM,qBAAqBE,SAAQ,wBAAwB,CAAC,EAAE;AAAA,MAC5D;AAAA,IACF;AACA,UAAM,oBAAoBC,WAAU,OAAO,kBAAkB;AAC7D,OAAG,UAAU;AAAA,MACX,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAED,UAAM,eAAe,kBAAkB;AACvC,QAAI,eAAe,GAAG;AACpB,YAAM,YAAYJ,WAAU,MAAM,iBAAiB;AACnD,YAAM,eAAeA,WAAU,aAAa,SAAS;AACrD,YAAM,eAAe;AAAA,QACnB;AAAA;AAAA,MAEF;AACA,SAAG,UAAU;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,KAAK,eAAe,IAAI,KAAK,OAAO,KAAK,GAAG;AACnE,UAAM,QAAQE,YAAW,SAAS,QAAQ,CAAC;AAC3C,UAAM,KAAK,YAAY,KAAK;AAE5B,UAAM,KAAK,kBAAkB,GAAG,OAAO;AAEvC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,kBAAkB,MAAc;AACpC,WAAO,MAAM,KAAK,KAAK,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAAA,EACvD;AACF;;;AlBxRA,IAAMG,UAAS,UAAU;AAkElB,IAAM,cAAN,MAAM,qBAAoB,aAAa;AAAA,EACpC,SAAwB;AAAA,EAEtB;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EAEb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,qBAAqB,IAAI,MAAM;AAAA,EAC/B,cAAc,IAAI,MAAM;AAAA,EACxB,yBAAyB;AAAA,EACzB,YAA8B;AAAA,EAE9B,UAA8B,oBAAI,IAAI;AAAA,EAEtC,4BAAsC,CAAC;AAAA,EAEvC;AAAA,EAEA,mBAA2C;AAAA,EAEzC,SAAqB,CAAC;AAAA,EACtB,eACR,oBAAI,IAAI;AAAA;AAAA,EAGF,yBAAgD;AAAA,EAE9C,iBACR,MACA,IACgC;AAChC,WAAO,UAAU,SAA4B;AAC3C,UAAI,CAAC,KAAK,QAAQ;AAChB,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,aAAO,MAAM,KAAK,OAAO,gBAAgB,MAAM,OAAO,SAAS;AAC7D,cAAM,UAAU,KAAK,YAAY,EAAE;AACnC,YAAI;AACF,iBAAO,MAAM,GAAG,GAAG,IAAI;AAAA,QACzB,SAAS,OAAO;AACd,cAAI,iBAAiB,OAAO;AAC1B,kBAAM,WAAW,cAAc,OAAO;AAAA,UACxC,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,YAAC,MAAc,UAAU;AAAA,UAC3B;AACA,gBAAM;AAAA,QACR,UAAE;AACA,eAAK,IAAI;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAgB,iBAAiB,YAAoB;AACnD,UAAM,EAAE,OAAO,aAAa,QAAQ,IAAI,MAAM,OAAO,oBAAoB;AACzE,UAAM,EAAE,0BAA0B,IAAI,MAAM,OAAO,qBAAqB;AACxE,UAAM,EAAE,gCAAgC,IAAI,MAAM,OAChD,oCACF;AACA,UAAM,EAAE,oBAAoB,IAAI,MAAM,OACpC,+BACF;AAEA,UAAM,wBAAwB,IAAI,oBAAoB,CAAC;AACvD,gBAAY,oBAAoB,IAAI,0BAA0B,CAAC;AAC/D,YAAQ,wBAAwB,IAAI,gCAAgC,CAAC;AAErE,SAAK,SAAS,MAAM,UAAU,UAAU;AAAA,EAC1C;AAAA,EAEQ,6BAA6B;AACnC,SAAK,uBAAuB,KAAK;AAAA,MAC/B;AAAA,MACA,KAAK,qBAAqB,KAAK,IAAI;AAAA,IACrC;AACA,SAAK,kBAAkB,KAAK;AAAA,MAC1B;AAAA,MACA,KAAK,gBAAgB,KAAK,IAAI;AAAA,IAChC;AACA,SAAK,qBAAqB,KAAK;AAAA,MAC7B;AAAA,MACA,KAAK,mBAAmB,KAAK,IAAI;AAAA,IACnC;AACA,SAAK,eAAe,KAAK;AAAA,MACvB;AAAA,MACA,KAAK,aAAa,KAAK,IAAI;AAAA,IAC7B;AACA,SAAK,eAAe,KAAK;AAAA,MACvB;AAAA,MACA,KAAK,aAAa,KAAK,IAAI;AAAA,IAC7B;AACA,SAAK,aAAa,KAAK;AAAA,MACrB;AAAA,MACA,KAAK,WAAW,KAAK,IAAI;AAAA,IAC3B;AACA,SAAK,6BAA6B,KAAK;AAAA,MACrC;AAAA,MACA,KAAK,2BAA2B,KAAK,IAAI;AAAA,IAC3C;AACA,SAAK,4BAA4B,KAAK;AAAA,MACpC;AAAA,MACA,KAAK,0BAA0B,KAAK,IAAI;AAAA,IAC1C;AACA,SAAK,eAAe,KAAK;AAAA,MACvB;AAAA,MACA,KAAK,aAAa,KAAK,IAAI;AAAA,IAC7B;AACA,SAAK,kBAAkB,KAAK;AAAA,MAC1B;AAAA,MACA,KAAK,gBAAgB,KAAK,IAAI;AAAA,IAChC;AACA,SAAK,WAAW,KAAK;AAAA,MACnB;AAAA,MACA,KAAK,SAAS,KAAK,IAAI;AAAA,IACzB;AACA,SAAK,yBAAyB,KAAK;AAAA,MACjC;AAAA,MACA,KAAK,uBAAuB,KAAK,IAAI;AAAA,IACvC;AACA,SAAK,sBAAsB,KAAK;AAAA,MAC9B;AAAA,MACA,KAAK,oBAAoB,KAAK,IAAI;AAAA,IACpC;AACA,SAAK,8BAA8B,KAAK;AAAA,MACtC;AAAA,MACA,KAAK,4BAA4B,KAAK,IAAI;AAAA,IAC5C;AACA,SAAK,WAAW,KAAK;AAAA,MACnB;AAAA,MACA,KAAK,SAAS,KAAK,IAAI;AAAA,IACzB;AACA,SAAK,2BAA2B,KAAK;AAAA,MACnC;AAAA,MACA,KAAK,yBAAyB,KAAK,IAAI;AAAA,IACzC;AAAA,EACF;AAAA,EAEU,YAAY,SAAyB,QAAsB;AACnE,UAAM;AAEN,SAAK,SAAS,IAAI,oBAAoB,SAAS,MAAM;AACrD,SAAK,oBAAoB,IAAI,kBAAkB,KAAK,MAAM;AAC1D,SAAK,yBAAyB;AAAA,MAC5B,KAAK,OAAO,gBAAgB;AAAA,IAC9B;AACA,SAAK,iBAAiB,IAAI;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,kBAAkB,IAAI;AAAA,MACzB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,sBAAsB,IAAI;AAAA,MAC7B,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,0BAA0B,IAAI;AAAA,MACjC,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,mBAAmB,IAAI;AAAA,MAC1B,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,kBAAkB,IAAI;AAAA,MACzB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,aAAoB,WAAW;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAqB;AACnB,UAAM,SAAS,IAAI,aAAY,SAAS,MAAM;AAC9C,UAAM,eAAe,MAAM,OAAO,WAAW,gBAAgB,aAAa;AAE1E,WAAO;AAAA,MACL;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB;AAC/B,SAAK,YAAY,IAAI,UAAU,KAAK,MAAM;AAC1C,UAAM,KAAK,kBAAkB,cAAc;AAE3C,QAAI,eAAe;AACjB,WAAK,4BAA4B;AAAA,IACnC,OAAO;AACL,WAAK,sBAAsB;AAAA,IAC7B;AAEA,UAAM,KAAK,WAAW;AAAA,EACxB;AAAA,EAEA,MAAc,kBAAkB,EAAE,MAAM,GAA8B;AACpE,QAAI;AACF,UACE,OAAO,UAAU,cACjB,MAAM,SAAS,YACf,MAAM,SAAS,SAAS,gCACxB;AACA,cAAM,EAAE,yBAAyB,0BAA0B,IACzD,MAAM,SAAS;AAGjB,YACE,MAAM,SAAS,YACf,CAACC,YAAW,yBAAyB,yBAAyB,GAC9D;AACA,gBAAM,KAAK,cAAc,MAAM,SAAS,UAAU,IAAI;AAAA,QACxD;AAAA,MACF,WAAW,OAAO,UAAU,aAAa,MAAM,QAAQ,SAAS;AAC9D,cAAM,UAAU,MAAM,QAAQ;AAC9B,cAAM,aAAa,MAAM,KAAK,OAAO,OAAO;AAAA,UAC1CC,QAAO,QAAQ,EAAE;AAAA,QACnB;AAEA,cAAM,UAAU,MAAM,KAAK,gBAAgB;AAAA,UACzC;AAAA,UACA;AAAA,QACF;AACA,cAAM,KAAK,qBAAqB,QAAQ,OAAO,UAAU;AACzD,aAAK;AAAA,UACH;AAAA,UACA,QAAQ;AAAA,WACP,MAAM,KAAK,WAAW,GAAG;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,0BAA0B,KAAK;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAgB,wBAAwB;AACtC,UAAM,cAAc;AACpB,UAAM,gBAAgB;AACtB,UAAM,YAAY;AAElB,SAAK,mBAAmB,IAAI,gBAAgB;AAE5C,UAAM,QAAQ,CAAC,IAAY,WAA2C;AACpE,aAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,cAAM,QAAQ,WAAW,MAAM;AAC7B,cAAI,QAAQ;AACV,mBAAO,oBAAoB,SAAS,OAAO;AAAA,UAC7C;AACA,kBAAQ,IAAI;AAAA,QACd,GAAG,EAAE;AAEL,iBAAS,UAAU;AACjB,uBAAa,KAAK;AAClB,kBAAQ,KAAK;AACb,kBAAQ,oBAAoB,SAAS,OAAO;AAAA,QAC9C;AAEA,YAAI,QAAQ;AACV,iBAAO,iBAAiB,SAAS,OAAO;AAAA,QAC1C;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,aAAa;AACjB,WAAO,cAAc,aAAa;AAChC,UAAI;AACF,cAAM,UAAU,KAAK,OAAO,sBAAsB;AAElD,cAAM,cACJ,MAAM,KAAK,kBAAkB,wBAAwB,OAAO;AAC9D,cAAM,UAAU,MAAM,KAAK,kBAAkB,iBAAiB,OAAO;AAErE,cAAM,SAAS,YAAY;AAAA,UACzB;AAAA,YACE,mBAAmB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,UACnE;AAAA,UACA;AAAA,YACE,QAAQ,KAAK,kBAAkB;AAAA,UACjC;AAAA,QACF;AAYA,cAAM,aAAa,MAAM;AACvB,gBAAM,kBAAmB,QAAgB;AACzC,cACE,iBAAiB,eAAe,YAAY,OAAO,WAC/C,SAAS,QACb;AACA,4BAAgB,cAAc,WAAW,MAAM,UAAU,QAAQ,OAAO,MAAM;AAAA,UAChF,OAAO;AACL,uBAAW,YAAY,GAAG;AAAA,UAC5B;AAAA,QACF;AAIA,YAAI,QAAQ;AACV,qBAAW;AAAA,QACb;AAEA,cAAM,sBAAsB,MAAM,KAAK,eAAe;AAEtD,YAAI;AACF,2BAAiB,QAAQ,QAAQ;AAC/B,gBAAI,KAAK,kBAAkB,OAAO,SAAS;AACzC;AAAA,YACF;AAEA,gBAAI,KAAK,OAAO,UAAU,aAAa;AACrC,sBAAQ,IAAI,WAAW;AACvB,mBAAK,KAAK,kBAAkB;AAC5B,2BAAa;AAAA,YACf;AAEA,gBACE,KAAK,OAAO,UAAU,cACtB,KAAK,MAAM,SAAS,YACpB,oBAAoB,SAAS,KAAK,MAAM,SAAS,SAAS,EAAE,GAC5D;AACA;AAAA,YACF;AACA,kBAAM,KAAK,kBAAkB,IAAI;AAAA,UACnC;AAAA,QACF,SAAS,OAAO;AACd,gBAAM;AAAA,QACR;AAAA,MACF,SAAS,OAAO;AACd,YAAI,KAAK,kBAAkB,OAAO,SAAS;AACzC;AAAA,QACF;AAEA,cAAM,eAAe,KAAK;AAAA,UACxB,gBAAgB,KAAK,IAAI,GAAG,UAAU;AAAA,UACtC;AAAA,QACF;AAEA,YAAI,aAAa,aAAa;AAC5B;AACA,eAAK;AAAA,YACH;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UACvD;AACA,cAAI;AACF,kBAAM,YAAY,MAAM;AAAA,cACtB;AAAA,cACA,KAAK,kBAAkB;AAAA,YACzB;AACA,gBAAI,CAAC,WAAW;AACd;AAAA,YACF;AAAA,UACF,SAASC,QAAO;AACd,gBAAI,KAAK,kBAAkB,OAAO,SAAS;AACzC;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,eAAK,KAAK,uBAAuB,mCAAmC;AACpE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YAAiC;AAC7C,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AACA,UAAM,SAAS,MAAM,YAAY,YAAY;AAAA,MAC3C,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,qBAAqB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACrE;AAAA,MACA,gBAAgB;AAAA,IAClB,CAAC;AAED,WAAO,OAAO,QAAQ,OAAO,KAAK,EAC/B,OAAO,CAAC,CAAC,GAAG,IAAI,MAAM,KAAK,WAAW,WAAW,EACjD,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,IAAI;AAAA,EAC5B;AAAA,EAEA,MAAc,aAAa,cAA2C;AACpE,QAAI,gBAAgB,GAAG;AACrB,YAAM,IAAI,gBAAgB,kCAAkC;AAAA,QAC1D,OAAO;AAAA,QACP,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,QAAI,OAAO,WAAW,GAAG;AACvB,YAAM,IAAI,gBAAgB,yBAAyB;AAAA,QACjD,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEvC,QAAI,SAAS;AACb,QAAI,QAAoB,CAAC;AACzB,eAAW,QAAQ,QAAQ;AACzB,UAAI,eAAe,UAAU,KAAK,OAAO;AACvC,kBAAU,KAAK;AACf,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAEA,QAAI,WAAW,cAAc;AAC3B,YAAM,KAAK,kBAAkB,EAAE,aAAa,CAAC;AAE7C,eAAS;AACT,cAAQ,CAAC;AACT,YAAM,YAAY,MAAM,KAAK,UAAU;AACvC,gBAAU,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC1C,iBAAW,QAAQ,WAAW;AAC5B,YAAI,eAAe,UAAU,KAAK,OAAO;AACvC,oBAAU,KAAK;AACf,gBAAM,KAAK,IAAI;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC,MAAM,cAAc;AACrE,YAAM,IAAI;AAAA,QACR,6CAA6C,YAAY;AAAA,MAC3D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,oBAAoB,cAAsB;AACtD,QAAI,gBAAgB,GAAG;AACrB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,UAAM,SAAS,MAAM,KAAK,UAAU;AACpC,WAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEvC,QAAI,SAAS;AACb,UAAM,QAAoB,CAAC;AAC3B,eAAW,QAAQ,QAAQ;AACzB,UAAI,SAAS,cAAc;AACzB,kBAAU,KAAK;AACf,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAEA,QAAI,SAAS,cAAc;AACzB,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,uBAAuB;AAC7B,UAAM,cAAc,KAAK,mBAAmB;AAE5C,QAAI,KAAK,OAAO,UAAU,GAAG;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,sBAAsB,KAAK,KAAK,MAAM,WAAW;AAEvD,QAAI,kBAAkB;AACtB,QAAI,sBAAsB;AAE1B,aAAS,IAAI,qBAAqB,KAAK,GAAG,KAAK;AAC7C,YAAM,eAAe,KAAK;AAC1B,aAAO,mBAAmB,cAAc;AACtC,2BAAmB;AACnB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,OAAO,SAAS,sBAAsB;AAAA,EACpD;AAAA,EAEA,MAAc,iBAAiB;AAC7B,QAAI,KAAK,0BAA0B,CAAC,KAAK,qBAAqB,GAAG;AAC/D;AAAA,IACF;AAEA,UAAM,KAAK,WAAW,YAAY;AAChC,WAAK,yBAAyB;AAC9B,UAAI;AACF,YAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,gBAAM,KAAK,kBAAkB,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,QACtD;AACA,aAAK,SAAS,MAAM,KAAK,UAAU;AAAA,MACrC,UAAE;AACA,aAAK,yBAAyB;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,aAAa;AACzB,UAAM,KAAK,iBAAiB;AAC5B,SAAK,SAAS,MAAM,KAAK,UAAU;AACnC,UAAM,KAAK,OAAO,OAAO,4BAA4B,KAAK,MAAM;AAChE,UAAM,KAAK,0BAA0B;AACrC,UAAM,KAAK,yBAAyB;AACpC,SAAK,eAAe,EAAE,MAAM,CAAC,MAAM;AACjC,cAAQ,MAAM,6BAA6B,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,WAAc,WAAyC;AACnE,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ;AAC/C,QAAI;AACF,aAAO,MAAM,UAAU;AAAA,IACzB,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,uBAAwC;AACnD,WAAOC,YAAW,MAAM,KAAK,OAAO,OAAO,qBAAqB,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,kBAA+C;AAC1D,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe,mBAAmB;AAAA,QACrC,mBAAmBA;AAAA,UACjB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QAChD;AAAA,QACA,SAAS,KAAK,OAAO,eAAe;AAAA,MACtC,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAgB,WACd,gBACA,eACyC;AACzC,QAAI,kBAAkB,KAAK,kBAAkB,GAAG;AAE9C,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AACA,QAAI;AACJ,QAAI,CAAC,gBAAgB;AACnB,iBAAW,MAAM,KAAK,OAAO,OAAO,iBAAiB;AACrD,uBAAiB;AAAA,IACnB;AAEA,QAAI;AACJ,QAAI,OAAO,mBAAmB,UAAU;AACtC,aAAO;AAAA,IACT,OAAO;AACL,UAAI,iBAAiB,gBAAgB,QAAQ,GAAG;AAC9C,mBAAW;AACX,eAAO,MAAM,KAAK,OAAO,OAAO,eAAe,cAAc;AAAA,MAC/D,OAAO;AACL,eAAOC,YAAW,cAAc;AAAA,MAClC;AAAA,IACF;AACA,UAAM,KAAK,mBAAmB,MAAM,aAAa;AAEjD,UAAM,UAAU,KAAK,OAAO,WAAW;AAEvC,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAOA,YAAW,IAAI;AAAA,IACxB;AAEA,UAAM,QAAQ,uBAAuB,IAAI;AAEzC,QAAI,CAAC,MAAM,cAAc,CAAC,MAAM,WAAW;AACzC,YAAM,IAAI,gBAAgB,mCAAmC;AAAA,QAC3D,OAAO;AAAA,QACP,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,UAAM,iBAAiB,8BAA8B,IAAI;AACzD,UAAM,cAAc,MAAM;AAAA,MACxB,cAAc,iBAAiB,cAAc;AAAA;AAAA,IAC/C;AACA,SAAK,cAAc,IAAI;AAAA,MACrBD,YAAW,YAAY,UAAW;AAAA,MAClC,mBAAmB,OAAO;AAAA,MAC1B,wBAAwB,OAAO;AAAA,MAC/B,KAAK,OAAO;AAAA,IACd;AAEA,QAAI,QAAQ;AACV,YAAM,KAAK,iBAAiB,KAAK,QAAQ;AACzC,WAAK,2BAA2B;AAAA,IAClC;AAEA,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,mBACZ,MACA,eACA;AACA,UAAM,oBACJ,MAAM,KAAK,OAAO,OAAO;AAAA,MACvB;AAAA,MACA,KAAK,OAAO,WAAW;AAAA,MACvB;AAAA,IACF;AACF,UAAM,KAAK,iBAAiB;AAE5B,SAAK,eAAe,mBAAmB;AAAA,MACrC;AAAA,MACA,SAAS,KAAK,OAAO,eAAe;AAAA,IACtC,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,mBACX,YACsC;AACtC,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,MAAM,KAAK,UAAU,mBAAmB,UAAU;AACtE,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,kBAAkB;AAAA,IAC9B;AAAA,IACA;AAAA,EACF,GAGG;AACD,QAAI,gBAAgB,gBAAgB,GAAG;AACrC,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AAEA,QAAI,gBAAgB,CAAC,OAAO,cAAc,YAAY,GAAG;AACvD,YAAM,IAAI,gBAAgB,uCAAuC;AAAA,QAC/D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,QAAI;AACF,YAAM,KAAK,eAAe;AAAA,IAC5B,SAAS,GAAG;AACV,cAAQ,KAAK,6BAA6B;AAAA,IAC5C;AAEA,QAAI;AACJ,QAAI,gBAAgB,UAAU,OAAO,SAAS,GAAG;AAC/C,UAAI,eAAe,OAAO,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC,GAAG;AACpE,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC/D;AACA,qBAAe;AAAA,IACjB,WAAW,cAAc;AACvB,qBAAe,MAAM,KAAK,oBAAoB,YAAY;AAAA,IAC5D,WAAW,UAAU,OAAO,SAAS,GAAG;AACtC,qBAAe;AAAA,IACjB,OAAO;AACL,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,UAAM,gBAAgB,MAAM,QAAQ;AAAA,MAClC,aAAa,IAAI,OAAO,UAAU;AAAA,QAChC;AAAA,QACA,eAAe,MAAM,KAAK,OAAO,OAAO;AAAA,UACtCF,QAAO,KAAK,EAAE;AAAA,QAChB;AAAA,QACA,kBAAkB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,MAC/D,EAAE;AAAA,IACJ;AAEA,UAAM,EAAE,UAAU,aAAa,IAC7B,MAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACAG,YAAW,KAAK,OAAO,wBAAwB,CAAC;AAAA,MAChD,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAI;AAAA,IACrC;AACF,QAAI;AACF,UAAI,CAAC,SAAS,OAAO,CAAC,GAAG,MAAM;AAC7B,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAEA,YAAM,kBAAkB,aAAa,IAAI,SAAS,OAAO,CAAC,EAAE,KAAK,EAAE;AACnE,UAAI,CAAC,iBAAiB;AACpB,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AAEA,YAAM,EAAE,mBAAmB,iBAAiB,IAC1C,6BAA6B,eAAe;AAE9C,UAAI,CAAC,SAAS,OAAO,CAAC,EAAE,MAAM;AAC5B,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAEA,YAAM,aAA8B,CAAC;AACrC,iBAAW,KAAK;AAAA,QACd,SAAS,SAAS,OAAO,CAAC,EAAE,KAAK;AAAA,QACjC,iCAAiCD;AAAA,UAC/B,SAAS,OAAO,CAAC,EAAE;AAAA,QACrB;AAAA,QACA,yBAAyBA,YAAW,gBAAgB;AAAA,MACtD,CAAC;AAED,eAAS,IAAI,GAAG,IAAI,SAAS,OAAO,QAAQ,KAAK;AAC/C,cAAM,OAAO,SAAS,OAAO,CAAC;AAC9B,YAAI,CAAC,MAAM,MAAM;AACf,gBAAM,IAAI,MAAM,oBAAoB;AAAA,QACtC;AAEA,cAAME,mBAAkB,aAAa,IAAI,KAAK,KAAK,EAAE;AACrD,YAAI,CAACA,kBAAiB;AACpB,gBAAM,IAAI,MAAM,gCAAgC;AAAA,QAClD;AAEA,cAAM,YAAY;AAAA,UAChBA;AAAA,UACA;AAAA,QACF;AAEA,mBAAW,KAAK;AAAA,UACd,SAAS,KAAK,KAAK;AAAA,UACnB,iCAAiCF;AAAA,YAC/B,KAAK;AAAA,UACP;AAAA,UACA,yBAAyBA,YAAW,SAAS;AAAA,QAC/C,CAAC;AAAA,MACH;AAEA,YAAM,gBAAgBA;AAAA,QACpBG,WAAU,aAAa,iBAAiB;AAAA,MAC1C;AACA,UAAI,UAAgD;AACpD,gBAAU,MAAM,KAAK,WAAW,iBAAiB;AAAA,QAC/C;AAAA,QACA;AAAA,QACA,kBACE,gBACA,aAAa,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC;AAAA,QACxD,iBAAiB,aAAa;AAAA,UAC5B,CAAC,KAAK,SAAS,MAAM,KAAK;AAAA,UAC1B;AAAA,QACF;AAAA;AAAA,QAEA,SAAS;AAAA,QACT,gBAAgBC,QAAO;AAAA,MACzB,CAAC;AAED,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,sDAAsD;AAAA,MACxE;AAEA,YAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,QAC/C,KAAK,OAAO,sBAAsB;AAAA,MACpC;AAEA,YAAM,QAAQ,MAAM,YAAY,YAAY;AAAA,QAC1C,QAAQ;AAAA,UACN,OAAO;AAAA,UACP,SAAS;AAAA,YACP,SAAS,QAAQ,WAAW,IAAI,CAAC,SAAS,KAAK,MAAM;AAAA,UACvD;AAAA,QACF;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAED,UAAI,OAAO,OAAO,MAAM,KAAK,EAAE,WAAW,QAAQ,WAAW,QAAQ;AACnE,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC/D;AAEA,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,KAAK,GAAG;AACxD,YAAI,CAAC,KAAK,QAAQ;AAChB,gBAAM,IAAI,MAAM,8BAA8B,MAAM,EAAE;AAAA,QACxD;AAEA,YAAI,CAAC,KAAK,oBAAoB;AAC5B,gBAAM,IAAI,MAAM,sCAAsC,MAAM,EAAE;AAAA,QAChE;AAEA,cAAM,OAAO,QAAQ,WAAW,KAAK,CAACC,UAASA,MAAK,WAAW,MAAM;AACrE,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI,MAAM,2BAA2B,MAAM,EAAE;AAAA,QACrD;AAGA,cAAM,SAAS,oBAAoB,KAAK,MAAM;AAC9C,cAAM,gBAAgBJ,YAAW,KAAK,4BAA4B;AAClE,cAAM,WAAW,oBAAoB,aAAa;AAClD,cAAM,UAAU,iBAAiB,UAAU,GAAG,OAAO,UAAU,CAAC,CAAC;AAEjE,cAAM,gBAAgB,KAAK;AAE3B,cAAM,aAAa,0BAA0B,cAAc,MAAM,CAAC,CAAC;AACnE,cAAM,wBAAwBA,YAAW,KAAK,sBAAsB;AACpE;AAAA,UACE,WAAW,MAAM,CAAC;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,mBAAmB,MAAM,KAAK,WAAW,kBAAkB;AAAA,QAC/D,kBAAkBD,YAAW,iBAAiB;AAAA,QAC9C,gCAAgC,SAAS;AAAA,QACzC,qBAAqB,QAAQ;AAAA,MAC/B,CAAC;AAED,UAAI,CAAC,kBAAkB;AACrB,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AAEA,YAAM,KAAK,oCAAwC;AAEnD,aAAO;AAAA,IACT,SAAS,GAAG;AACV,YAAM,KAAK,kCAAkC;AAC7C,YAAM,IAAI,MAAM,kCAAkC,CAAC,EAAE;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,aACX,QAAgB,IAChB,SAAiB,GAIhB;AACD,UAAM,YAAY,MAAM,KAAK,gBAAgB;AAAA,MAC3C;AAAA,MACA;AAAA,IACF;AACA,UAAM,oBAAoBA;AAAA,MACxB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,IAChD;AACA,WAAO;AAAA,MACL,WAAW,UAAU,UAAU;AAAA,QAAI,CAAC,aAClC,4BAA4B,UAAU,iBAAiB;AAAA,MACzD;AAAA,MACA,QAAQ,UAAU;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,eAAqC;AAChD,YAAQ,KAAK,qDAAqD;AAElE,UAAM,KAAK,iBAAiB;AAE5B,UAAM,cAAc,MAAM,KAAK,uBAAuB,kBAAkB;AACxE,UAAM,EAAE,SAAS,cAAc,IAAI,MAAM,KAAK,WAAW;AAEzD,UAAM,YAAY,MAAM,YAAY,mBAAmB;AAAA,MACrD,YAAY,MAAM,KAAK,cAAc,KAAK,CAAC,EAAE,IAAIC,WAAU;AAAA,IAC7D,CAAC;AAED,WAAO,UAAU,iBAAiB,IAAI,CAAC,UAAU;AAAA,MAC/C,gBAAgBD,YAAW,KAAK,aAAc,UAAW,SAAS;AAAA,MAClE,WAAW,KAAK,aAAc;AAAA,MAC9B,aAAa,KAAK,aAAc;AAAA,MAChC,eAAe,OAAOM,iBAAgB,KAAK,aAAc,OAAO,CAAC;AAAA,MACjE,WAAWA,iBAAgB,KAAK,aAAc,SAAS;AAAA,IACzD,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,aAGV;AACD,SAAK,SAAS,MAAM,KAAK,UAAU;AACnC,UAAM,KAAK,iBAAiB;AAE5B,QAAI;AAEJ,QAAI,KAAK,aAAa,SAAS,GAAG;AAChC,sBAAgB,MAAM,KAAK,gBAAgB;AAAA,IAC7C,OAAO;AACL,sBAAgB,oBAAI,IAGlB;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,OAAO,KAAK,mBAAmB,CAAC;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,kBAEZ;AACA,UAAM,cAAc,MAAM,KAAK,uBAAuB,kBAAkB;AAGxE,UAAM,YAAY,MAAM,YAAY,mBAAmB;AAAA,MACrD,YAAY,MAAM,KAAK,KAAK,aAAa,KAAK,CAAC,EAAE,IAAIL,WAAU;AAAA,IACjE,CAAC;AAED,UAAM,SAAS,oBAAI,IAAuD;AAE1E,eAAW,QAAQ,UAAU,kBAAkB;AAC7C,YAAM,iBAAiBD;AAAA,QACrB,KAAK,aAAc,UAAW;AAAA,MAChC;AACA,YAAM,SAAS,KAAK,aAAa,IAAI,cAAc;AAEnD,aAAO,IAAI,gBAAgB;AAAA,QACzB,SAAS,SAAS,8BAA8B,MAAM,IAAI,OAAO,CAAC;AAAA,QAClE,WAAW;AAAA,UACT;AAAA,UACA,WAAW,KAAK,aAAc;AAAA,UAC9B,aAAa,KAAK,aAAc;AAAA,UAChC,eAAe,OAAOM,iBAAgB,KAAK,aAAc,OAAO,CAAC;AAAA,UACjE,WAAWA,iBAAgB,KAAK,aAAc,SAAS;AAAA,QACzD;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAA6B;AACnC,WAAO,KAAK,OAAO,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAa,6BAA8C;AACzD,WAAO,MAAM,KAAK,uBAAuB;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,yBAA0C;AACtD,UAAM,SAASF,QAAO;AACtB,UAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO;AAAA,MAC7CN,QAAO,MAAM;AAAA,IACf;AACA,UAAM,UAAU,MAAM,KAAK,eAAgB,uBAAuB;AAAA,MAChE;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,CAAC,QAAQ,gBAAgB;AAC3B,YAAM,IAAI,SAAS,sCAAsC;AAAA,QACvD,QAAQ;AAAA,QACR,QAAQ,EAAE,eAAe,OAAO;AAAA,MAClC,CAAC;AAAA,IACH;AACA,WAAO,QAAQ,eAAe;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,gBAAgB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAkB;AAChB,QAAI,CAAC,OAAO,cAAc,IAAI,GAAG;AAC/B,YAAM,IAAI,gBAAgB,+BAA+B;AAAA,QACvD,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,UAAM,MAAM,MAAM,KAAK,eAAgB,eAAe;AAAA,MACpD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,iBAA6B,CAAC;AACpC,eAAW,QAAQ,IAAI,OAAO;AAC5B,UAAI,KAAK,WAAW,aAAa;AAC/B,cAAM,EAAE,MAAM,IAAI,MAAM,KAAK,gBAAgB;AAAA,UAC3C;AAAA,UACA;AAAA,QACF;AAEA,mBAAW,KAAK,OAAO;AACrB,cAAI,EAAE,WAAW,aAAa;AAC5B,kBAAM,WAAW,MAAM,KAAK;AAAA,cAC1B,CAAC,CAAC;AAAA,cACF;AAAA,YACF;AACA,2BAAe,KAAK,GAAG,QAAQ;AAAA,UACjC,OAAO;AACL,2BAAe,KAAK,CAAC;AAAA,UACvB;AAAA,QACF;AAAA,MACF,OAAO;AACL,uBAAe,KAAK,IAAI;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,4BAA+C;AAC1D,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AACA,YACE,MAAM,YAAY,+BAA+B;AAAA,MAC/C,mBAAmB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,IACnE,CAAC,GACD,iBAAiB,IAAI,CAAC,SAAS,KAAK,cAAc;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,aAAa,MAAqC;AAC7D,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,gBAAgB,kCAAkC;AAAA,QAC1D,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,QAAI,QAAQ,KAAK,QAAQ,IAAI,IAAI;AACjC,QAAI,CAAC,OAAO;AACV,cAAQ,IAAI,MAAM;AAClB,WAAK,QAAQ,IAAI,MAAM,KAAK;AAAA,IAC9B;AAEA,UAAM,QAAQ,MAAM,MAAM,aAAa,YAAY;AACjD,YAAM,UAAU,KAAK,OAAO,cAAc;AAC1C,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,MAClB;AAEA,UAAI;AAEJ,UAAI,KAAK,OAAO,WAAW,qBAAqB;AAC9C,cAAM,cAAc,cAAc,YAAY;AAC9C,cAAM,WAAW,MAAM,YAAY,kBAAkB,IAAI;AACzD,gBAAQ,SAAS;AAAA,MACnB,OAAO;AACL,YAAI,KAAK,OAAO,WAAW,uBAAuB;AAChD,gBAAM,OAAO;AAAA,YACX,GAAG,oBAAoB,QAAQ,IAAI,oBAAoB,QAAQ;AAAA,UACjE;AACA,kBAAQ,eAAe,IAAI,SAAS,IAAI;AAAA,QAC1C;AAEA,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,OAAO,IAAI,QAAQ;AAAA,UACxD;AAAA,QACF,CAAC;AAED,gBAAQ,MAAM,SAAS,KAAK;AAAA,MAC9B;AAEA,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,UAAI,CAAC,iBAAiB,KAAK,KAAK,GAAG;AACjC,cAAM,IAAI,gBAAgB,2BAA2B;AAAA,UACnD,OAAO;AAAA,UACP,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,YAAM,YAAY,kBAAkB,KAAK;AAEzC,YAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,QAC/C,KAAK,OAAO,sBAAsB;AAAA,MACpC;AAEA,YAAM,yBACJ,IAAI;AAAA,SAEA,MAAM,YAAY,+BAA+B;AAAA,UAC/C,mBACE,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,QAClD,CAAC,GACD,iBAAiB,IAAI,CAAC,SAAS,CAAC,KAAK,gBAAgB,IAAI,CAAC;AAAA,MAC9D;AAEF,UAAI;AACJ,UAAI,OAAO;AACX,eAAS,IAAI,GAAG,IAAI,UAAU,eAAe,KAAK;AAChD,cAAM,SAAS,UAAU,UAAU,CAAC;AACpC,YAAI,CAAC,QAAQ;AACX;AAAA,QACF;AACA,cAAM,eAAeS,WAAU,OAAO,OAAO,MAAO;AACpD,cAAM,UAAUC,SAAQ,WAAW,KAAK,OAAO,WAAW,CAAC,CAAC,EAAE;AAAA,UAC5D;AAAA,QACF;AACA,YAAI,uBAAuB,IAAI,OAAO,GAAG;AACvC,iBAAO;AACP,2BAAiB,uBAAuB,IAAI,OAAO;AACnD;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,gBAAgB;AACnB,cAAM,IAAI,gBAAgB,yCAAyC;AAAA,UACjE,OAAO;AAAA,UACP,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,UAAI;AACJ,UAAI,CAAC,eAAe,QAAQ;AAC1B,wBAAgB,eAAe;AAAA,MACjC,OAAO;AACL,wBAAgB,MAAM,KAAK,OAAO,OAAO;AAAA,UACvCV,QAAO,eAAe,MAAM;AAAA,QAC9B;AAAA,MACF;AAEA,YAAMW,SAAQ,MAAM,KAAK,gBAAgB;AAAA,QACvC;AAAA,QACA,cAAc,eAAe;AAAA,QAC7B;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAOA;AAAA,IACT,CAAC;AAED,SAAK,QAAQ,OAAO,IAAI;AAExB,WAAO,MAAM,IAAI,uBAAuB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,gBAAgB,OAAe;AAC1C,UAAM,YAAY,kBAAkB,KAAK;AACzC,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AACA,UAAM,yBACJ,IAAI;AAAA,OAEA,MAAM,YAAY,+BAA+B;AAAA,QAC/C,mBAAmB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MACnE,CAAC,GACD,iBAAiB,IAAI,CAAC,SAAS,CAAC,KAAK,gBAAgB,IAAI,CAAC;AAAA,IAC9D;AAEF,QAAI,OAAO;AACX,UAAM,YAAwB,CAAC;AAC/B,aAAS,IAAI,GAAG,IAAI,UAAU,eAAe,KAAK;AAChD,YAAM,SAAS,UAAU,UAAU,CAAC;AACpC,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AACA,YAAM,eAAeF,WAAU,OAAO,OAAO,MAAO;AACpD,YAAM,UAAUC,SAAQ,WAAW,KAAK,OAAO,WAAW,CAAC,CAAC,EAAE;AAAA,QAC5D;AAAA,MACF;AACA,YAAM,uBAAuB,uBAAuB,IAAI,OAAO;AAC/D,UAAI,sBAAsB;AACxB,eAAO;AACP,cAAM,WAAW,MAAM,KAAK,eAAgB,eAAe;AAAA,UACzD,eAAe,qBAAqB;AAAA,UACpC,cAAc,qBAAqB;AAAA,UACnC;AAAA,UACA;AAAA,QACF,CAAC;AACD,kBAAU,KAAK,GAAG,SAAS,KAAK;AAAA,MAClC;AAAA,IACF;AACA,QAAI,UAAU,WAAW,GAAG;AAC1B,YAAM,IAAI;AAAA,QACR,2CAA2C,QAAQ,SAAS,CAAC;AAAA,MAC/D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,qBACZ,QACA,eACqB;AACrB,UAAM,gBAAgB,MAAM,QAAQ;AAAA,MAClC,OAAO,IAAI,OAAO,UAAU;AAAA,QAC1B;AAAA,QACA;AAAA,QACA,kBAAkB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,MAC/D,EAAE;AAAA,IACJ;AAEA,UAAM,WAAW,MAAM,KAAK,gBAAgB;AAAA,MAC1C;AAAA,MACA,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,IAChD;AAEA,UAAM,cAAc,MAAM,KAAK,cAAc,QAAQ;AAErD,UAAM,iBAAiB,IAAI,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAC5D,SAAK,SAAS;AAAA,MACZ,GAAG,KAAK,OAAO,OAAO,CAAC,SAAS,CAAC,eAAe,IAAI,KAAK,EAAE,CAAC;AAAA,MAC5D,GAAG;AAAA,IACL;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,SAAS;AAAA,IACpB;AAAA,IACA;AAAA,EACF,GAA4C;AAC1C,QAAI,CAAC,sBAAsB;AACzB,YAAM,IAAI,gBAAgB,0CAA0C;AAAA,QAClE,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,OAAO,cAAc,UAAU,GAAG;AACrC,YAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,QAAI,cAAc,GAAG;AACnB,YAAM,IAAI,gBAAgB,iCAAiC;AAAA,QACzD,OAAO;AAAA,QACP,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,UAAM,kBAAkB;AAAA,MACtB;AAAA,MACA,KAAK,OAAO,eAAe;AAAA,IAC7B;AAEA,UAAM,iBAAiBX;AAAA,MACrB,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MAC9CI,YAAW,eAAe;AAAA,IAC5B;AAEA,WAAO,MAAM,KAAK,WAAW,YAAY;AACvC,UAAI,eAAe,MAAM,KAAK,aAAa,UAAU;AAErD,YAAM,KAAK,0BAA0B,YAAY;AACjD,qBAAe,MAAM,KAAK,yBAAyB,YAAY;AAE/D,YAAM,gBAAgB,MAAM,QAAQ;AAAA,QAClC,aAAa,IAAI,OAAO,UAAU;AAAA,UAChC;AAAA,UACA,eAAe,MAAM,KAAK,OAAO,OAAO;AAAA,YACtCH,QAAO,KAAK,EAAE;AAAA,UAChB;AAAA,UACA,kBAAkB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,QAC/D,EAAE;AAAA,MACJ;AAEA,YAAM,WAAW,MAAM,KAAK,gBAAgB;AAAA,QAC1C;AAAA,QACAG,YAAW,eAAe;AAAA,MAC5B;AAEA,YAAM,iBAAiB,IAAI,IAAI,aAAa,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAClE,WAAK,SAAS,KAAK,OAAO,OAAO,CAAC,SAAS,CAAC,eAAe,IAAI,KAAK,EAAE,CAAC;AAGvE,UAAI,gBAAgB;AAClB,cAAM,KAAK,cAAc,QAAQ;AAAA,MACnC;AAEA,aAAO;AAAA,QACL;AAAA,QACAD,YAAW,MAAM,KAAK,OAAO,OAAO,qBAAqB,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,yBACZ,OACqB;AACrB,UAAM,eAAe,SAAS,KAAK;AACnC,UAAM,gBAA4B,CAAC;AACnC,UAAM,UAAoB,CAAC;AAC3B,QAAI,cAAc,CAAC,GAAG,YAAY;AAElC,eAAW,QAAQ,cAAc;AAC/B,YAAM,SAAS,oBAAoB,KAAK,MAAM;AAC9C,YAAM,EAAE,YAAY,IAAI;AAAA,QACtB,OAAO,SAAS,CAAC,EAAE;AAAA,MACrB;AACA,UAAI,aAAa;AACf,sBAAc,KAAK,IAAI;AACvB,gBAAQ,KAAK,KAAK,EAAE;AAAA,MACtB;AAAA,IACF;AAEA,kBAAc,YAAY,OAAO,CAAC,SAAS,CAAC,cAAc,SAAS,IAAI,CAAC;AAExE,eAAW,QAAQ,eAAe;AAChC,YAAM,gBAAgB,MAAM,KAAK,OAAO,OAAO;AAAA,QAC7CF,QAAO,KAAK,EAAE;AAAA,MAChB;AACA,YAAM,EAAE,OAAAW,OAAM,IAAI,MAAM,KAAK,gBAAgB;AAAA,QAC3C;AAAA,QACA;AAAA,MACF;AACA,WAAK,SAAS,KAAK,OAAO,OAAO,CAAC,SAAS,KAAK,OAAO,KAAK,EAAE;AAC9D,YAAM,WAAW,MAAM,KAAK,qBAAqBA,QAAO,aAAa;AACrE,kBAAY,KAAK,GAAG,QAAQ;AAAA,IAC9B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,0BAA0B,OAAoB;AAC1D,UAAM,iBAA6B,CAAC;AACpC,UAAM,UAAoB,CAAC;AAE3B,eAAW,QAAQ,SAAS,KAAK,QAAQ;AACvC,YAAM,WAAW,oBAAoB,KAAK,QAAQ;AAClD,YAAM,EAAE,YAAY,IAAI;AAAA,QACtB,SAAS,SAAS,CAAC,EAAE;AAAA,QACrB;AAAA,MACF;AACA,UAAI,aAAa;AACf,uBAAe,KAAK,IAAI;AACxB,gBAAQ,KAAK,KAAK,EAAE;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,eAAe,WAAW,GAAG;AAC/B;AAAA,IACF;AAEA,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,UAAM,YAAY,MAAM,YAAY,YAAY;AAAA,MAC9C,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,UACP;AAAA,QACF;AAAA,MACF;AAAA,MACA,gBAAgB;AAAA,IAClB,CAAC;AAED,UAAM,WAAW,oBAAI,IAAsB;AAC3C,eAAW,QAAQ,OAAO,OAAO,UAAU,KAAK,GAAG;AACjD,eAAS,IAAI,KAAK,IAAI,IAAI;AAAA,IAC5B;AAEA,eAAW,QAAQ,gBAAgB;AACjC,UAAI,CAAC,KAAK,cAAc;AACtB,cAAM,IAAI,MAAM,QAAQ,KAAK,EAAE,gBAAgB;AAAA,MACjD;AAEA,YAAM,aAAa,SAAS,IAAI,KAAK,YAAY;AACjD,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,eAAe,KAAK,YAAY,YAAY;AAAA,MAC9D;AAEA,YAAM,EAAE,OAAAA,OAAM,IAAI,MAAM,KAAK,gBAAgB;AAAA,QAC3C,CAAC,IAAI;AAAA,QACL;AAAA,QACA,MAAM,KAAK,OAAO,OAAO,kBAAkBX,QAAO,KAAK,EAAE,CAAC;AAAA,MAC5D;AAEA,UAAIW,OAAM,WAAW,GAAG;AACtB,cAAM,IAAI,MAAM,wBAAwBA,OAAM,MAAM,EAAE;AAAA,MACxD;AAEA,YAAM,UAAUA,OAAM,CAAC;AACvB,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,iCAAiC;AAAA,MACnD;AAEA,WAAK,SAAS,KAAK,OAAO,OAAO,CAAC,SAAS,KAAK,OAAO,KAAK,EAAE;AAC9D,WAAK,OAAO,KAAK,OAAO;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,cACZ,UACA,OAAgB,OAChB,aAAqB,GACrB;AACA,UAAM,cAAc;AACpB,UAAM,gBAAgB;AACtB,UAAM,eAAe;AAErB,QAAI,aAAa,GAAG;AAClB,YAAM,UAAU,KAAK;AAAA,QACnB,gBAAgB,KAAK,IAAI,GAAG,aAAa,CAAC;AAAA,QAC1C;AAAA,MACF;AACA,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,OAAO,CAAC;AAAA,IAC7D;AACA,QAAI;AACF,UAAI,SAAS,MAAM,KAAK,mBAAmB,aAAa,YAAY;AAClE,cAAM,gBACJ,MAAM,KAAK,gBAAgB,sBAAsB,QAAQ;AAE3D,YAAI,gBAAgC,CAAC;AAErC,mBAAW,QAAQ,SAAS,QAAQ;AAClC,cAAI,KAAK,MAAM;AACb,kBAAM,aAAa,cAAc,IAAI,KAAK,KAAK,EAAE;AACjD,gBAAI,YAAY;AACd,4BAAc,KAAK;AAAA,gBACjB,MAAM,KAAK;AAAA,gBACX,eAAe;AAAA,gBACf,kBAAkB,MAAM,KAAK,OAAO,OAAO;AAAA,kBACzCX,QAAO,KAAK,KAAK,EAAE;AAAA,gBACrB;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,KAAK,gBAAgB;AAAA,UAC1C;AAAA,UACA;AAAA,QACF;AAEA,aAAK,OAAO,KAAK,GAAG,SAAS,KAAK;AAElC,YAAI,MAAM;AACR,eAAK;AAAA,YACH;AAAA,YACA,SAAS;AAAA,aACR,MAAM,KAAK,WAAW,GAAG;AAAA,UAC5B;AAAA,QACF;AAEA,eAAO,SAAS;AAAA,MAClB,CAAC;AAED,YAAM,KAAK,0BAA0B,MAAM;AAC3C,eAAS,MAAM,KAAK,yBAAyB,MAAM;AAEnD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,aAAa,aAAa;AAC5B,gBAAQ,MAAM,yCAAyC,KAAK;AAC5D,aAAK,cAAc,UAAU,MAAM,aAAa,CAAC;AACjD,eAAO,CAAC;AAAA,MACV,WAAW,aAAa,GAAG;AACzB,gBAAQ,MAAM,4BAA4B,KAAK;AAC/C,eAAO,CAAC;AAAA,MACV,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,YACE,WAAW;AAAA,YACX,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC/D;AAAA,UACA,iBAAiB,QAAQ,QAAQ;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,eACZ,MACA,MACmB;AACnB,UAAM,YAAY,MAAM,KAAK,gBAAgB,sBAAsB;AACnE,UAAM,WAAqC,CAAC;AAC5C,eAAW,YAAY,UAAU,WAAW;AAC1C,UAAI,QAAQ,SAAS,SAAS,MAAM;AAClC;AAAA,MACF;AAEA,UACE,SAAS,yDACT,SAAS,2DAET,SAAS,4DAET;AACA;AAAA,MACF;AACA,eAAS;AAAA,QACP,KAAK,cAAc,UAAU,IAAI,EAC9B,KAAK,MAAM,SAAS,EAAE,EACtB,MAAM,CAAC,UAAU;AAChB,kBAAQ,KAAK,4BAA4B,SAAS,EAAE,KAAK,KAAK;AAC9D,iBAAO;AAAA,QACT,CAAC;AAAA,MACL;AAAA,IACF;AACA,UAAM,UAAU,MAAM,QAAQ,WAAW,QAAQ;AACjD,WAAO,QACJ;AAAA,MACC,CAAC,WAAW,OAAO,WAAW,eAAe,OAAO,UAAU;AAAA,IAChE,EACC,IAAI,CAAC,WAAY,OAA0C,KAAK;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oCAAoC;AAChD,eAAW,YAAY,OAAO,OAAO,KAAK,OAAO,oBAAoB,CAAC,GAAG;AACvE,YAAM,YACJ,MAAM,KAAK,gBAAgB;AAAA,QACzB,SAAS;AAAA,MACX;AAEF,iBAAW,YAAY,UAAU,WAAW;AAC1C,YACE,SAAS,qDACT;AACA,gBAAM,KAAK,gBAAgB,eAAe,UAAU,SAAS,OAAO;AAAA,QACtE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAa,uBAAuB;AAAA,IAClC;AAAA,IACA;AAAA,IACA,gBAAgB,KAAK,KAAK,KAAK;AAAA,EACjC,GAAmE;AACjE,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,QAAI,MAAM,UAAU,KAAK,aAAa,GAAG;AACvC,YAAM,IAAI,gBAAgB,kBAAkB;AAAA,QAC1C,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,OAAO,cAAc,UAAU,GAAG;AACrC,YAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,OAAO,cAAc,aAAa,GAAG;AACxC,YAAM,IAAI,gBAAgB,0CAA0C;AAAA,QAClE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,QAAI,gBAAgB,GAAG;AACrB,YAAM,IAAI,gBAAgB,2BAA2B;AAAA,QACnD,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,QAAI,QAAQ,KAAK,SAAS,KAAK;AAC7B,YAAM,IAAI,gBAAgB,qBAAqB;AAAA,QAC7C,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,UAAM,0BAA0B,OAC9BY,aACA,aACAC,UACG;AACH,YAAM,UAAU,KAAK,OAAO,WAAW;AACvC,UAAI,iBAAiC,uBAAe;AACpD,UAAI,6BAA6B;AAC/B,yBAAiB,uBAAe;AAAA,MAClC,WAAW,6BAA6B;AACtC,yBAAiB,uBAAe;AAAA,MAClC;AAEA,YAAMC,WAAU,MAAM,KAAK,UAAW,wBAAwB;AAAA,QAC5D,YAAAF;AAAA,QACA,SAAS;AAAA,QACT,aAAaV,YAAW,WAAW;AAAA,QACnC,YAAY;AAAA,QACZ,MAAAW;AAAA,MACF,CAAC;AAED,aAAOC;AAAA,IACT;AAEA,UAAM,UAAU,MAAM,KAAK,iBAAkB,uBAAuB;AAAA,MAClE;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,IAClB,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,oBAAoB;AAAA,IAC/B;AAAA,IACA;AAAA,EACF,GAA8B;AAC5B,WAAO,MAAM,KAAK,WAAW,YAAY;AACvC,UAAI,CAAC,KAAK,WAAW;AACnB,cAAM,IAAI,mBAAmB,8BAA8B;AAAA,UACzD,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAEA,YAAM,iBAAiBC,QAAO,OAAO;AACrC,YAAM,aACJ;AAAA,QACE,eAAe,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,QAAQ,GAC/D;AAAA,MACN,IAAI;AAEN,UAAI,MAAM,UAAU,KAAK,cAAc,GAAG;AACxC,cAAM,IAAI,gBAAgB,kBAAkB;AAAA,UAC1C,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAEA,YAAM,cAAc,eAAe,SAAS;AAAA,QAC1C,CAAC,YAAY,QAAQ,SAAS;AAAA,MAChC,GAAG;AAEH,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,gBAAgB,oCAAoC;AAAA,UAC5D,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,YAAM,cAAc,MAAM,KAAK,4BAA4B;AAAA,QACzD,gBAAgB;AAAA,MAClB,CAAC;AAED,UAAI,aAAa,aAAa;AAC5B,cAAM,IAAI,gBAAgB,0CAA0C;AAAA,UAClE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU,GAAG,WAAW;AAAA,QAC1B,CAAC;AAAA,MACH;AAEA,YAAM,cAAc,aAAa;AAEjC,YAAM,kBAAkB,KAAK,mBAAmB;AAChD,UAAI,cAAc,iBAAiB;AACjC,cAAM,IAAI,gBAAgB,wBAAwB;AAAA,UAChD,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU,GAAG,WAAW;AAAA,QAC1B,CAAC;AAAA,MACH;AAEA,UAAI,SAAS,MAAM,KAAK,aAAa,WAAW;AAEhD,YAAM,KAAK,0BAA0B,MAAM;AAC3C,eAAS,MAAM,KAAK,yBAAyB,MAAM;AAEnD,YAAM,eAAe,MAAM,QAAQ;AAAA,QACjC,OAAO,IAAI,OAAO,UAAU;AAAA,UAC1B;AAAA,UACA,eAAe,MAAM,KAAK,OAAO,OAAO;AAAA,YACtCf,QAAO,KAAK,EAAE;AAAA,UAChB;AAAA,UACA,kBAAkB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,QAC/D,EAAE;AAAA,MACJ;AAEA,YAAM,eAAe,MAAM,KAAK,iBAAiB,qBAAqB;AAAA,QACpE,QAAQ;AAAA,QACR,wBAAwBG;AAAA,UACtB,KAAK,OAAO,wBAAwB;AAAA,QACtC;AAAA,QACA,aAAaA,YAAW,WAAW;AAAA,QACnC,kBAAkB;AAAA,QAClB,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC;AAED,UAAI,CAAC,aAAa,UAAU;AAC1B,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,YAAM,WAAW,MAAM,KAAK,gBAAgB;AAAA,QAC1C,aAAa;AAAA,QACb;AAAA,QACA,oBAAI,IAAI;AAAA,MACV;AAEA,YAAM,cAAc,MAAM,KAAK,UAAU,qBAAqB;AAAA,QAC5D,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB,CAAC;AAED,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,iBAAiB,IAAI,IAAI,aAAa,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;AACvE,WAAK,SAAS,KAAK,OAAO,OAAO,CAAC,SAAS,CAAC,eAAe,IAAI,KAAK,EAAE,CAAC;AAEvE,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,4BAA4B;AAAA,IACvC;AAAA,EACF,GAAmD;AACjD,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,UAAM,cACJ,MAAM,KAAK,UAAU,4BAA4B,cAAc;AAEjE,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,UAAM,kBAAkB,kBAAkB,YAAY,WAAW;AACjE,WAAO,KAAK,KAAK,gBAAgB,IAAI;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAc,8BACZ,MACA,qBACA,UACA,YACA;AACA,WAAO,MAAM,KAAK,oBAAqB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,WACZ,MACA,MACA,cACA,UACA,YACA;AACA,WAAO,MAAM,KAAK,oBAAqB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,SAAS;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,QAAI,CAAC,OAAO,cAAc,UAAU,GAAG;AACrC,YAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AACA,WAAO,MAAM,KAAK,WAAW,YAAY;AACvC,aAAO,MAAM,KAAK,SAAS,gBAAgB,WAAW,UAAU;AAAA,IAClE,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,SACZ,gBACA,WACA,kBACA;AACA,QAAI,CAAC,OAAO,cAAc,gBAAgB,GAAG;AAC3C,YAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,QAAI,eAA2B,CAAC;AAChC,QAAI,kBAAkB;AACpB,qBAAe,MAAM,KAAK,aAAa,gBAAgB;AAAA,IACzD,OAAO;AACL,qBAAe,KAAK,OAAO,IAAI,CAAC,UAAU;AAAA,QACxC,GAAG;AAAA,MACL,EAAE;AAAA,IACJ;AAEA,UAAM,cAAc,MAAM,KAAK,WAAW,uBAAuB;AAAA,MAC/D,iBAAiB,aAAa,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,MACnD,mBAAmB;AAAA,IACrB,CAAC;AAED,QAAI,aAAa;AACf,UAAI;AACJ,cAAQ,WAAW;AAAA,QACjB,KAAK,kBAAU;AACb,iBACG,YAAY,WAAW,eAAe,iBAAiB,MACvD,YAAY,WAAW,QAAQ,iBAAiB;AACnD;AAAA,QACF,KAAK,kBAAU;AACb,iBACG,YAAY,aAAa,eAAe,iBAAiB,MACzD,YAAY,aAAa,QAAQ,iBAAiB;AACrD;AAAA,QACF,KAAK,kBAAU;AACb,iBACG,YAAY,WAAW,eAAe,iBAAiB,MACvD,YAAY,WAAW,QAAQ,iBAAiB;AACnD;AAAA,QACF;AACE,gBAAM,IAAI,gBAAgB,sBAAsB;AAAA,YAC9C,OAAO;AAAA,YACP,OAAO;AAAA,YACP,UAAU;AAAA,UACZ,CAAC;AAAA,MACL;AAEA,UACE,QAAQ,UACR,MAAM,aAAa,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC,GAC5D;AACA,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,0BAA0B,YAAY;AACjD,mBAAe,MAAM,KAAK,yBAAyB,YAAY;AAE/D,UAAM,gBAAgB,MAAM,QAAQ;AAAA,MAClC,aAAa,IAAI,OAAO,UAAU;AAAA,QAChC;AAAA,QACA,eAAe,MAAM,KAAK,OAAO,OAAO;AAAA,UACtCH,QAAO,KAAK,EAAE;AAAA,QAChB;AAAA,QACA,kBAAkB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,MAC/D,EAAE;AAAA,IACJ;AAEA,UAAM,kBAAkB,MAAM,KAAK,WAAW,gBAAgB;AAAA,MAC5D,iBAAiB,aAAa,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,MACnD,mBAAmB;AAAA,MACnB,gBAAgBM,QAAO;AAAA,MACvB;AAAA,IACF,CAAC;AAED,QAAI,CAAC,iBAAiB,yBAAyB;AAC7C,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,cAAc;AAAA,MAClB,gBAAgB;AAAA,IAClB;AAEA,UAAM,eAAe,YAAY,SAAS,CAAC,EAAE;AAC7C,UAAM,gBAAgB,QAAQ,WAAW;AAEzC,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AAEA,UAAM,mBAAuC,CAAC;AAC9C,aAAS,IAAI,GAAG,IAAI,YAAY,gBAAgB,GAAG,KAAK;AACtD,uBAAiB,KAAK;AAAA,QACpB,MAAMH,YAAW,aAAa;AAAA,QAC9B,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,UAAM,oBAAoBA,YAAW,KAAK,OAAO,wBAAwB,CAAC;AAC1E,UAAM,WAAW,MAAM,KAAK,gBAAgB,6BAA6B;AAAA,MACvE,QAAQ;AAAA,MACR,UAAU;AAAA,MACV;AAAA,MACA,gBAAgB;AAAA,IAClB,CAAC;AAED,UAAM,mBAAmB,MAAM,KAAK,WAAW,iBAAiB;AAAA,MAC9D,gCAAgC,SAAS,SAAS;AAAA,MAClD,mBAAmB,gBAAgB;AAAA,IACrC,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,yBAAyB;AAAA,IACpC;AAAA,IACA;AAAA,EACF,GAG+C;AAC7C,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,OAAO,cAAc,UAAU,GAAG;AACrC,YAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,yBAAyB,OAAO;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,QAAI,SAAS,MAAM,KAAK,aAAa,UAAU;AAE/C,UAAM,KAAK,0BAA0B,MAAM;AAC3C,aAAS,MAAM,KAAK,yBAAyB,MAAM;AAEnD,UAAM,cAAc,MAAM,KAAK,UAAU,uBAAuB;AAAA,MAC9D,iBAAiB,OAAO,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAgB,mBAAmB;AACjC,SAAK,aAAa,MAAM;AAExB,UAAM,uBACJ,MAAM,KAAK,wBAAwB;AAAA,MACjC,CAAC,MAAM,KAAK,OAAO,OAAO,qBAAqB,CAAC;AAAA,MAChD,CAAC;AAAA,IACH;AAEF,UAAM,uBAAuB,qBAAqB;AAAA,MAChD,CAAC,WACC,CAAC,KAAK,0BAA0B,SAAS,OAAO,QAAQ,MAAM,EAAE;AAAA,IACpE;AAEA,UAAM,mBAAmB,IAAI;AAAA,MAC3B,qBAAqB,IAAI,CAAC,WAAW,OAAO,QAAQ,EAAE,EAAE,OAAO,OAAO;AAAA,IACxE;AACA,SAAK,4BAA4B,KAAK,0BAA0B;AAAA,MAC9D,CAAC,OAAO,iBAAiB,IAAI,EAAE;AAAA,IACjC;AAGA,UAAM,iBAAiB,oBAAI,IAGzB;AAEF,yBAAqB,QAAQ,CAAC,WAAW;AACvC,YAAM,WAAWD,YAAW,OAAO,OAAQ,cAAe;AAC1D,YAAM,QAAQ,OAAO;AAErB,UAAI,CAAC,eAAe,IAAI,QAAQ,GAAG;AACjC,uBAAe,IAAI,UAAU,CAAC,CAAC;AAAA,MACjC;AAEA,qBAAe,IAAI,QAAQ,EAAG,KAAK;AAAA,QACjC,GAAG;AAAA,QACH,yBAAyB;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAED,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,eAAe;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAKoB;AAClB,UAAM,KAAK,iBAAiB;AAE5B,WAAO,KAAK,wBAAwB;AAAA,MAClC,KAAK;AAAA,MACL;AAAA,QACE;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,oBACX,iBAKA,iBACiB;AACjB,QAAI,gBAAgB,WAAW,GAAG;AAChC,YAAM,IAAI,gBAAgB,4CAA4C;AAAA,QACpE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AACA,UAAM,sBAAsB,gBAAgB,CAAC,EAAG;AAChD,UAAM,eAAe,gBAAgB;AAAA,MACnC,CAAC,WAAW,OAAO,mBAAmB;AAAA,IACxC;AACA,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK,iBAAiB;AAE5B,WAAO,KAAK,wBAAwB;AAAA,MAClC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,uBACX,iBACA,wBACuC;AACvC,UAAM,cAAc,MAAM,KAAK,kBAAkB;AAAA,MAC/C,KAAK,OAAO,sBAAsB;AAAA,IACpC;AAEA,QAAI;AACJ,QAAI,wBAAwB,QAAQ;AAClC,oBAAc;AAAA,QACZ,iBAAiB,iBAAiB,IAAIC,WAAU;AAAA,QAChD,iBAAiB,CAACA,YAAW,MAAM,KAAK,qBAAqB,CAAC,CAAC;AAAA,QAC/D,wBAAwB,uBAAuB,IAAIA,WAAU;AAAA,MAC/D;AAAA,IACF,OAAO;AACL,oBAAc;AAAA,QACZ,iBAAiB,iBAAiB,IAAIA,WAAU;AAAA,QAChD,iBAAiB,CAACA,YAAW,MAAM,KAAK,qBAAqB,CAAC,CAAC;AAAA,MACjE;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,YAAY,yBAAyB,WAAW;AACvE,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,MAAa,oBAAqC;AAChD,WAAO;AAAA,MACL,MAAM,KAAK,OAAO,OAAO,qBAAqB;AAAA,MAC9C,KAAK,OAAO,WAAW;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,2BACX,SACA,SACiB;AACjB,UAAM,OAAOH,QAAO,OAAO;AAC3B,UAAM,YAAY,MAAM,KAAK,OAAO,OAAO;AAAA,MACzC;AAAA,MACA;AAAA,IACF;AACA,WAAOE,YAAW,SAAS;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,+BACX,SACA,WACkB;AAClB,UAAM,OAAOF,QAAO,OAAO;AAC3B,QAAI,OAAO,cAAc,UAAU;AACjC,kBAAYG,YAAW,SAAS;AAAA,IAClC;AACA,WAAO,KAAK,OAAO,OAAO,+BAA+B,MAAM,SAAS;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,2BACX,IACyC;AACzC,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,WAAO,MAAM,KAAK,UAAU,2BAA2B,EAAE;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,wBACX,IACsC;AACtC,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,WAAO,MAAM,KAAK,UAAU,wBAAwB,EAAE;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,mBAAmB,IAA6C;AAC3E,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,mBAAmB,8BAA8B;AAAA,QACzD,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,WAAO,MAAM,KAAK,UAAU,mBAAmB,EAAE;AAAA,EACnD;AAAA,EAEQ,UAAU;AAChB,QAAI,KAAK,wBAAwB;AAC/B,oBAAc,KAAK,sBAAsB;AACzC,WAAK,yBAAyB;AAAA,IAChC;AACA,SAAK,kBAAkB,MAAM;AAC7B,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAa,qBAAqB;AAChC,SAAK,QAAQ;AACb,UAAM,KAAK,kBAAkB,iBAAiB;AAAA,EAChD;AAAA;AAAA,EAGQ,8BAA8B;AAEpC,QAAI,KAAK,wBAAwB;AAC/B,oBAAc,KAAK,sBAAsB;AAAA,IAC3C;AAIA,SAAK,yBAAyB,YAAY,YAAY;AACpD,UAAI;AACF,cAAM,KAAK,eAAe,QAAW,IAAI;AAAA,MAC3C,SAAS,OAAO;AACd,gBAAQ,MAAM,wCAAwC,KAAK;AAAA,MAC7D;AAAA,IACF,GAAG,GAAK;AAAA,EACV;AACF;","names":["bytesToHex","bytesToNumberBE","equalBytes","hexToBytes","secp256k1","Address","OutScript","sha256","decode","uuidv7","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","FRAGMENT","Transaction","uuidv7","bytesToHex","sha256","bytesToHex","sha256","crypto","Transaction","uuidv7","hexToBytes","numberToBytesBE","secp256k1","sha256","uuidv7","crypto","numberToBytesBE","secp256k1","sha256","uuidv7","hexToBytes","Transaction","sha256","INITIAL_TIME_LOCK","sha256","Transaction","bytesToHex","hexToBytes","secp256k1","Address","OutScript","Transaction","hexToBytes","secp256k1","Transaction","bytesToHex","Address","OutScript","crypto","equalBytes","sha256","error","bytesToHex","hexToBytes","refundSignature","secp256k1","uuidv7","leaf","bytesToNumberBE","OutScript","Address","nodes","amountSats","memo","invoice","decode"]}