diff --git a/lazer/cardano/hermes/README.md b/lazer/cardano/hermes/README.md new file mode 100644 index 00000000..d47e9f07 --- /dev/null +++ b/lazer/cardano/hermes/README.md @@ -0,0 +1,81 @@ +# Team "Los Hydra Boys" Pythathon Submission + +## Details + +Team Name: Los Hydra Boys +Submission Name: Hermes Market +Team Members: Ignacio Dopazo (@ignaciodopazo), Nicolás Ludueña (@nicolasLuduena), Valentino Cerutti (@Micrograx) +Contact: luduena.nicolas.victorio@gmail.com + +## Project Description + +Hermes market is a proof of concept integration of Pyth oracle information with Cardano's bleeding edge L2 [Hydra](https://hydra.family/head-protocol) that allows for real time bets on BTC price. Therefore truly giving an edge over a simple 5 minute market with up to 2 minute block finality in the L1 on the worst cases. Even on mainnet with high congestion scenarios, block confirmation is not guaranteed after several days. + +## Motivation + +Cardano is a powerful and very secure blockchain, but slow for the fast transactions: Cardano's consensus algorithm, while efficient, still requires massive global replication of state changes, potentially increasing transaction settlement times during peak hours. For our use case, we require real-time transaction settlement times. + +For solving this issue, we rely on Hydra L2 to provide the speed and scalability we need for this project. Hydra L2 is a layer 2 solution that is built on top of Cardano and provides a low-latency, high-throughput, and secure way to process transactions. + +For the Oracle service, we use Pyth, a service provider of real-time price feeds for various kinds of assets. For this PoC, we built a 5-minute prediction market for BTC/USD trading pair. + +## Architecture + +### Onchain + +We designed an Aiken smart contract for managing the markets lifecycle and the bets placed on them through the orders script. + +There are several operations that can be performed on the market script: +- Create a new market: every 5 minutes, a new market UTxOis created associated with a fresh order script. +- Place Buy or Sell order: a user can place a buy or sell order for receiving the appropriate position tokens. +- Record the final price of the market: the oracle service will record the final price in the market UTxO. +- Claim winnings: a winning user can claim the winnings by providing the position tokens. +- Claim losses: user provide their losing tokens for being burned. +- Close the market: the market is closed by burning the Market UTxO control token. +- Process an orders match: grab complementary orders from opposite directions, and distribute the tokens appropriately. + +You can find the diagrams for all these transactions [here](./doc/transactions.pdf) + +### Infrastructure + +Two Hydra nodes required for running one Hydra Head in offline mode. We declare the initial UTxO set for the Hydra chain, inject the appropriate scripts and assets for working with the Pyth oracle service. + +### Server & Offchain + +The server encompasses the prediction market business logic for interacting with the onchain scripts, and with the offchain services that interact with the Pyth oracle service and builds the Market script transactions. Also, we have a Hydra service that connects seamlessly with the Hydra nodes for sending and receiving transactions, and looking up for useful blockchain information. + +### Client + +The client is a simple React application to visualize the current prediction market state, with real-time updates coming from the server being shown in a nice real-time udpated chart, with buy and sell orders being shown as well. It also allows to place buy and sell orders, and to claim winnings or losses. + +### Limitations + +A key limitation for this PoC is that we use Hydra in offline mode, which means that the Hydra nodes are not connected to a Cardano Node, but we just declar a initial UTxO set for the Hydra chain. For using Pyth within Hydra in this offline mode setup, we "inject" the Pyth-related onchain entities (withdraw validator and Pyth State asset) in the initial UTxO set. + +But for a production deployment in a public testnet or mainnet, the part of injecting the Pyth-related onchain entities on the Hydra initial UTxO set presents a real challenge. We would need to spend the UTxO containing the Pyth State asset for being commited to the Hydra chain. Naturally, the Pyth contract will not allow this to happen. + +So for this idea to work in a public testnet or mainnet, either an update of the Pyth contract is needed, or an update of the Hydra protocol is needed for supporting L1 UTxOs as reference inputs (no spending allowed) inside the Hydra Head. This would be sufficient since the UTxO holding the Pyth State asset is only needed as reference inputs in the Oracle operations. + +## Tech Stack + +- App: Vite + React + TailwindCSS +- Server: Node.js + WebSocket +- Infrastructure: Docker compose, Hydra +- Onchain: Aiken, [Pyth Lazer Aiken lib](https://github.com/pyth-network/pyth-lazer-cardano) +- Offchain: Lucid Evolution + +## Setup & Run + +1. Run the infrastructure: see [infra/README.md](./infra/README.md) +2. Run the server +```bash +cd server +pnpm install +pnpm api +``` +3. Run the UI +```bash +cd ui +pnpm install +pnpm dev +``` \ No newline at end of file diff --git a/lazer/cardano/hermes/doc/report.typ b/lazer/cardano/hermes/doc/report.typ new file mode 100644 index 00000000..cf667230 --- /dev/null +++ b/lazer/cardano/hermes/doc/report.typ @@ -0,0 +1,229 @@ +// Transaction diagrams + +#let tx_out_height_estimate(input) = { + let address = if "address" in input { 1 } else { 0 } + let value = if "value" in input { input.value.len() } else { 0 } + let datum = if "datum" in input { input.datum.len() } else { 0 } + return (address + value + datum) * 8pt +} + +#let datum_field(indent, k, val) = [ + #if val == "" [ + #h(indent)\+ #raw(k) + ] else [ + #h(indent)\+ #raw(k): + #if type(val) == content { val } + #if type(val) == str and val != "" { repr(val) } + #if type(val) == int { repr(val) } + #if type(val) == array [ + #stack(dir: ttb, spacing: 0.4em, for item in val [ + #datum_field(indent + 1.2em, "", item) \ + ]) + ] + #if type(val) == dictionary [ + #v(-0.7em) + #stack(dir: ttb, spacing: 0em, for (k, v) in val.pairs() [ + #datum_field(indent + 1.2em, k, v) \ + ]) + ] + ] +] + +#let tx_out(input, position, inputHeight) = { + let address = if "address" in input [ + *Address: #h(0.5em) #input.address* + ] else [] + let value = if "value" in input [ + *Value:* #if ("ada" in input.value) [ *#input.value.ada* ADA ] \ + #v(-1.0em) + #stack(dir: ttb, spacing: 0.4em, ..input + .value + .pairs() + .map(((k, v)) => [ + #if k != "ada" [ + #h(2.3em) \+ + #if type(v) == content { math.bold(v) } + #if type(v) == str and v != "" [*#v*] + #k + ] + ])) + ] else [] + let datum = if "datum" in input [ + *Datum:* \ + #v(-0.8em) + #stack(dir: ttb, spacing: 0.4em, ..input.datum.pairs().map(((k, val)) => datum_field(1.2em, k, val))) + ] else [] + let addressHeight = measure(address).height + if "address" in input { 6pt } else { 0pt } + let valueHeight = measure(value).height + if "value" in input { 6pt } else { 0pt } + let datumHeight = measure(datum).height + if "datum" in input { 6pt } else { 0pt } + let thisHeight = 32pt + addressHeight + valueHeight + datumHeight + + if "dots" in input { + return ( + content: place(dx: position.x, dy: position.y, [ + #place(dx: 4em, dy: -1em)[*.*] + #place(dx: 4em, dy: 0em)[*.*] + #place(dx: 4em, dy: 1em)[*.*] + ]), + height: thisHeight, + ) + } else { + return ( + content: place(dx: position.x, dy: position.y, [ + *#input.name* + #line(start: (-4em, -1em), end: (10em, -1em), stroke: red) + #place(dx: 10em, dy: -1.5em)[#circle(radius: 0.5em, fill: white, stroke: red)] + #if "address" in input { place(dx: 0em, dy: -3pt)[#address] } + #place(dx: 0em, dy: addressHeight)[#value] + #if "datum" in input { place(dx: 0em, dy: addressHeight + valueHeight)[#datum] } + ]), + height: thisHeight, + ) + } +} + +#let vanilla_transaction( + name, + inputs: (), + outputs: (), + signatures: (), + certificates: (), + withdrawals: (), + mint: (:), + validRange: none, + notes: none, +) = context { + let inputHeightEstimate = inputs.fold(0pt, (sum, input) => sum + tx_out_height_estimate(input)) + let inputHeight = 0em + let inputs = [ + #let start = (x: -18em, y: 1em) + #for input in inputs { + let tx_out = tx_out(input, start, inputHeight) + + tx_out.content + + // Now connect this output to the transaction + if not "dots" in input { + place(dx: start.x + 10.5em, dy: start.y + 0.84em)[ + #let lineStroke = if input.at("reference", default: false) { + (paint: blue, thickness: 1pt, dash: "dashed") + } else { blue } + #line(start: (0em, 0em), end: (7.44em, 0em), stroke: lineStroke) + ] + place(dx: start.x + 10.26em, dy: start.y + 0.59em)[#circle(radius: 0.25em, fill: blue)] + } + if input.at("redeemer", default: none) != none { + place(dx: start.x + 12.26em, dy: start.y - 0.2em)[#input.at("redeemer")] + } + + start = (x: start.x, y: start.y + tx_out.height) + inputHeight += tx_out.height + } + ] + + let outputHeightEstimate = outputs.fold(0pt, (sum, output) => sum + tx_out_height_estimate(output)) + let outputHeight = 0em + let outputs = [ + #let start = (x: 4em, y: 1em) + #for output in outputs { + let tx_out = tx_out(output, start, outputHeight) + tx_out.content + start = (x: start.x, y: start.y + tx_out.height) + outputHeight += tx_out.height + } + ] + + // Collapse down the `mint` array + let display_mint = (:) + for (k, v) in mint { + let display = [] + if type(v) == int { + // the provided value is an integer + if v == 0 { + continue + } else if v > 0 { + display += [ \+ ] + } else if v < 0 { + display += [ \- ] + } + display += [#calc.abs(v)] + } else { + // the provided value can be a letter or variable name + if type(v) == str and v.starts-with("-") { + display += [\- #v.slice(1)] + } else { + display += [\+ #v] + } + } + display += [ #raw(k)] + display_mint.insert(k, display) + } + + let mints = if display_mint.len() > 0 [ + *Mint:* \ + #for (k, v) in display_mint [ + #v \ + ] + ] else [] + let sigs = if signatures.len() > 0 [ + *Signatures:* \ + #for signature in signatures [ + - #signature + ] + ] else [] + let certs = if certificates.len() > 0 [ + *Certificates:* + #for certificate in certificates [ + - #certificate + ] + ] else [] + let withs = if withdrawals.len() > 0 [ + *Withdrawals:* + #for withdrawal in withdrawals [ + - #withdrawal + ] + ] else [] + let valid_range = if validRange != none [ + *Valid Range:* \ + #if "lower" in validRange [#validRange.lower $<=$ ] + `slot` + #if "upper" in validRange [$<=$ #validRange.upper] + ] else [] + + let boxHeight = { + 100pt + 32pt * (mint.len() + certificates.len() + signatures.len()) + 40pt * withdrawals.len() + } + + let transaction = [ + #set align(center) + #rect( + radius: 4pt, + height: calc.max(boxHeight, inputHeight + 16pt, outputHeight + 16pt), + [ + #pad(top: 1em, name) + #v(1em) + #set align(left) + #stack(dir: ttb, spacing: 1em, mints, sigs, certs, withs, valid_range) + ], + ) + ] + + let diagram = stack(dir: ltr, inputs, transaction, outputs) + let size = measure(diagram) + block(width: 100%)[ + #set align(center) + #diagram + #set align(left) + #if notes != none [ + #box( + width: 100%, + fill: rgb("f0f0f0"), + stroke: 0.5pt + black, + inset: 8pt, + )[ + #set text(size: 9pt) + *Notes*: #notes + ] + ] + ] +} diff --git a/lazer/cardano/hermes/doc/transactions.pdf b/lazer/cardano/hermes/doc/transactions.pdf new file mode 100644 index 00000000..8afb04ed Binary files /dev/null and b/lazer/cardano/hermes/doc/transactions.pdf differ diff --git a/lazer/cardano/hermes/doc/transactions.typ b/lazer/cardano/hermes/doc/transactions.typ new file mode 100644 index 00000000..cc364699 --- /dev/null +++ b/lazer/cardano/hermes/doc/transactions.typ @@ -0,0 +1,575 @@ +#import "report.typ": * + +#let tx_create_market = vanilla_transaction( + "Create Market", + mint: ( + "Control Token": 1, + ), + inputs: ( + ( + reference: true, + name: "Pyth State", + value: ( + "Pyth NFT": 1, + ), + datum: ( + "Pyth Datum": ("...":"", "withdraw_script":"") + ), + ), + ( name: "Seed UTxO" ) + ), + outputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `None`, + remainingShares: 0 + ), + ), + ), + withdrawals: ("withdraw_script",), + // TODO: Think about this + validRange: (lower: "time", upper: "time + 4.5 minutes"), + notes: [ + startValue should be provided by the oracle + ] +) + +#tx_create_market + +#pagebreak() + +#let tx_record_close_price = vanilla_transaction( + "Record Close Price", + inputs: ( + ( + reference: true, + name: "Pyth State", + value: ( + "Pyth NFT": 1, + ), + datum: ( + "Pyth Datum": ("...":"", "withdraw_script":"") + ), + ), + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `None`, + remainingShares: "X" + ), + redeemer: [#h(-1.5em)"RecordClosePrice"] + ), + ), + outputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `Some(P')`, + remainingShares: "X" + ), + ), + ), + withdrawals: ("withdraw_script",), + // TODO: Think about this + validRange: (lower: "endTimestamp"), + notes: [ + endValue should be provided by the oracle + ] +) + +#tx_record_close_price + +#pagebreak() + +#let tx_claim_winnings = vanilla_transaction( + "Claim Winnings", + inputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": `M` + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `Some(P')`, + remainingShares: "X" + ), + redeemer: [#h(-1.5em)"ClaimWinnings"] + ), + ( + name: "User UTxO", + value: ( + "PositionToken": "C", + ), + ) + ), + outputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": `M - C` + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `Some(P')`, + remainingShares: "X - C" + ), + ), + ( + name: "User UTxO", + value: ( + "ADA": "C", + ), + ) + ), + mint: ( + "PositionToken": "-C" + ), + notes: [ + if P' >= P { PositionToken = "UP" } \ + else { PositionToken = "DOWN"} + ] +) + +#tx_claim_winnings + +#pagebreak() + +#let tx_claim_losings = vanilla_transaction( + "Claim Losing", + inputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": `M` + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `Some(P')`, + remainingShares: "X" + ), + redeemer: [#h(-1.5em)"ClaimLosings"] + ), + ( + name: "User UTxO", + value: ( + "PositionToken": "C", + ), + ) + ), + outputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": `M` + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `Some(P')`, + remainingShares: "X - C" + ), + ), + ), + mint: ( + "PositionToken": "-C" + ), + notes: [ + if P' < P { PositionToken = "UP" } \ + else { PositionToken = "DOWN"} + ] +) + +#tx_claim_losings + +#pagebreak() + +#let tx_close_market = vanilla_transaction( + "Close Market", + inputs: ( + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": `M` + ), + datum: ( + startTimestamp: `time`, + startValue: "P", + endTimestamp: `time + 5 minutes`, + endValue: `Some(P')`, + remainingShares: "0" + ), + redeemer: [Close] + ), + ), + outputs: ( + ( + name: "User UTxO", + value: ( + "ADA": "M", + ), + ), + ), + +) + +#tx_close_market + +#pagebreak() + +#let tx_place_buy_order = vanilla_transaction( + "Place Buy Order", + mint: ( + "Order Control Token": 1, + ), + inputs: ( + ), + outputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "ADAs": `M`, + ), + datum: ( + owner: `pkh`, + direction: "Up|Down", + operation: `Buy`, + price: `N`, + ), + ), + ), +) + +#tx_place_buy_order + +#let tx_place_sell_order = vanilla_transaction( + "Place Sell Order", + mint: ( + "Order Control Token": 1, + ), + inputs: ( + ), + outputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "UP/DOWN": `M`, + ), + datum: ( + owner: `pkh`, + direction: "Up|Down", + operation: `Sell`, + price: `N`, + ), + ), + ), +) + +#tx_place_sell_order + + +#pagebreak() + +#let tx_complete_fill_order = vanilla_transaction( + "Complete Fill Order", + mint: ( + "Order Control Token": -1, + ), + inputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "offered_token": `N`, + ), + datum: ( + owner: `pkh`, + direction: "Up|Down", + operation: `Sell|Buy`, + price: `P`, + ), + redeemer: ("CompleteFill"), + ), + ( + name: "User UTxO", + value: ( + "asked_token": `M`, + ), + ), + ), + outputs: ( + ( + name: "Order Fill UTxO", + address: "owner", + value: ( + "asked_token": `M`, + ), + ), + ( + name: "User UTxO", + value: ( + "offered_token": `N`, + ), + ), + ), + notes: [If operation == Sell { M = P \* N } else { N = P \* M }], +) + +#tx_complete_fill_order + +#pagebreak() + +#let tx_partial_fill_order = vanilla_transaction( + "Partial Fill Order", + mint: ( + "Order Control Token": -1, + ), + inputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "offered_token": `N`, + ), + datum: ( + owner: `pkh`, + direction: "Up|Down", + operation: `Sell|Down`, + price: `P`, + ), + redeemer: ("PartialFill"), + ), + ( + name: "User UTxO", + value: ( + "asked_token": `M`, + ), + ), + ), + outputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "offered_token": `N - N'`, + ), + datum: ( + owner: `pkh`, + direction: "Up|Down", + operation: `Sell|Down`, + price: `P`, + ), + redeemer: ("FillOrder"), + ), + ( + name: "Order Fill UTxO", + address: "owner", + value: ( + "asked_token": `M`, + ), + ), + ( + name: "User UTxO", + value: ( + "offered_token": `N'`, + ), + ), + ), + notes: [If operation == Sell { M = P \* N' } else { N' = P \* M }], +) + +#tx_partial_fill_order + +#pagebreak() + +#let tx_match_orders = vanilla_transaction( + "Match Orders", + mint: ( + "Order Control Token": "O", + "UP": "N", + "DOWN": "N" + ), + inputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "ADAs": [$N_1$], + ), + datum: ( + owner: [$"pkh"_1$], + direction: "Up", + operation: `Buy`, + price: [$P_1$], + ), + redeemer: ([$R_1$]), + ), + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "ADAs": [$N_2$], + ), + datum: ( + owner: [$"pkh"_2$], + direction: "Down", + operation: `Buy`, + price: [$P_2$], + ), + redeemer: ([$R_2$]), + ), + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": "C" + ), + datum: ( + endTimestamp: `T`, + remainingShares: `X`, + "...": "" + ), + redeemer: "Match" + ), + ), + outputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "ADAs": [N'], + ), + datum: ( + owner: [$"pkh"_n$], + direction: [$D_n$], + operation: `Buy`, + price: [$P_n$], + ), + redeemer: ("PartialMatch"), + ), + ( + name: "Up UTxO", + address: [$"pkh"_1$], + value: ( + "UP": `N`, + ), + ), + ( + name: "Down UTxO", + address: [$"pkh"_2$], + value: ( + "DOWN": `N`, + ), + ), + ( + name: "Market", + address: "market script address", + value: ( + "Control token": "1", + "ADA": "C + N" + ), + datum: ( + endTimestamp: `T`, + remainingShares: `X + 2 * N`, + "...": "" + ), + ), + ), + notes: [ + $ + N = min(N_1, N_2) \ + $ + + If N_1 > N_2 { R1 = PartialMatch; R2 = Match; $"pkh"_n$ = $"pkh"_1$; $D_n$ = Up; $P_n$ = $P_1$; O = -1 } \ + else if N_2 > N_1 { R1 = Match; R2 = PartialMatch; $"pkh"_n$ = $"pkh"_2$; $D_n$ = Down; $P_n$ = $P_2$; O = 1} \ + else { R1 = R2 = Match; O = 2 } + ], +) + +#tx_match_orders + +#pagebreak() + +#let tx_cancel_order = vanilla_transaction( + "Cancel Order", + mint: ( + "Order Control Token": -1, + ), + inputs: ( + ( + name: "Order", + address: "order book address", + value: ( + "Order Control token": "1", + "V": ``, + ), + datum: ( + owner: "pkh", + "...":"" + ), + redeemer: ("Cancel"), + ), + ), + outputs: ( + ( + name: "Owner UTxO", + address: "pkh", + value: ( + "V": ``, + ), + ), + ), + signatures: ("pkh",) +) + +#tx_cancel_order \ No newline at end of file diff --git a/lazer/cardano/hermes/infra/.gitignore b/lazer/cardano/hermes/infra/.gitignore new file mode 100644 index 00000000..f7fceb78 --- /dev/null +++ b/lazer/cardano/hermes/infra/.gitignore @@ -0,0 +1 @@ +persistence \ No newline at end of file diff --git a/lazer/cardano/hermes/infra/README.md b/lazer/cardano/hermes/infra/README.md new file mode 100644 index 00000000..55e106f2 --- /dev/null +++ b/lazer/cardano/hermes/infra/README.md @@ -0,0 +1,16 @@ +# Infrastructure + +Docker Compose stack (Hydra peers + automatic seed tx). + +```bash +cd infra + +# for running the infra +docker compose up -d + +# for reseting infra state +docker compose down -v && rm -rf persistence/ + +# for reset + restart +docker compose down -v && rm -rf persistence/ && docker compose up -d +``` diff --git a/lazer/cardano/hermes/infra/credentials/hydra-funds.addr b/lazer/cardano/hermes/infra/credentials/hydra-funds.addr new file mode 100644 index 00000000..3be26909 --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra-funds.addr @@ -0,0 +1 @@ +addr_test1vzqdn97wxxuem2ukec6fswslmknuj2zlcwhuz2wfqvkdcgq9235ym \ No newline at end of file diff --git a/lazer/cardano/hermes/infra/credentials/hydra-funds.sk b/lazer/cardano/hermes/infra/credentials/hydra-funds.sk new file mode 100644 index 00000000..04598af4 --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra-funds.sk @@ -0,0 +1,5 @@ +{ + "type": "PaymentSigningKeyShelley_ed25519", + "description": "Payment Signing Key", + "cborHex": "5820245120cdf333f8ea69114a2b3f05bcbc0d5c8e8486ca94c020623d5cca822e04" +} diff --git a/lazer/cardano/hermes/infra/credentials/hydra-funds.vk b/lazer/cardano/hermes/infra/credentials/hydra-funds.vk new file mode 100644 index 00000000..bb5e7905 --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra-funds.vk @@ -0,0 +1,5 @@ +{ + "type": "PaymentVerificationKeyShelley_ed25519", + "description": "Payment Verification Key", + "cborHex": "5820216f72947d1b97d56825c5f9f8a2e6f14234c03171853264f2f552a2685b25e0" +} diff --git a/lazer/cardano/hermes/infra/credentials/hydra-peer.sk b/lazer/cardano/hermes/infra/credentials/hydra-peer.sk new file mode 100644 index 00000000..c29acf0c --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra-peer.sk @@ -0,0 +1,5 @@ +{ + "type": "HydraSigningKey_ed25519", + "description": "", + "cborHex": "58200f443860b542a1df129d3ea775f6b04b40a0534ee0bd0a4b69b31966c9743380" +} diff --git a/lazer/cardano/hermes/infra/credentials/hydra-peer.vk b/lazer/cardano/hermes/infra/credentials/hydra-peer.vk new file mode 100644 index 00000000..f4a31386 --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra-peer.vk @@ -0,0 +1,5 @@ +{ + "type": "HydraVerificationKey_ed25519", + "description": "", + "cborHex": "58208d279429c491414c1da80373d38d88141c46c86584a8cca81c2481139b1021b3" +} diff --git a/lazer/cardano/hermes/infra/credentials/hydra.sk b/lazer/cardano/hermes/infra/credentials/hydra.sk new file mode 100644 index 00000000..656fe1f0 --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra.sk @@ -0,0 +1,5 @@ +{ + "type": "HydraSigningKey_ed25519", + "description": "", + "cborHex": "582083139d5660a51960770abd900669899e42c07994925d09ad7e881341ef852392" +} diff --git a/lazer/cardano/hermes/infra/credentials/hydra.vk b/lazer/cardano/hermes/infra/credentials/hydra.vk new file mode 100644 index 00000000..6f64eb0f --- /dev/null +++ b/lazer/cardano/hermes/infra/credentials/hydra.vk @@ -0,0 +1,5 @@ +{ + "type": "HydraVerificationKey_ed25519", + "description": "", + "cborHex": "58204a3fd9c3c461c04bf5b8f83ade43ec89a8dbee1ee261015d564a32fc8595024d" +} diff --git a/lazer/cardano/hermes/infra/docker-compose.yaml b/lazer/cardano/hermes/infra/docker-compose.yaml new file mode 100644 index 00000000..d9be7cf2 --- /dev/null +++ b/lazer/cardano/hermes/infra/docker-compose.yaml @@ -0,0 +1,87 @@ +services: + # Two distinct Hydra parties are required for offline head so the + # initial UTxO snapshot is agreed before L2 txs validate. + hydra-node: + user: "1000:1000" + image: ghcr.io/cardano-scaling/hydra-node:1.3.0 + restart: always + volumes: + - .:/devnet + ports: + - "4011:4011" + - "5011:5011" + - "6011:6011" + command: + [ + "--node-id", "1", + "--api-host", "0.0.0.0", + "--listen", "172.29.88.11:5011", + "--monitoring-port", "6011", + "--api-port", "4011", + "--peer", "172.29.88.12:5012", + "--hydra-signing-key", "/devnet/credentials/hydra.sk", + "--hydra-verification-key", "/devnet/credentials/hydra-peer.vk", + "--persistence-dir", "/devnet/persistence/hydra-node", + "--offline-head-seed", "fafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafa", + "--ledger-protocol-parameters", "/devnet/protocol-parameters.json", + "--initial-utxo", "/devnet/initial-utxo-set.json" + ] + networks: + pythathon_hydra: + ipv4_address: 172.29.88.11 + + hydra-node-peer: + user: "1000:1000" + image: ghcr.io/cardano-scaling/hydra-node:1.3.0 + restart: always + volumes: + - .:/devnet + ports: + - "4012:4012" + - "5012:5012" + - "6012:6012" + command: + [ + "--node-id", "2", + "--api-host", "0.0.0.0", + "--listen", "172.29.88.12:5012", + "--monitoring-port", "6012", + "--api-port", "4012", + "--peer", "172.29.88.11:5011", + "--hydra-signing-key", "/devnet/credentials/hydra-peer.sk", + "--hydra-verification-key", "/devnet/credentials/hydra.vk", + "--persistence-dir", "/devnet/persistence/hydra-node-peer", + "--offline-head-seed", "fafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafa", + "--ledger-protocol-parameters", "/devnet/protocol-parameters.json", + "--initial-utxo", "/devnet/initial-utxo-set.json" + ] + networks: + pythathon_hydra: + ipv4_address: 172.29.88.12 + + # Writes /devnet/persistence/.hydra-seed-tx.done on success (wiped with persistence/). + hydra-seed-tx: + image: alpine:3.20 + restart: "no" + depends_on: + hydra-node: + condition: service_started + hydra-node-peer: + condition: service_started + volumes: + - .:/devnet + environment: + HYDRA_HTTP_HOST: hydra-node + HYDRA_HTTP_PORT: "4011" + HYDRA_WS_URL: ws://hydra-node:4011 + command: ["/bin/sh", "/devnet/submit-seed-tx.sh"] + networks: + - pythathon_hydra + +networks: + pythathon_hydra: + driver: bridge + ipam: + config: + - subnet: 172.29.88.0/24 + gateway: 172.29.88.1 diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/build-seed-tx.sh b/lazer/cardano/hermes/infra/hydra-bootstrap/build-seed-tx.sh new file mode 100755 index 00000000..368070f5 --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/build-seed-tx.sh @@ -0,0 +1,80 @@ +#! /bin/bash +# Build + sign the Hydra offline-head seed tx for Preprod (--testnet-magic 1). +# Tx layout follows infra/hydra-bootstrap/entrypoint.sh: cardano-cli latest transaction build-raw, then sign, then cat. +# Run from repo host with Docker (entrypoint runs cardano-cli inside its image; we invoke the same CLI via docker run). +# +# No --tx-out-reference-script-file: cardano-cli’s reference-script CBOR does not match Hydra 1.3’s ledger check +# (ConwayUtxowFailure MalformedReferenceScripts). The Pyth UTxO carries inline datum + tokens only; attach Plutus +# in L2 txs explicitly (e.g. Lucid attach.WithdrawalValidator / attach.Script) instead of readFrom scriptRef. + +set -euo pipefail + +BOOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +INFRA="$(cd "${BOOT}/.." && pwd)" + +CARDANO_IMAGE="${CARDANO_IMAGE:-ghcr.io/intersectmbo/cardano-node:10.1.4}" + +cardano_cli() { + docker run --rm --user "$(id -u):$(id -g)" --entrypoint cardano-cli \ + -v "${INFRA}:/work" -w /work/hydra-bootstrap \ + "${CARDANO_IMAGE}" "$@" +} + +# Preprod (not the devnet 42 from entrypoint.sh) +testnet_magic="${TESTNET_MAGIC:-1}" + +# Define the UTxO details and amounts (initial-utxo-set.json fiction #0) +tx_in1="0000000000000000000000000000000000000000000000000000000000000000#0" +tx_in_lovelace=100000000041175 +fee=41175 +# Remaining lovelace to the Pyth script output after fee +out_lovelace=$((tx_in_lovelace - fee)) + +policy_id="d799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6" +asset_name_hex="50797468205374617465" +# Must match submit-seed-tx.sh PYTH_OUTPUT_ADDR +pyth_script_address="${PYTH_OUTPUT_ADDR:-addr_test1wrm3tr5zpw9k2nefjtsz66wfzn6flnphr5kd6ak9ufrl3wcqqfyn8}" + +tx_out="${pyth_script_address}+${out_lovelace}+1 ${policy_id}.${asset_name_hex}" + +signing_key="${SEED_SIGNING_KEY:-${INFRA}/credentials/hydra-funds.sk}" +if [[ "${signing_key}" != "${INFRA}"/* ]]; then + echo "Signing key must be under ${INFRA}" >&2 + exit 1 +fi +signing_key_container="/work/${signing_key#"${INFRA}"/}" + +# Inline datum CBOR (hex) — same as seed-output-datum.hex +datum_hex="$(tr -d ' \n\t' < "${SEED_DATUM_HEX_FILE:-${BOOT}/seed-output-datum.hex}")" +if command -v xxd >/dev/null 2>&1; then + printf '%s' "${datum_hex}" | xxd -r -p > "${BOOT}/seed-output-datum.cbor" +else + python3 -c "import sys,binascii; sys.stdout.buffer.write(binascii.unhexlify(sys.argv[1]))" "${datum_hex}" > "${BOOT}/seed-output-datum.cbor" +fi + +tx_raw="/work/hydra-bootstrap/seed.body.json" +tx_signed="/work/hydra-bootstrap/seed.witnessed.json" + +# Build the raw transaction (cf. entrypoint.sh — build-raw, then fee, then out-file) +echo "Building raw transaction..." +cardano_cli latest transaction build-raw \ + --tx-in "${tx_in1}" \ + --tx-out "${tx_out}" \ + --tx-out-inline-datum-cbor-file seed-output-datum.cbor \ + --protocol-params-file /work/protocol-parameters.json \ + --fee "${fee}" \ + --out-file "${tx_raw}" + +# Sign the transaction (Preprod testnet-magic) +echo "Signing transaction (Preprod testnet-magic ${testnet_magic})..." +cardano_cli latest transaction sign \ + --tx-body-file "${tx_raw}" \ + --signing-key-file "${signing_key_container}" \ + --testnet-magic "${testnet_magic}" \ + --out-file "${tx_signed}" + +cp "${BOOT}/seed.witnessed.json" "${INFRA}/seed-spend.signed.json" +cp "${BOOT}/seed.body.json" "${BOOT}/seed-spend.raw" + +echo "Wrote ${INFRA}/seed-spend.signed.json and ${BOOT}/seed-spend.raw" +cat "${INFRA}/seed-spend.signed.json" diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/reference-script.plutus b/lazer/cardano/hermes/infra/hydra-bootstrap/reference-script.plutus new file mode 100644 index 00000000..ad24817f --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/reference-script.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "", + "cborHex": "590ab60101003229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bae002488888888966002646465300130063754003370e90014dc3a4001300a0039805001244444b30013370e9003002c4c8c966002600c601a6ea800e2b3001300e3754007159800980298069baa301130120028a518b20188b201e8b2018375a602000260186ea801a264b300130010068cc004c040c034dd5003cdd6001488c8cc00400400c88cc00c004c0080092223300100222598008014660024602c602e602e0032301630170019ba54800244b3001300b30133754005132323259800980d80144c8c9660026020003159800980c9baa00280345901a456600260220031323259800980f80140222c80e0dd6980e800980c9baa0028acc004c0340062b3001301937540050068b20348b202e405c80b8c05cdd5000980d001c59018192cc004c05c0062b3001337129002180b000c5a2601e602c00280aa2c80c0dd5180c800980c800980a1baa0028b202448888cc8966002601e602e6ea800a2646464646644b300130220038992cc004c058c078dd5000c4c8c8c8ca60026eb4c0980066eb8c0980126eb4c09800e6eb8c0980092222598009815802c4cc060dd59815007112cc00400a26603401844b30010028acc004c08cc0a8dd500f44cc88cc89660026644b30013371e6eb8c0d0c0d4c0d4c0d4c0c4dd500d800c528c4c8cc004004dd5981018191baa01c2259800800c528456600264b30013371e6eb8c0d000401226600e606600200b14a08190c0d80062946266004004606e0028189034205e3001302f375404a6eb8c0c8c0bcdd501144c9289919800800811112cc00400629344c8cc89263259800cc004dd7181018199baa0019bae302130333754003375c606c60666ea800572a8acc004c8c966002605a60686ea800629422605a60686ea8c0e0c0d4dd5000a06632598009816981a1baa0018a60103d87a8000898109981bcc004cc020c0e0c0d4dd50009803981a9baa02ba6103d87a8000a60103d879800040cc97ae040cc64660020026eacc088c0d4dd500f912cc004006298103d87a80008992cc004cdc78021bae3036001898119981c981b800a5eb82266006006607600481a8c0e40050371bae30203033375400310018b20628b2062325980099b8f48900375c606c606e003130360018b2062323235980099b8f375c606e00291104b9011a82008919191919191919911981f98149981f98200039981f9ba90013303f30400024bd701981f9820182080125eb80d6600266e252000001892cc004cdc48011b8d00189981f1ba93300a0020013303e3753300100299b81371a0020050015c612f5c11640e91640e46eb8c0f8c0fc008dd7181f0021bad303d001323303c375066f29281bae303d0013303c303d303e0014bd702cc004cdc4a40086e340062660766ea4cc01d20040013303b375330014801266e00dc6800a40070015c612f5c11640dc6eb8c0ecc0f0004d6600294624b30013371290201b8d00189981d1ba93300648100004cc0e8dd4cc005204099b80371a002901fc0057184bd704590364590351bae303a303b001300100259800a51892cc004cdc4a4100026e340062660706ea4cc0112080010013303837533001482000666e00dc6800a40ff0015c612f5c11640d11640cd1640c86eb8c0dcc0e00056600266e252008371a00513303537526600290040011981a9ba99800a4011337006e3400920078012e3097ae08b20623718900019801801981b0011bae303400140c91640b444b300130040018a518acc004c01000a29422b3001980099baf9800981918179baa002981918179baa001919192cc004c0a8c0c4dd5181a981b00144006264b3001302b001899ba548008cc0d4dd419b80375a606c60666ea800920024bd704566002605400310028801206240c460626ea8005030181a00098181baa001400c98103d87b8000a50a5140b51980099baf9800980e18179baa002980e18179baa001919192cc004c0a8c0c4dd5181a981b00144006264b3001302b001899ba548008cc0d4dd419b80375a606c60666ea800920014bd704566002605400310028801206240c460626ea8005030181a00098181baa001400c98103d8798000a50a5140b514a0816902d205a2303130323032303230323032303230320012323232332259800981400145284566002604a0051980099baf30343031375400298103d87b8000a50a5140bd13233225980098158014528c566002605800513322598009817181a9baa30233036375400d13371000400313371200400281a0dd6981b981a1baa00359800981618199baa30213034375400f1001899b80001480090324528206440c860626ea8004dd6981a98191baa004303430313754002817902f18171baa001303230330033031302e3754002606000260586ea8004888c8cc89660026050005159800981418181baa0018a60103d87a80008a6103d879800040bd15980098128014566002604a60606ea80062980103d87a80008a6103d87b800040bd13322598009815000c530103d87b80008acc004c0ac006264b30013371000600314c0103d87980008acc004cdc4000801c530103d87b80008a6103d87a800040c88190dd6981b18199baa0038a6103d879800040c48188dd6981a18189baa00330303754002817902f18171baa001300200330010038b2052899191980b18160010980198188021bae302c001302e00240b11323233014302b00213003302f004375c6052002605800481522c8140604c002604a0026048002603e6ea80062c80e8c08401a2c80f8dd7180f8009bab301f002301f001301e001301d0013018375400516405864b3001300e301637540031301a3017375400316405464660020026eb0c010c05cdd5006912cc004006298103d87a80008992cc006600266ebc00530103d87a8000a50a51405d1001899801801980e801202e325980099912cc00400a294226530013259800980a180e1baa00189bad301d302037566040603a6ea8006290002036301f0019baf301f30200019bab003488966002003159800980100344cc01400d20008a5040751325980099baf301f0014c010140008acc004cc018010dd6981018119bab3020001898019ba630240028a5040791598009980300224001130030078a50407880f0c0880050200ca60020033756601260386ea8c024c070dd5002488cc080008cc080dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c0780066eacc07c00660460069112cc004cdc8a441000038acc004cdc7a441000038998029807198121ba60024bd70000c4cc015300103d87a8000006408119800803c006446600e0046604c66ec0dd48029ba6004001401c8100604200480fa2942294229410201ba63301b337606ea4058dd31980d99bb0301c3019375498118d8799f4a507974682053746174654850797468204f7073ff004c010101004bd6f7b63025eb7bdb1808928c566002602260306ea8c070c064dd5180e180c9baa300630193754003132598009807180c9baa001898031980e180e980d1baa0014bd704590181803980c9baa30063019375400316405d14c103d87a8000405c603600280c88966002601e602e6ea800a2646464b3001301f002899803180f00189980300080245901c180e800980e800980c1baa0028b202c44c8c008c05c00cdd7180a801202645900b1b874801100a0c024c028004c024004c010dd5005452689b2b20042611e581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e60001" +} diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/seed-output-datum.cbor b/lazer/cardano/hermes/infra/hydra-bootstrap/seed-output-datum.cbor new file mode 100644 index 00000000..4d0531d7 Binary files /dev/null and b/lazer/cardano/hermes/infra/hydra-bootstrap/seed-output-datum.cbor differ diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/seed-output-datum.hex b/lazer/cardano/hermes/infra/hydra-bootstrap/seed-output-datum.hex new file mode 100644 index 00000000..5362572e --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/seed-output-datum.hex @@ -0,0 +1 @@ +d8799fd8799f581c363d819f282a6cf2a6c2cb6bbc68213538355ca64e4b64620e14949a015820a36234ef3749a2c94136b6345bceff450791ef1ebc99e918f16f8075a441bb241822ffbf582080efc1f480c5615af3fb673d42287e993da9fbc3506b6e41dfa32950820c2e6cd8799fd8799fd87980d87a80ffd8799fd87a9f1b000001a2f5f38d08ffd87a80ffffffa0581c68a8972304546f254cbf625996c3a9e2ac860f77a9fcd4ee9f73907bff diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/seed-spend.raw b/lazer/cardano/hermes/infra/hydra-bootstrap/seed-spend.raw new file mode 100644 index 00000000..a73ae32d --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/seed-spend.raw @@ -0,0 +1,5 @@ +{ + "type": "Unwitnessed Tx ConwayEra", + "description": "Ledger Cddl Format", + "cborHex": "84a300d90102818258200000000000000000000000000000000000000000000000000000000000000000000181a300581d70f7158e820b8b654f2992e02d69c914f49fcc371d2cdd76c5e247f8bb01821b00005af3107a4000a1581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6a14a5079746820537461746501028201d81858b0d8799fd8799f581c363d819f282a6cf2a6c2cb6bbc68213538355ca64e4b64620e14949a015820a36234ef3749a2c94136b6345bceff450791ef1ebc99e918f16f8075a441bb241822ffbf582080efc1f480c5615af3fb673d42287e993da9fbc3506b6e41dfa32950820c2e6cd8799fd8799fd87980d87a80ffd8799fd87a9f1b000001a2f5f38d08ffd87a80ffffffa0581c68a8972304546f254cbf625996c3a9e2ac860f77a9fcd4ee9f73907bff0219a0d7a0f5f6" +} diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/seed.body.json b/lazer/cardano/hermes/infra/hydra-bootstrap/seed.body.json new file mode 100644 index 00000000..a73ae32d --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/seed.body.json @@ -0,0 +1,5 @@ +{ + "type": "Unwitnessed Tx ConwayEra", + "description": "Ledger Cddl Format", + "cborHex": "84a300d90102818258200000000000000000000000000000000000000000000000000000000000000000000181a300581d70f7158e820b8b654f2992e02d69c914f49fcc371d2cdd76c5e247f8bb01821b00005af3107a4000a1581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6a14a5079746820537461746501028201d81858b0d8799fd8799f581c363d819f282a6cf2a6c2cb6bbc68213538355ca64e4b64620e14949a015820a36234ef3749a2c94136b6345bceff450791ef1ebc99e918f16f8075a441bb241822ffbf582080efc1f480c5615af3fb673d42287e993da9fbc3506b6e41dfa32950820c2e6cd8799fd8799fd87980d87a80ffd8799fd87a9f1b000001a2f5f38d08ffd87a80ffffffa0581c68a8972304546f254cbf625996c3a9e2ac860f77a9fcd4ee9f73907bff0219a0d7a0f5f6" +} diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/seed.signed.json b/lazer/cardano/hermes/infra/hydra-bootstrap/seed.signed.json new file mode 100644 index 00000000..1f0cc255 --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/seed.signed.json @@ -0,0 +1,5 @@ +{ + "type": "Witnessed Tx ConwayEra", + "description": "Ledger Cddl Format", + "cborHex": "84a300d90102818258200000000000000000000000000000000000000000000000000000000000000000000181a400581d70f7158e820b8b654f2992e02d69c914f49fcc371d2cdd76c5e247f8bb01821b00005af3107a4000a1581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6a14a5079746820537461746501028201d81858b0d8799fd8799f581c363d819f282a6cf2a6c2cb6bbc68213538355ca64e4b64620e14949a015820a36234ef3749a2c94136b6345bceff450791ef1ebc99e918f16f8075a441bb241822ffbf582080efc1f480c5615af3fb673d42287e993da9fbc3506b6e41dfa32950820c2e6cd8799fd8799fd87980d87a80ffd8799fd87a9f1b000001a2f5f38d08ffd87a80ffffffa0581c68a8972304546f254cbf625996c3a9e2ac860f77a9fcd4ee9f73907bff03d818590abb8203590ab60101003229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bae002488888888966002646465300130063754003370e90014dc3a4001300a0039805001244444b30013370e9003002c4c8c966002600c601a6ea800e2b3001300e3754007159800980298069baa301130120028a518b20188b201e8b2018375a602000260186ea801a264b300130010068cc004c040c034dd5003cdd6001488c8cc00400400c88cc00c004c0080092223300100222598008014660024602c602e602e0032301630170019ba54800244b3001300b30133754005132323259800980d80144c8c9660026020003159800980c9baa00280345901a456600260220031323259800980f80140222c80e0dd6980e800980c9baa0028acc004c0340062b3001301937540050068b20348b202e405c80b8c05cdd5000980d001c59018192cc004c05c0062b3001337129002180b000c5a2601e602c00280aa2c80c0dd5180c800980c800980a1baa0028b202448888cc8966002601e602e6ea800a2646464646644b300130220038992cc004c058c078dd5000c4c8c8c8ca60026eb4c0980066eb8c0980126eb4c09800e6eb8c0980092222598009815802c4cc060dd59815007112cc00400a26603401844b30010028acc004c08cc0a8dd500f44cc88cc89660026644b30013371e6eb8c0d0c0d4c0d4c0d4c0c4dd500d800c528c4c8cc004004dd5981018191baa01c2259800800c528456600264b30013371e6eb8c0d000401226600e606600200b14a08190c0d80062946266004004606e0028189034205e3001302f375404a6eb8c0c8c0bcdd501144c9289919800800811112cc00400629344c8cc89263259800cc004dd7181018199baa0019bae302130333754003375c606c60666ea800572a8acc004c8c966002605a60686ea800629422605a60686ea8c0e0c0d4dd5000a06632598009816981a1baa0018a60103d87a8000898109981bcc004cc020c0e0c0d4dd50009803981a9baa02ba6103d87a8000a60103d879800040cc97ae040cc64660020026eacc088c0d4dd500f912cc004006298103d87a80008992cc004cdc78021bae3036001898119981c981b800a5eb82266006006607600481a8c0e40050371bae30203033375400310018b20628b2062325980099b8f48900375c606c606e003130360018b2062323235980099b8f375c606e00291104b9011a82008919191919191919911981f98149981f98200039981f9ba90013303f30400024bd701981f9820182080125eb80d6600266e252000001892cc004cdc48011b8d00189981f1ba93300a0020013303e3753300100299b81371a0020050015c612f5c11640e91640e46eb8c0f8c0fc008dd7181f0021bad303d001323303c375066f29281bae303d0013303c303d303e0014bd702cc004cdc4a40086e340062660766ea4cc01d20040013303b375330014801266e00dc6800a40070015c612f5c11640dc6eb8c0ecc0f0004d6600294624b30013371290201b8d00189981d1ba93300648100004cc0e8dd4cc005204099b80371a002901fc0057184bd704590364590351bae303a303b001300100259800a51892cc004cdc4a4100026e340062660706ea4cc0112080010013303837533001482000666e00dc6800a40ff0015c612f5c11640d11640cd1640c86eb8c0dcc0e00056600266e252008371a00513303537526600290040011981a9ba99800a4011337006e3400920078012e3097ae08b20623718900019801801981b0011bae303400140c91640b444b300130040018a518acc004c01000a29422b3001980099baf9800981918179baa002981918179baa001919192cc004c0a8c0c4dd5181a981b00144006264b3001302b001899ba548008cc0d4dd419b80375a606c60666ea800920024bd704566002605400310028801206240c460626ea8005030181a00098181baa001400c98103d87b8000a50a5140b51980099baf9800980e18179baa002980e18179baa001919192cc004c0a8c0c4dd5181a981b00144006264b3001302b001899ba548008cc0d4dd419b80375a606c60666ea800920014bd704566002605400310028801206240c460626ea8005030181a00098181baa001400c98103d8798000a50a5140b514a0816902d205a2303130323032303230323032303230320012323232332259800981400145284566002604a0051980099baf30343031375400298103d87b8000a50a5140bd13233225980098158014528c566002605800513322598009817181a9baa30233036375400d13371000400313371200400281a0dd6981b981a1baa00359800981618199baa30213034375400f1001899b80001480090324528206440c860626ea8004dd6981a98191baa004303430313754002817902f18171baa001303230330033031302e3754002606000260586ea8004888c8cc89660026050005159800981418181baa0018a60103d87a80008a6103d879800040bd15980098128014566002604a60606ea80062980103d87a80008a6103d87b800040bd13322598009815000c530103d87b80008acc004c0ac006264b30013371000600314c0103d87980008acc004cdc4000801c530103d87b80008a6103d87a800040c88190dd6981b18199baa0038a6103d879800040c48188dd6981a18189baa00330303754002817902f18171baa001300200330010038b2052899191980b18160010980198188021bae302c001302e00240b11323233014302b00213003302f004375c6052002605800481522c8140604c002604a0026048002603e6ea80062c80e8c08401a2c80f8dd7180f8009bab301f002301f001301e001301d0013018375400516405864b3001300e301637540031301a3017375400316405464660020026eb0c010c05cdd5006912cc004006298103d87a80008992cc006600266ebc00530103d87a8000a50a51405d1001899801801980e801202e325980099912cc00400a294226530013259800980a180e1baa00189bad301d302037566040603a6ea8006290002036301f0019baf301f30200019bab003488966002003159800980100344cc01400d20008a5040751325980099baf301f0014c010140008acc004cc018010dd6981018119bab3020001898019ba630240028a5040791598009980300224001130030078a50407880f0c0880050200ca60020033756601260386ea8c024c070dd5002488cc080008cc080dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c0780066eacc07c00660460069112cc004cdc8a441000038acc004cdc7a441000038998029807198121ba60024bd70000c4cc015300103d87a8000006408119800803c006446600e0046604c66ec0dd48029ba6004001401c8100604200480fa2942294229410201ba63301b337606ea4058dd31980d99bb0301c3019375498118d8799f4a507974682053746174654850797468204f7073ff004c010101004bd6f7b63025eb7bdb1808928c566002602260306ea8c070c064dd5180e180c9baa300630193754003132598009807180c9baa001898031980e180e980d1baa0014bd704590181803980c9baa30063019375400316405d14c103d87a8000405c603600280c88966002601e602e6ea800a2646464b3001301f002899803180f00189980300080245901c180e800980e800980c1baa0028b202c44c8c008c05c00cdd7180a801202645900b1b874801100a0c024c028004c024004c010dd5005452689b2b20042611e581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e600010219a0d7a100d9010281825820216f72947d1b97d56825c5f9f8a2e6f14234c03171853264f2f552a2685b25e058408329f51aecab2e7cecacfd02d294d00d1050ae66c9e556cf6932254172fa8e1c410b0e098671564adeda126123d23f0ec3ad866d5df5bb1a92766f73bff30c04f5f6" +} diff --git a/lazer/cardano/hermes/infra/hydra-bootstrap/seed.witnessed.json b/lazer/cardano/hermes/infra/hydra-bootstrap/seed.witnessed.json new file mode 100644 index 00000000..9c8d636d --- /dev/null +++ b/lazer/cardano/hermes/infra/hydra-bootstrap/seed.witnessed.json @@ -0,0 +1,5 @@ +{ + "type": "Witnessed Tx ConwayEra", + "description": "Ledger Cddl Format", + "cborHex": "84a300d90102818258200000000000000000000000000000000000000000000000000000000000000000000181a300581d70f7158e820b8b654f2992e02d69c914f49fcc371d2cdd76c5e247f8bb01821b00005af3107a4000a1581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6a14a5079746820537461746501028201d81858b0d8799fd8799f581c363d819f282a6cf2a6c2cb6bbc68213538355ca64e4b64620e14949a015820a36234ef3749a2c94136b6345bceff450791ef1ebc99e918f16f8075a441bb241822ffbf582080efc1f480c5615af3fb673d42287e993da9fbc3506b6e41dfa32950820c2e6cd8799fd8799fd87980d87a80ffd8799fd87a9f1b000001a2f5f38d08ffd87a80ffffffa0581c68a8972304546f254cbf625996c3a9e2ac860f77a9fcd4ee9f73907bff0219a0d7a100d9010281825820216f72947d1b97d56825c5f9f8a2e6f14234c03171853264f2f552a2685b25e058403014cf053b2687bb3e6ef63b78dd2736d3de4fcec8b3ed423c92038187e669180382c440164da59b85790d7ea5a19556c3024a4860517564bf05aa0ddbd5620af5f6" +} diff --git a/lazer/cardano/hermes/infra/initial-utxo-set.json b/lazer/cardano/hermes/infra/initial-utxo-set.json new file mode 100644 index 00000000..0b1158b0 --- /dev/null +++ b/lazer/cardano/hermes/infra/initial-utxo-set.json @@ -0,0 +1,15 @@ +{ + "0000000000000000000000000000000000000000000000000000000000000000#0": { + "address": "addr_test1vzqdn97wxxuem2ukec6fswslmknuj2zlcwhuz2wfqvkdcgq9235ym", + "value": { + "lovelace": 100000000041175, + "d799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6": {"50797468205374617465": 1} + } + }, + "0000000000000000000000000000000000000000000000000000000000000000#1": { + "address": "addr_test1vzqdn97wxxuem2ukec6fswslmknuj2zlcwhuz2wfqvkdcgq9235ym", + "value": { + "lovelace": 100000000000000 + } + } +} diff --git a/lazer/cardano/hermes/infra/protocol-parameters.json b/lazer/cardano/hermes/infra/protocol-parameters.json new file mode 100644 index 00000000..d13b71e1 --- /dev/null +++ b/lazer/cardano/hermes/infra/protocol-parameters.json @@ -0,0 +1,707 @@ +{ + "collateralPercentage": 150, + "committeeMaxTermLength": 146, + "committeeMinSize": 7, + "costModels": { + "PlutusV1": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 228465, + 122, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 24548, + 29498, + 38, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 228465, + 122, + 0, + 1, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 228465, + 122, + 0, + 1, + 1, + 85848, + 228465, + 122, + 0, + 1, + 1, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 53384111, + 14333, + 10 + ], + "PlutusV2": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 228465, + 122, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 24548, + 29498, + 38, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 228465, + 122, + 0, + 1, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 228465, + 122, + 0, + 1, + 1, + 85848, + 228465, + 122, + 0, + 1, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10 + ], + "PlutusV3": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 24548, + 29498, + 38, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1, + 100181, + 726, + 719, + 0, + 1, + 100181, + 726, + 719, + 0, + 1, + 100181, + 726, + 719, + 0, + 1, + 107878, + 680, + 0, + 1, + 95336, + 1, + 281145, + 18848, + 0, + 1, + 180194, + 159, + 1, + 1, + 158519, + 8942, + 0, + 1, + 159378, + 8813, + 0, + 1, + 107490, + 3298, + 1, + 106057, + 655, + 1, + 1964219, + 24520, + 3 + ] + }, + "dRepActivity": 20, + "dRepDeposit": 500000000, + "dRepVotingThresholds": { + "committeeNoConfidence": 0.6, + "committeeNormal": 0.67, + "hardForkInitiation": 0.6, + "motionNoConfidence": 0.67, + "ppEconomicGroup": 0.67, + "ppGovGroup": 0.75, + "ppNetworkGroup": 0.67, + "ppTechnicalGroup": 0.67, + "treasuryWithdrawal": 0.67, + "updateToConstitution": 0.75 + }, + "executionUnitPrices": { + "priceMemory": 0, + "priceSteps": 0 + }, + "govActionDeposit": 100000000000, + "govActionLifetime": 6, + "maxBlockBodySize": 90112, + "maxBlockExecutionUnits": { + "memory": 62000000000000, + "steps": 20000000000000000 + }, + "maxBlockHeaderSize": 1100, + "maxCollateralInputs": 3, + "maxTxExecutionUnits": { + "memory": 14000000000000, + "steps": 10000000000000000 + }, + "maxTxSize": 25000, + "maxValueSize": 5000, + "minFeeRefScriptCostPerByte": 15, + "minPoolCost": 170000000, + "monetaryExpansion": 3.0e-3, + "poolPledgeInfluence": 0.3, + "poolRetireMaxEpoch": 18, + "poolVotingThresholds": { + "committeeNoConfidence": 0.51, + "committeeNormal": 0.51, + "hardForkInitiation": 0.51, + "motionNoConfidence": 0.51, + "ppSecurityGroup": 0.51 + }, + "protocolVersion": { + "major": 9, + "minor": 0 + }, + "stakeAddressDeposit": 2000000, + "stakePoolDeposit": 500000000, + "stakePoolTargetNum": 500, + "treasuryCut": 0.2, + "txFeeFixed": 0, + "txFeePerByte": 0, + "utxoCostPerByte": 4310 +} diff --git a/lazer/cardano/hermes/infra/seed-spend.signed.json b/lazer/cardano/hermes/infra/seed-spend.signed.json new file mode 100644 index 00000000..9c8d636d --- /dev/null +++ b/lazer/cardano/hermes/infra/seed-spend.signed.json @@ -0,0 +1,5 @@ +{ + "type": "Witnessed Tx ConwayEra", + "description": "Ledger Cddl Format", + "cborHex": "84a300d90102818258200000000000000000000000000000000000000000000000000000000000000000000181a300581d70f7158e820b8b654f2992e02d69c914f49fcc371d2cdd76c5e247f8bb01821b00005af3107a4000a1581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6a14a5079746820537461746501028201d81858b0d8799fd8799f581c363d819f282a6cf2a6c2cb6bbc68213538355ca64e4b64620e14949a015820a36234ef3749a2c94136b6345bceff450791ef1ebc99e918f16f8075a441bb241822ffbf582080efc1f480c5615af3fb673d42287e993da9fbc3506b6e41dfa32950820c2e6cd8799fd8799fd87980d87a80ffd8799fd87a9f1b000001a2f5f38d08ffd87a80ffffffa0581c68a8972304546f254cbf625996c3a9e2ac860f77a9fcd4ee9f73907bff0219a0d7a100d9010281825820216f72947d1b97d56825c5f9f8a2e6f14234c03171853264f2f552a2685b25e058403014cf053b2687bb3e6ef63b78dd2736d3de4fcec8b3ed423c92038187e669180382c440164da59b85790d7ea5a19556c3024a4860517564bf05aa0ddbd5620af5f6" +} diff --git a/lazer/cardano/hermes/infra/submit-seed-tx.sh b/lazer/cardano/hermes/infra/submit-seed-tx.sh new file mode 100755 index 00000000..2e483204 --- /dev/null +++ b/lazer/cardano/hermes/infra/submit-seed-tx.sh @@ -0,0 +1,101 @@ +#!/bin/sh +set -eu + +# Keep sentinel under persistence/ so `rm -rf persistence/` or a fresh volume wipes it. +# (A file at /devnet/.hydra-seed-tx.done survives `docker compose down -v` because ./ is a bind mount.) +SENTINEL=/devnet/persistence/.hydra-seed-tx.done +PYTH_SETUP_TX_ADDR=/devnet/seed-spend.signed.json +INITIAL_UTXO_REF='0000000000000000000000000000000000000000000000000000000000000000#0' +PYTH_OUTPUT_ADDR='addr_test1wrm3tr5zpw9k2nefjtsz66wfzn6flnphr5kd6ak9ufrl3wcqqfyn8' + +HYDRA_HTTP_HOST="${HYDRA_HTTP_HOST:-hydra-node}" +HYDRA_HTTP_PORT="${HYDRA_HTTP_PORT:-4011}" +WS_URL="${HYDRA_WS_URL:-ws://${HYDRA_HTTP_HOST}:${HYDRA_HTTP_PORT}}" +MAX_WAIT="${SEED_TX_MAX_WAIT:-180}" + +if [ ! -f "$PYTH_SETUP_TX_ADDR" ]; then + echo "Missing $PYTH_SETUP_TX_ADDR" >&2 + exit 1 +fi + +mkdir -p /devnet/persistence + +if [ -f "$SENTINEL" ]; then + echo "Seed tx already submitted ($(basename "$SENTINEL") exists)." + exit 0 +fi + +apk add --no-cache curl jq ca-certificates websocat >/dev/null + +api_root() { + curl -sf "http://${HYDRA_HTTP_HOST}:${HYDRA_HTTP_PORT}$1" || true +} + +echo "Waiting for Hydra HTTP API (protocol-parameters)..." +n=0 +until api_root /protocol-parameters | jq -e . >/dev/null 2>&1; do + n=$((n + 1)) + if [ "$n" -ge "$MAX_WAIT" ]; then + echo "Timeout waiting for Hydra API." >&2 + exit 1 + fi + sleep 1 +done + +echo "Waiting for initial UTxO with ref ${INITIAL_UTXO_REF} in /snapshot/utxo..." +n=0 +while true; do + body=$(api_root /snapshot/utxo) + if echo "$body" | jq -e --arg k "$INITIAL_UTXO_REF" --arg a "$PYTH_OUTPUT_ADDR" ' + type == "object" + and (has($k) | not) + and (to_entries | map(.value.address == $a and .value.inlineDatumRaw != null) | any) + ' >/dev/null 2>&1; then + touch "$SENTINEL" + echo "Head already seeded (no fiction UTxO; found output at ${PYTH_OUTPUT_ADDR})." + exit 0 + fi + if echo "$body" | jq -e --arg k "$INITIAL_UTXO_REF" 'type == "object" and has($k)' >/dev/null 2>&1; then + break + fi + n=$((n + 1)) + if [ "$n" -ge "$MAX_WAIT" ]; then + echo "Timeout: initial UTxO not in snapshot. Ensure all Hydra peers are up and connected." >&2 + exit 1 + fi + sleep 1 +done + +MSG=$(jq -c '{tag: "NewTx", transaction: .}' "$PYTH_SETUP_TX_ADDR") +WS_FULL="${WS_URL}?history=no" + +echo "Submitting NewTx via ${WS_FULL} ..." +OUT=$( (sleep 0.3; echo "$MSG"; sleep 4) | websocat "$WS_FULL" 2>&1) || true + +if echo "$OUT" | grep -q '"tag":"TxValid"'; then + mkdir -p "$(dirname "$SENTINEL")" + touch "$SENTINEL" + echo "Seed tx accepted (TxValid)." + exit 0 +fi + +if echo "$OUT" | grep -q '"tag":"TxInvalid"'; then + body=$(api_root /snapshot/utxo) + if echo "$body" | jq -e --arg k "$INITIAL_UTXO_REF" --arg a "$PYTH_OUTPUT_ADDR" ' + type == "object" + and (has($k) | not) + and (to_entries | map(.value.address == $a and .value.inlineDatumRaw != null) | any) + ' >/dev/null 2>&1; then + mkdir -p "$(dirname "$SENTINEL")" + touch "$SENTINEL" + echo "Seed already applied (TxInvalid on replay; snapshot shows seeded output)." + exit 0 + fi + echo "$OUT" | tail -n 3 >&2 + echo "Hydra rejected the seed transaction (TxInvalid)." >&2 + exit 1 +fi + +echo "$OUT" >&2 +echo "Unexpected WebSocket response; not marking done." >&2 +exit 1 diff --git a/lazer/cardano/hermes/onchain/.gitignore b/lazer/cardano/hermes/onchain/.gitignore new file mode 100644 index 00000000..ff7811b1 --- /dev/null +++ b/lazer/cardano/hermes/onchain/.gitignore @@ -0,0 +1,6 @@ +# Aiken compilation artifacts +artifacts/ +# Aiken's project working directory +build/ +# Aiken's default documentation export +docs/ diff --git a/lazer/cardano/hermes/onchain/README.md b/lazer/cardano/hermes/onchain/README.md new file mode 100644 index 00000000..91bda432 --- /dev/null +++ b/lazer/cardano/hermes/onchain/README.md @@ -0,0 +1,65 @@ +# hermes + +Write validators in the `validators` folder, and supporting functions in the `lib` folder using `.ak` as a file extension. + +```aiken +validator my_first_validator { + spend(_datum: Option, _redeemer: Data, _output_reference: Data, _context: Data) { + True + } +} +``` + +## Building + +```sh +aiken build +``` + +## Configuring + +**aiken.toml** +```toml +[config.default] +network_id = 41 +``` + +Or, alternatively, write conditional environment modules under `env`. + +## Testing + +You can write tests in any module using the `test` keyword. For example: + +```aiken +use config + +test foo() { + config.network_id + 1 == 42 +} +``` + +To run all tests, simply do: + +```sh +aiken check +``` + +To run only tests matching the string `foo`, do: + +```sh +aiken check -m foo +``` + +## Documentation + +If you're writing a library, you might want to generate an HTML documentation for it. + +Use: + +```sh +aiken docs +``` + +## Resources + +Find more on the [Aiken's user manual](https://aiken-lang.org). diff --git a/lazer/cardano/hermes/onchain/aiken.lock b/lazer/cardano/hermes/onchain/aiken.lock new file mode 100644 index 00000000..0bfd0179 --- /dev/null +++ b/lazer/cardano/hermes/onchain/aiken.lock @@ -0,0 +1,27 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +[[requirements]] +name = "aiken-lang/stdlib" +version = "v3.0.0" +source = "github" + +[[requirements]] +name = "pyth-network/pyth-lazer-cardano" +version = "main" +source = "github" + +[[packages]] +name = "aiken-lang/stdlib" +version = "v3.0.0" +requirements = [] +source = "github" + +[[packages]] +name = "pyth-network/pyth-lazer-cardano" +version = "main" +requirements = [] +source = "github" + +[etags] +"pyth-network/pyth-lazer-cardano@main" = [{ secs_since_epoch = 1774219791, nanos_since_epoch = 77626650 }, "a46dacd97a22eb07feeaf966d48c3116c8249ddc836705656e3135cea285bcfc"] diff --git a/lazer/cardano/hermes/onchain/aiken.toml b/lazer/cardano/hermes/onchain/aiken.toml new file mode 100644 index 00000000..7839f420 --- /dev/null +++ b/lazer/cardano/hermes/onchain/aiken.toml @@ -0,0 +1,23 @@ +name = "los-hydra-boys/hermes" +version = "0.0.0" +compiler = "v1.1.21" +plutus = "v3" +license = "Apache-2.0" +description = "Aiken contracts for project 'los-hydra-boys/hermes'" + +[repository] +user = "los-hydra-boys" +project = "hermes" +platform = "github" + +[[dependencies]] +name = "aiken-lang/stdlib" +version = "v3.0.0" +source = "github" + +[[dependencies]] +name = "pyth-network/pyth-lazer-cardano" +version = "main" +source = "github" + +[config] diff --git a/lazer/cardano/hermes/onchain/lib/contants.ak b/lazer/cardano/hermes/onchain/lib/contants.ak new file mode 100644 index 00000000..d744adff --- /dev/null +++ b/lazer/cardano/hermes/onchain/lib/contants.ak @@ -0,0 +1,8 @@ +pub const up_tn = "UP" + +pub const down_tn = "DOWN" + +pub const control_token_tn = "CONTROL" + +// Milliseconds in 5 minutes +pub const five_minutes = 300_000 diff --git a/lazer/cardano/hermes/onchain/lib/hermes_types.ak b/lazer/cardano/hermes/onchain/lib/hermes_types.ak new file mode 100644 index 00000000..47f2b861 --- /dev/null +++ b/lazer/cardano/hermes/onchain/lib/hermes_types.ak @@ -0,0 +1,60 @@ +use aiken/crypto.{VerificationKeyHash} +use cardano/transaction.{OutputReference} + +pub type PosixTime = + Int + +pub type Direction { + Up + Down +} + +pub type Operation { + Buy + Sell +} + +pub type Price { + numerator: Int, + denominator: Int, +} + +pub type OrderDatum { + direction: Direction, + operation: Operation, + price: Price, + owner: VerificationKeyHash, + expected_tokens: Int, +} + +pub type OrderRedeemer { + Cancel + Match + Fill(Int) +} + +pub type OrderMintRedeemer { + Mint(OutputReference) + Burn +} + +pub type MarketDatum { + start_price: Price, + end_price: Option, + remaining_shares: Int, +} + +pub type MarketRedeemer { + RecordFinalPrice + ClaimWinnings(Int) + ClaimLosings(Int) + CloseMarket + ProcessMatch +} + +pub type MarketMintRedeemer { + MintControlToken + BurnControlToken + MintPositionToken(Direction) + BurnPositionToken(Direction) +} diff --git a/lazer/cardano/hermes/onchain/lib/subvalidators/common_checks.ak b/lazer/cardano/hermes/onchain/lib/subvalidators/common_checks.ak new file mode 100644 index 00000000..c4395e8c --- /dev/null +++ b/lazer/cardano/hermes/onchain/lib/subvalidators/common_checks.ak @@ -0,0 +1,41 @@ +use aiken/collection/dict as dict +use aiken/collection/list +use aiken/math/rational.{denominator, numerator} +use cardano/assets.{PolicyId, tokens} +use cardano/transaction.{Transaction} +use hermes_types.{PosixTime, Price} +use pyth +use types/u32 +use types/u64 + +pub fn validate_only_burn(policy_id: PolicyId, tx: Transaction) -> Bool { + // For this policy, all qtys are negative + let Transaction { mint, .. } = tx + + dict.foldl( + tokens(mint, policy_id), + True, + fn(_, qty, acc) -> Bool { acc && qty < 0 }, + ) +} + +pub fn read_btc_usd_price( + pyth_id: PolicyId, + start_time: PosixTime, + self: Transaction, +) -> Price { + expect [update] = pyth.get_updates(pyth_id, self) + expect Some(feed) = + list.find(update.feeds, fn(feed) { u32.as_int(feed.feed_id) == 1 }) + expect Some(Some(price)) = feed.price + expect Some(exponent) = feed.exponent + + expect Some(multiplier) = rational.from_int(10) |> rational.pow(exponent) + let rat_price = rational.from_int(price) |> rational.mul(multiplier) + + let update_timestamp = update.timestamp_us + + expect u64.as_int(update_timestamp) == start_time * 1000 + + Price { denominator: denominator(rat_price), numerator: numerator(rat_price) } +} diff --git a/lazer/cardano/hermes/onchain/lib/subvalidators/market_checks.ak b/lazer/cardano/hermes/onchain/lib/subvalidators/market_checks.ak new file mode 100644 index 00000000..f04fd75b --- /dev/null +++ b/lazer/cardano/hermes/onchain/lib/subvalidators/market_checks.ak @@ -0,0 +1,338 @@ +use aiken/collection/dict.{to_pairs} +use aiken/collection/list +use cardano/address.{Script} +use cardano/assets.{ + PolicyId, Value, from_asset, from_lovelace, match, merge, negate, quantity_of, + tokens, +} +use cardano/transaction.{InlineDatum, Input, Output, Spend, Transaction} +use contants.{control_token_tn, down_tn, five_minutes, up_tn} +use hermes_types.{ + MarketDatum, MarketRedeemer, PosixTime, Price, ProcessMatch, +} +use subvalidators/common_checks.{read_btc_usd_price} + +pub fn validate_init_market( + pyth_policy: PolicyId, + start_time: PosixTime, + own_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { outputs, mint, .. } = tx + + // Only one output at the script address + expect [own_output] = + list.filter( + outputs, + fn(o) { o.address.payment_credential == Script(own_policy) }, + ) + + // Extract value and datum + expect Output { + value: o_value, + datum: InlineDatum(o_datum), + reference_script: None, + .. + } = own_output + + // Datum has + // End value is None + // Ramaining shares is 0 + expect MarketDatum { + start_price: o_d_price, + end_price: None, + remaining_shares: 0, + }: MarketDatum = o_datum + + let price = read_btc_usd_price(pyth_policy, start_time, tx) + + // Minting only 1 control token in this policy + expect [Pair(minted_tn, 1)] = tokens(mint, own_policy) |> to_pairs() + + and { + // Start value extracted from oracle + o_d_price == price, + // Value has control token + match(o_value, from_asset(own_policy, control_token_tn, 1), >=), + minted_tn == control_token_tn, + } +} + +pub fn validate_record_final_price( + pyth_policy: PolicyId, + start_time: PosixTime, + own_policy: PolicyId, + own_datum: MarketDatum, + own_value: Value, + tx: Transaction, +) -> Bool { + // Datum only adds the end price + let Transaction { outputs, .. } = tx + + // Only one output at the script address + expect [own_output] = + list.filter( + outputs, + fn(o) { o.address.payment_credential == Script(own_policy) }, + ) + + expect Output { + value: o_value, + datum: InlineDatum(o_datum), + reference_script: None, + .. + } = own_output + + let new_price = read_btc_usd_price(pyth_policy, start_time + five_minutes, tx) + + let expected_datum = + MarketDatum { + start_price: own_datum.start_price, + remaining_shares: own_datum.remaining_shares, + end_price: Some(new_price), + } + let expected_datum_data: Data = expected_datum + and { + // Output datum matched expected + o_datum == expected_datum_data, + // Value has not decreased + match(o_value, own_value, >=), + } +} + +pub fn validate_claim_winnings( + own_value: Value, + claimed_tokens: Int, + own_datum: MarketDatum, + own_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { outputs, mint, .. } = tx + + // Only one output at the script address + expect [own_output] = + list.filter( + outputs, + fn(o) { o.address.payment_credential == Script(own_policy) }, + ) + + expect Output { + value: o_value, + datum: InlineDatum(o_datum), + reference_script: None, + .. + } = own_output + + let paid_value = from_lovelace(claimed_tokens * 1_000_000) + + let remaining_value = merge(own_value, negate(paid_value)) + + expect MarketDatum { + start_price: i_d_start_price, + end_price: Some(i_d_end_price), + remaining_shares: i_d_remaining_shares, + } = own_datum + + let expected_datum = + MarketDatum { + start_price: i_d_start_price, + remaining_shares: i_d_remaining_shares - claimed_tokens, + end_price: Some(i_d_end_price), + } + let expected_datum_data: Data = expected_datum + + let claiming_token_name = + if compare_prices(i_d_end_price, i_d_start_price) == Less { + down_tn + } else { + up_tn + } + + expect [Pair(minted_tn, qty)] = tokens(mint, own_policy) |> to_pairs() + + and { + minted_tn == claiming_token_name, + qty == -claimed_tokens, + // Output datum matched expected + o_datum == expected_datum_data, + // Value has not decreased + match(o_value, remaining_value, >=), + } +} + +pub fn validate_claim_losings( + own_value: Value, + claimed_tokens: Int, + own_datum: MarketDatum, + own_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { outputs, mint, .. } = tx + + // Only one output at the script address + expect [own_output] = + list.filter( + outputs, + fn(o) { o.address.payment_credential == Script(own_policy) }, + ) + + expect Output { + value: o_value, + datum: InlineDatum(o_datum), + reference_script: None, + .. + } = own_output + + expect MarketDatum { + start_price: i_d_start_price, + end_price: Some(i_d_end_price), + remaining_shares: i_d_remaining_shares, + } = own_datum + + let expected_datum = + MarketDatum { + start_price: i_d_start_price, + remaining_shares: i_d_remaining_shares - claimed_tokens, + end_price: Some(i_d_end_price), + } + let expected_datum_data: Data = expected_datum + + let claiming_token_name = + if compare_prices(i_d_end_price, i_d_start_price) == Less { + up_tn + } else { + down_tn + } + + expect [Pair(minted_tn, qty)] = tokens(mint, own_policy) |> to_pairs() + + and { + minted_tn == claiming_token_name, + qty == -claimed_tokens, + // Output datum matched expected + o_datum == expected_datum_data, + // Value has not decreased + match(o_value, own_value, >=), + } +} + +pub fn validate_close_market( + own_policy: PolicyId, + own_datum: MarketDatum, + tx: Transaction, +) -> Bool { + let Transaction { mint, .. } = tx + // Burning the control token in this policy + expect [Pair(minted_tn, -1)] = tokens(mint, own_policy) |> to_pairs() + and { + minted_tn == control_token_tn, + own_datum.remaining_shares == 0, + } + // Burned control token +} + +pub fn validate_process_match( + own_datum: MarketDatum, + own_value: Value, + own_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { outputs, mint, .. } = tx + + expect [own_output] = + list.filter( + outputs, + fn(o) { o.address.payment_credential == Script(own_policy) }, + ) + + expect Output { value: o_value, datum: InlineDatum(o_raw_datum), .. } = + own_output + + expect o_datum: MarketDatum = o_raw_datum + + let up_minted = quantity_of(mint, own_policy, up_tn) + let down_minted = quantity_of(mint, own_policy, down_tn) + + // Datum is updated by the amount of up and down tokens minted + let matched_amount = up_minted + + // Value is increased by the matched lovelace (1-to-1 with token scale in matching context) + let matched_lovelace = matched_amount + let expected_value = merge(own_value, from_lovelace(matched_lovelace)) + + and { + up_minted > 0, + up_minted == down_minted, + // Value is increased by matched lovelace AND control token is not stolen + // (`expected_value` includes `own_value` which holds the control token) + match(o_value, expected_value, >=), + // Datum keeps prices and updates shares + o_datum.start_price == own_datum.start_price, + o_datum.end_price == own_datum.end_price, + // Datum is updated by the amount of up and down tokens minted + o_datum.remaining_shares == own_datum.remaining_shares + matched_amount, + } +} + +pub fn validate_mint_position_tokens( + own_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { inputs, mint, redeemers, .. } = tx + + // Validate that the same amount of up and down tokens got minted + let own_minted = tokens(mint, own_policy) |> to_pairs() + let up_minted = quantity_of(mint, own_policy, up_tn) + let down_minted = quantity_of(mint, own_policy, down_tn) + + let valid_mints = and { + up_minted > 0, + up_minted == down_minted, + } + + // Valiates that no other token with other name is minted + let no_extra_mints = list.length(own_minted) == 2 + + expect Some(market_input) = + list.find( + inputs, + fn(i) { i.output.address.payment_credential == Script(own_policy) }, + ) + + // Validates that the market utxo has the control token + let has_control_token = + quantity_of(market_input.output.value, own_policy, control_token_tn) >= 1 + + // Validate that a market utxo is consumed with match redeemer + expect Some(Pair(_, raw_redeemer)) = + list.find( + redeemers, + fn(pair) { + let Pair(purpose, _) = pair + purpose == Spend(market_input.output_reference) + }, + ) + + expect market_redeemer: MarketRedeemer = raw_redeemer + let is_match_redeemer = market_redeemer == ProcessMatch + + and { + valid_mints, + no_extra_mints, + has_control_token, + is_match_redeemer, + } +} + +pub fn compare_prices(price1: Price, price2: Price) -> Ordering { + let l = price1.numerator * price2.denominator + let r = price2.numerator * price1.denominator + + if l > r { + Greater + } else if l < r { + Less + } else { + Equal + } +} diff --git a/lazer/cardano/hermes/onchain/lib/subvalidators/order_checks.ak b/lazer/cardano/hermes/onchain/lib/subvalidators/order_checks.ak new file mode 100644 index 00000000..482ff079 --- /dev/null +++ b/lazer/cardano/hermes/onchain/lib/subvalidators/order_checks.ak @@ -0,0 +1,413 @@ +use aiken/cbor +use aiken/collection/dict.{to_pairs} +use aiken/collection/list as list +use aiken/crypto.{ScriptHash, blake2b_256} +use cardano/address.{Address, Script, VerificationKey} +use cardano/assets.{ + PolicyId, Value, add, from_asset, from_lovelace, match, merge, negate, + quantity_of, tokens, +} +use cardano/transaction.{ + InlineDatum, Input, Output, OutputReference, Transaction, +} +use contants.{down_tn, up_tn} +use hermes_types.{Buy, Direction, Down, Operation, OrderDatum, Price, Sell, Up} + +pub fn validate_create_order( + seed: OutputReference, + position_token_policy: PolicyId, + own_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { extra_signatories, inputs, outputs, mint, .. } = tx + + // Only one output at the script address + expect [own_output] = + list.filter( + outputs, + fn(o) { o.address.payment_credential == Script(own_policy) }, + ) + + expect Some(_) = list.find(inputs, fn(i) { i.output_reference == seed }) + + // Extract value and datum + expect Output { + value: o_value, + datum: InlineDatum(o_datum), + reference_script: None, + .. + } = own_output + + expect OrderDatum { + owner: o_d_owner, + operation: o_d_operation, + direction: o_d_direction, + price: o_d_price, + expected_tokens: o_d_expected_tokens, + }: OrderDatum = o_datum + + // Minting only 1 control token in this policy + expect [Pair(minted_tn, 1)] = tokens(mint, own_policy) |> to_pairs() + + let expected_value = + calculate_offered_tokens( + o_d_direction, + o_d_operation, + o_d_price, + o_d_expected_tokens, + position_token_policy, + ) + + and { + // Signed by owner + list.has(extra_signatories, o_d_owner), + // Value has offered tokens and control token + match(o_value, add(expected_value, own_policy, minted_tn, 1), >=), + // Control token has correct name + minted_tn == blake2b_256(cbor.serialise(seed)), + } +} + +pub fn validate_cancel( + own_datum: OrderDatum, + own_policy: PolicyId, + own_value: Value, + tx: Transaction, +) -> Bool { + let Transaction { extra_signatories, mint, .. } = tx + + let neg_control_token = tokens(negate(own_value), own_policy) + + and { + // Owner is signing the transaction + list.has(extra_signatories, own_datum.owner), + // Control token is burnt + match(mint, neg_control_token, ==), + } +} + +pub fn validate_match( + own_policy: PolicyId, + market_script_hash: ScriptHash, + tx: Transaction, +) -> Bool { + let Transaction { inputs, outputs, mint, .. } = tx + + // Expect two inputs from the own script + expect [input_a, + input_b] = + list.filter( + inputs, + fn(i) { i.output.address.payment_credential == Script(own_policy) }, + ) + + // Determine which input is "self" and which is "other" + expect Input { + output: Output { value: a_value, datum: InlineDatum(a_raw_datum), .. }, + .. + } = input_a + + expect Input { + output: Output { value: b_value, datum: InlineDatum(b_raw_datum), .. }, + .. + } = input_b + + expect a_datum: OrderDatum = a_raw_datum + expect b_datum: OrderDatum = b_raw_datum + + // Expect different directions + expect a_datum.direction != b_datum.direction + + // Expect both operations to be Buy + expect a_datum.operation == Buy + expect b_datum.operation == Buy + + // Expect the sum of the prices to be 1 + // price_a.num / price_a.den + price_b.num / price_b.den == 1 + // => price_a.num * price_b.den + price_b.num * price_a.den == price_a.den * price_b.den + let price_sum_numerator = + a_datum.price.numerator * b_datum.price.denominator + b_datum.price.numerator * a_datum.price.denominator + let price_sum_denominator = + a_datum.price.denominator * b_datum.price.denominator + expect price_sum_numerator == price_sum_denominator + + // Figure out which order has the greater amount (the one that continues) + // and which has the smaller amount (the one that gets fully consumed) + let (bigger_datum, bigger_value, smaller_datum, _smaller_value) = + if a_datum.expected_tokens >= b_datum.expected_tokens { + (a_datum, a_value, b_datum, b_value) + } else { + (b_datum, b_value, a_datum, a_value) + } + + let matched_amount = smaller_datum.expected_tokens + + // The order with the greater amount should be replicated with updated expected_tokens and value + let is_complete_fill = bigger_datum.expected_tokens == matched_amount + + let continuing_order_ok = or { + // Complete fill: both control tokens burned + is_complete_fill, + // Partial fill: bigger order continues + { + let expected_continuing_datum = + OrderDatum { + ..bigger_datum, + expected_tokens: bigger_datum.expected_tokens - matched_amount, + } + let expected_continuing_datum_data: Data = expected_continuing_datum + + let filled_lovelace = + matched_amount * bigger_datum.price.numerator / bigger_datum.price.denominator + + let expected_continuing_value = + merge(bigger_value, negate(from_lovelace(filled_lovelace))) + + list.any( + outputs, + fn(Output { address: o_addr, value: o_val, datum: o_datum, .. }) { + if o_addr.payment_credential == Script(own_policy) { + expect InlineDatum(o_dat) = o_datum + and { + match(o_val, expected_continuing_value, >=), + o_dat == expected_continuing_datum_data, + } + } else { + False + } + }, + ) + }, + } + + // The other order control token should be burned + // If complete fill, both control tokens should be burned (2 tokens burned from own_policy) + // If partial fill, only the smaller order's control token should be burned (1 token burned) + let expected_burn_count = + if is_complete_fill { + -2 + } else { + -1 + } + + let control_tokens_burned = + dict.foldl(tokens(mint, own_policy), 0, fn(_, qty, acc) { acc + qty }) + + // Both owners should be paid the corresponding position tokens (Up/Down) + let a_position_tn = + when a_datum.direction is { + Up -> up_tn + Down -> down_tn + } + + let b_position_tn = + when b_datum.direction is { + Up -> up_tn + Down -> down_tn + } + + let a_owner_paid = + list.any( + outputs, + fn(Output { address: o_addr, value: o_val, .. }) { + o_addr.payment_credential == VerificationKey(a_datum.owner) && match( + o_val, + from_asset(market_script_hash, a_position_tn, matched_amount), + >=, + ) + }, + ) + + let b_owner_paid = + list.any( + outputs, + fn(Output { address: o_addr, value: o_val, .. }) { + o_addr.payment_credential == VerificationKey(b_datum.owner) && match( + o_val, + from_asset(market_script_hash, b_position_tn, matched_amount), + >=, + ) + }, + ) + + // Up and Down tokens should be minted and sent to the owners + let up_minted = quantity_of(mint, market_script_hash, up_tn) == matched_amount + let down_minted = + quantity_of(mint, market_script_hash, down_tn) == matched_amount + + // Adas should be paid to the market utxo + // The market output should have the market input's existing value plus the matched lovelace + let total_lovelace = + matched_amount * a_datum.price.numerator / a_datum.price.denominator + matched_amount * b_datum.price.numerator / b_datum.price.denominator + + expect Some(market_input) = + list.find( + inputs, + fn(i) { + i.output.address.payment_credential == Script(market_script_hash) + }, + ) + + let expected_market_value = + merge(market_input.output.value, from_lovelace(total_lovelace)) + + let market_paid = + list.any( + outputs, + fn(Output { address: o_addr, value: o_val, .. }) { + o_addr.payment_credential == Script(market_script_hash) && match( + o_val, + expected_market_value, + >=, + ) + }, + ) + + // The market utxo is already guaranteed to be consumed by the expect Some(market_input) above + and { + continuing_order_ok, + control_tokens_burned == expected_burn_count, + a_owner_paid, + b_owner_paid, + up_minted, + down_minted, + market_paid, + } +} + +pub fn validate_fill( + own_datum: OrderDatum, + own_value: Value, + own_policy: PolicyId, + filled_amount: Int, + position_token_policy: PolicyId, + tx: Transaction, +) -> Bool { + let Transaction { outputs, mint, .. } = tx + + expect [Pair(control_token_tn, 1)] = + tokens(own_value, own_policy) |> to_pairs() + + let OrderDatum { + direction: i_d_direction, + operation: i_d_operation, + price: i_d_price, + owner: i_d_owner, + expected_tokens: i_d_expected_tokens, + } = own_datum + + let expected_owner_value = + calculate_asked_tokens( + i_d_direction, + i_d_operation, + i_d_price, + filled_amount, + position_token_policy, + ) + + // Owner expected output + // addr: owner + // Value: filled tokens + let owner_output_found = + list.any( + outputs, + fn(Output { address: o_addr, value: o_val, .. }) { + o_addr.payment_credential == VerificationKey(i_d_owner) && match( + o_val, + expected_owner_value, + >=, + ) + }, + ) + + let continuing_order_ok = or { + and { + // Is complete fill + i_d_expected_tokens == filled_amount, + // Control token is burnt + quantity_of(mint, own_policy, control_token_tn) == -1, + }, + { + let expected_datum = + OrderDatum { + ..own_datum, + expected_tokens: i_d_expected_tokens - filled_amount, + } + let expected_datum_data: Data = expected_datum + + let offered_tokens = + calculate_offered_tokens( + i_d_direction, + i_d_operation, + i_d_price, + filled_amount, + position_token_policy, + ) + + let expected_order_value = merge(own_value, negate(offered_tokens)) + + // Continuing order + // addr: own_policy + // Value: own_value - filled_amount + // Datum: expected_datum + list.any( + outputs, + fn(Output { address: o_addr, value: o_val, datum: o_datum, .. }) { + if o_addr.payment_credential == Script(own_policy) { + expect InlineDatum(o_dat) = o_datum + + and { + match(o_val, expected_order_value, >=), + o_dat == expected_datum_data, + } + } else { + False + } + }, + ) + }, + } + + and { + owner_output_found, + continuing_order_ok, + } +} + +//------------------------- +// LIBRARY +//------------------------- + +pub fn calculate_asked_tokens( + dir: Direction, + op: Operation, + price: Price, + filled_amount: Int, + position_token_policy: PolicyId, +) { + when op is { + Buy -> + when dir is { + Up -> from_asset(position_token_policy, up_tn, filled_amount) + Down -> from_asset(position_token_policy, down_tn, filled_amount) + } + Sell -> from_lovelace(filled_amount * price.numerator / price.denominator) + } +} + +pub fn calculate_offered_tokens( + dir: Direction, + op: Operation, + price: Price, + filled_amount: Int, + position_token_policy: PolicyId, +) { + when op is { + Buy -> from_lovelace(filled_amount * price.numerator / price.denominator) + Sell -> + when dir is { + Up -> from_asset(position_token_policy, up_tn, filled_amount) + Down -> from_asset(position_token_policy, down_tn, filled_amount) + } + } +} diff --git a/lazer/cardano/hermes/onchain/plutus.json b/lazer/cardano/hermes/onchain/plutus.json new file mode 100644 index 00000000..0c1eda7f --- /dev/null +++ b/lazer/cardano/hermes/onchain/plutus.json @@ -0,0 +1,460 @@ +{ + "preamble": { + "title": "los-hydra-boys/hermes", + "description": "Aiken contracts for project 'los-hydra-boys/hermes'", + "version": "0.0.0", + "plutusVersion": "v3", + "compiler": { + "name": "Aiken", + "version": "v1.1.21+42babe5" + }, + "license": "Apache-2.0" + }, + "validators": [ + { + "title": "market.market.mint", + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/hermes_types~1MarketMintRedeemer" + } + }, + "parameters": [ + { + "title": "start_time", + "schema": { + "$ref": "#/definitions/hermes_types~1PosixTime" + } + }, + { + "title": "pyth_policy", + "schema": { + "$ref": "#/definitions/cardano~1assets~1PolicyId" + } + } + ], + "compiledCode": "5925e90101002229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bad0039bae00248888888889660033001300537540172232330010010032259800800c52f5c11332259800980280144cc034008cc0100100062660080080028048c030004c03400500a4dc3a4001370e90024dc4a4009370e9001488c96600266e3d22100375c601660180031300b0018b200c30020019ba5480024464660020020064466006002600400523009300a300a0019b8048006460126014003371090004dc0a4001370e90034dc3a4011374a9001488c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a2003006402d1330050053011004402c6eb8c028004dd598058009806800a01614bd6f7b63024444444444444444453001301b012980d00948966002602460306ea800a2646464b30013020002899192cc004c05c0062b3001301e37540050068b203e8acc004c05000626464b300130240028044590211bad3022001301e3754005159800980b000c566002603c6ea800a00d16407d16407080e101c180e1baa001301f0038b203a3259800980e000c566002602660360031689809180d800a0348b203a3754603c002603c00260326ea800a2c80ba444b30010028a508994c004c966002602a60366ea800626eb4c070c07cdd5980f980e1baa0018a400080d0c0780066ebcc078c07c0066eac00d22259800800c566002600400d13300500348002294101c44c96600266ebcc0780053010140008acc004cc018010dd6980f98111bab301f001898019ba630230028a5040751598009980300224001130030078a50407480e8c08400501f0ca6002003004911980f8011980f9ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c0740066eacc07800660440069112cc004cdc8a441000038acc004cdc7a44100003899802980a998119ba60024bd70000c4cc015300103d87a8000006407d19800803c006446600e0046604a66ec0dd48029ba6004001401c80f8604000480f229422942294101f48896600266e2000520008a40011598009809800c520028992cc004c050cdc300124009198008024c00400e66e0c009200440111300198008024c00400e66e0cc0300092004401080c8dc1001203040612232330010010032259800800c530103d87a80008992cc004c010006260206603c00297ae089980180198100012034301e00140712300c3301a3750002660349810101004bd704888c8cc88cc008008004896600200300389919912cc004cdc8803801456600266e3c01c00a20030064079133005005302400440786eb8c074004dd6980f0009810000a03c330050040031480024464b300130130018acc004c068dd5001c00a2c80da2b30013010001899192cc004c08000a0091640746eb4c078004c068dd5001c56600260240031323259800981000140122c80e8dd6980f000980d1baa0038acc004c01c0062b3001301a37540070028b20368acc004c0180062b3001301a37540070028b20368b2030406080c1018203030183754005222598009809800c52f5bded8c113232330010014bd6f7b630112cc00400626603e66ec0dd48031ba60034bd6f7b63044ca60026eb8c0740066eacc07800660440049112cc004cdc8005001c4cc08ccdd81ba900a374c00e00b15980099b8f00a00389981199bb037520146e9801c00626604666ec0dd48019ba600233006006001407c80f8604000280f0c8cc0040052f5bded8c044b300100189980f19bb037520086ea000d2f5bded8c113298009bae301c0019bad301d00198108012444b300133720010007133022337606ea4020dd4003802c56600266e3c02000e26604466ec0dd48041ba800700189981119bb037520066ea0008cc01801800501e203c180f800a03a406122598009809180c1baa0028991919912cc004c08400e00b1640786eb4c078004dd6980f001180f000980c9baa0028b202e48888888888a6002604a0173025302600b912cc004c074c08cdd500144c8c8c966002605600513300e302a00313300e0010048b20503029001302900130243754005164089300700748888cc896600260420051329800899912cc004c0900062646644b300130320018991919912cc004c0a8c0c4dd50014566002605060626ea8c0d4c0d800e264b3001302c303237540031323232332259800981e001c4c8cc060004566002605e60706ea800a2b3001303937540051598009819001c4c966002607c0031325980098189bad303b0018acc004cdd7801cc0040de0710234051159800cc00402a6e9a600202748907434f4e54524f4c00a400480da4466e2400400902144cdc79bae303a001488107434f4e54524f4c008a5040e514a081ca2c81c8c0f40062c81d8cc08c0340462c81ba2c81d22c81b8c0ec0162c81c8dd6981c800981c801181c800981c00098199baa0018b20623035303237540051640c11640c060660026eacc0cc008c0cc004c0c8c0b8dd51818800c5902f1bab302f30303030001330263758605e002466ebcc0c0c0b4dd5181818169baa00130183302f375200a97ae0302f302f302b37540271598009810800c4cc00800c04e2b30013023001899191991194c00566002603e00313370e0033001003804522104444f574e00404914a08172660286eb0c0cc0148cdd7981a18189baa303430313754604260626ea8004c070cc0ccdd4804a5eb82605066004004660340060109112cc004c0b0c0c8dd500144c8cc8966002605e606a6ea8006264660300022b30010078acc0040162b3001003899baf0014c103d87d80008a5040d514a081aa2941035181b1919bb0303a001303a303b00137586072606c6ea80062c81a0cdc4a400530013756604860686ea8c090c0d0dd5000c032910107434f4e54524f4c00405864660020026eacc0e0c0e4c0e4c0e4c0e4c0e4024896600200314c0103d87a80008992cc004cdd7981b00098111981c981d181b9baa0044bd7044c0accc0e4dd39981c981b0009981c981b800a5eb812f5c1133003003303b00240d4607200281b8c0d8c0ccdd500145903126002005007a4410255500040446eacc0c00048966002003148002266e01200233002002303300140c0606060606060606000260566ea804e2660040060268149029205222329800800ccc058dd59817981818181818181818161baa002003a514004444b30010028800c4ca60020093033003992cc00400e266e20dd698180012400114a08170dd71817000a008303100240bc60506ea801e60506ea801e4464b300130250018acc004c0b0dd5001c00a2c816a2b300130220018acc004c0b0dd5001c00a2c816a2c815102a18151baa002488966002604a00515980098161baa00a801c5902d4566002604400515980098161baa00a801c5902d45660026048005132598009818800c4cc008c0c00040122c8170c0b0dd500545660026032005132598009818800c4cc008c0c00040122c8170c0b0dd500545902a205440a881506eb8c0acc0a0dd5002c566002603c00513233223300c009159800981218151baa001899912cc004c098c0b0dd5000c4c8c966002604a605c6ea800633001375c6064605e6ea80066eacc0c8c0cc00a53001488100a44100800a02091194c0040060070024004444b30010028800c4c8cc8a600200d303b0059919800800802912cc00400626607666ec0dd48021ba60034bd6f7b63044ca60026eb8c0e40066eacc0e8006607c0049112cc004cdc8004001c4cc0fccdd81ba9008374c00e00b15980099b8f0080038992cc0056600200314a314a081fa2005133040337606ea4024dd30008012078329800800c022006800888966002005100189919914c00401a608e00b32330010010052259800800c4cc11ccdd81ba9004375000697adef6c608994c004dd71822800cdd69823000cc1280092225980099b9000800389982599bb037520106ea001c0162b30013371e010007132598009821800c400a26609866ec0dd48049ba8001002412066e0001c00a26609666ec0dd48019ba800233006006001411c8238609000282310061bae3040001375a60820026086004820a26607e66ec0dd48019ba60023300600600140ec81d8607800281d10061bae30340013756606a002606e00481aa605c6ea803522222598009816800c4c96600260720031323232598009818181b9baa0018acc004c0b8c0dcdd5181d981e001456600266ebcc0ecc0e0dd500098161981d181d981c1baa00d3303a302c3303a980081a4cdc001aa41819e49020404497ae03303a302a3038375401a97ae08cc004dd5981d801cdd3004488cdc4800801203c8a5040d91640d91640d8607400260740026072606a6ea8c0e00062c81b0cc0b8dd6181b981c181c181a1baa01c23375e6070606a6ea8c0e0c0d4dd500098101981b9ba90064bd7044c9660026056005132332259800981e00144c8c8c966002606660746ea80062b30013031303a3754607c607e00513232332259800981c181f1baa002899912cc004c114006264b30013371e6eb8c1040056600266ebccc03800c01130103d87980008a4504444f574e008a4502555000410115980099b87375a6084002606001715980099baf304530423754010606c6608800866088606c6608800697ae033044375066e04dd698229823003005a5eb82330013756608a015374c660200246466002002602466e080312080897a2259800800c52f5bded8c1132330473376060880026e98c8cc004004dd59823001112cc004006297adef6c608991982519bb030470013750606c6eb4c120004cc00c00cc130008c1280050481980180198248011823800a08a9119b8900100240a114a0820229410404528208030440018b20843042303f3754004660526eacc108c10cc10c0280422c81e8c100004c100008c100004c0ecdd5008459039459039181e800981e800981e181c1baa303b0028b20723303037586072002466ebcc0e8c0dcdd5181d181b9baa001302233039375201097ae0375a6072606c6ea8050c0e4c0e4c0d4dd500ec566002605a005132332259800981e00144c8c8c966002606660746ea80062b30013031303a3754607c607e00513232332259800981c181f1baa002899912cc004c114006264b30013371e6eb8c1040056600266ebccc03800c01130103d87980008a45025550008a4504444f574e00410115980099b87375a6084002606001715980099baf304530423754010606c6608800866088606c6608800697ae033044375066e04dd698229823003005a5eb82330013756608a015374c025223371200200481422941040452820808a50410060880031641086084607e6ea8008cc0a4dd598211821982180500845903d182000098200011820000981d9baa0108b20728b2072303d001303d001303c3038375460760051640e4660606eb0c0e40048cdd7981d181b9baa303a303737540026044660726ea40212f5c06eb4c0e4c0d8dd500a181c981c981a9baa01d8acc004c08800a264b3001303a0018992cc004cdc3a40026eb4c0dc0062b30013371e6eb8c0d8005220107434f4e54524f4c00898181bad30293037375401914a081aa2c81a8c0e40062c81b8cc07cdd5981c181c981c981c981c981a9baa01d00689919912cc004c0f00062646644b30013033303a37540031323259800981b181e1baa002899191919912cc004c11800e266042608a00a264b3001303c0018992cc004c120006266046608e00201116411460866ea800a2b300130390018acc004c10cdd5001401e2c82222c820904118209baa0018b2086375a6086002608600460860026084002607a6ea800a2c81d84c966002605800315980099b870019800803c03a91104444f574e00407d159800cc0040126e98cc02c034c0300064466e24004009023456600266ebcc100c0f4dd50011820181e9baa0128acc004cdd79816981e9baa002302d303d375402513370e6eb4c0bcc0f4dd500119b80375a605e607a6ea8048006294103b452820768a5040ed14a081da294103b4c00401a01b489025550004078607c60766ea80062c81c8dd5981e000981e181e800981e181c1baa303b0018b20723756607260746074002660606eb0c0e40048cdd7981d181b9baa303a303737540026044660726ea40212f5c060726072606a6ea8075033206640cc446644b30013371000200514c0103d87b80008acc004cdc4001000c530103d87980008a6103d87a800040d881b0cdc11bad3039303637540046eb4c098c0d8dd500099b82375a6072606c6ea8004dd69813181b1baa00240c88b205a3031302e37546062002605a6ea8c0c0c0c4c0b4dd5181818169baa0018b2056302e302b37540026601e6eb0c0b8c0acdd5009919baf302f302c37540020071640a460580026058605a00260506ea80162c813102618129baa00322232598009817000c4c8c966002604a60566ea800626464b30013027302d375400313259800981418171baa0018992cc004c0a4c0bcdd5000c4c966002605460606ea8006264b30013370e6eb4c0d4c0c8dd500419b8200b483403e2604c66068606a60646ea8004cc0d0c088c0c8dd5000a5eb822c8180cc88c09ccc0d4dd419b82375a606c0046eb4c0d8004cc0d4dd419b82375a606c606e0046eb4c0d8c0dc0052f5c060626ea8c050dd6981a18189baa00330313754606860626ea80062c8178c8ca60026eb4c0d40066eb4c0d4c0d80066eb4c0d4c0c8dd5001a444b3001598009817001c4cdc4800a400114a0819a298103d87a80008acc004c090006260526606e60526606e6ea0cc04000c004cc0dcdd419808001000a5eb812f5c115980099b8800148002260526606e60526606e6ea0cc040008c08c004cc0dcdd4198080019811800a5eb812f5c114c010ad8799fd8799f0101ffff0040cc81990330c0c4dd50009809a40291640b8606460666066606660666066605e6ea800e2c8168c0c4c0b8dd5000c5902c180e98169baa001302f302c37540031640a86601e6eb0c074c0acdd5000918111bad302f302c3754002605a0031640ac64b300130233029375400313259800981218151baa0018991980f800912cc00400a2646600200200844b30010018a5eb822660653001371290004dc62400937009001cdc4a4011371890004dc62401137009003a444444466446605c4646b30013371e6eb8c0f80052210475d3c793008cc004888c8cc00cdd698210009bae3042304300130030019b89480426e3120109b804803e600e90082444446600a464660886ea0cde5250375c608a00266088608a608c00297ae05980098029b8d0018998219ba930020013304337526600860066e340040052f5c11640fc4646600e46608a6ea0cdc7000a40006608a6ea4cc008c0d0dc6800800a5eb808cc0208cc118dd419b8e00148000cc118dd499801981a9b8d0010014bd7011191919824981d998249ba800733049375000a66092609400297ae033049304a304b0014bd7018008012cc004c05400a2653001001a5eb82006800888966002608200312323304c374e002660986ea40092f5c065300100180252f5c080088896600200510018cc00400e60a00053304e304f002001400c826a246530010059982618268008024c0ec00e6eb8c134c138005005191919911919801194c0040066eb0c14800a6086660a260a400c660a2980103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a80004bd702002222598008014400633001003982a8014c8c966002609800313230483305630570013305630483305630573054375400697ae030583058001305337540071598009824800c4c8c8c124cc15cc160008cc15cc160004cc15cc124cc15cc160c154dd500225eb80c164c164004c160004c14cdd5001c56600260960031323232304a33058305900333058305900233058305900133058304a3305830593056375400a97ae0305a305a00130590013058001305337540071598009820000c4c8c8c8c8c12ccc164c168010cc164c16800ccc164c168008cc164c168004cc164c12ccc164c168c15cdd500325eb80c16cc16c004c168004c164004c160004c14cdd5001c566002607e00313232323232304c3305a305b0053305a305b0043305a305b0033305a305b0023305a305b0013305a304c3305a305b3058375400e97ae0305c305c001305b001305a001305900130580013053375400715980099b87480280062646464646464609a660b660b800c660b660b800a660b660b8008660b660b8006660b660b8004660b660b8002660b6609a660b660b860b26ea80212f5c060ba60ba00260b800260b600260b400260b200260b000260a66ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c138cc170c17401ccc170c174018cc170c174014cc170c174010cc170c17400ccc170c174008cc170c174004cc170c138cc170c174c168dd5004a5eb80c178c178004c174004c170004c16c004c168004c164004c160004c14cdd5001c56600266e1d200e0018991919191919191918279982e982f0041982e982f0039982e982f0031982e982f0029982e982f0021982e982f0019982e982f0011982e982f0009982e98279982e982f182d9baa00a4bd70182f982f800982f000982e800982e000982d800982d000982c800982c00098299baa0038acc004cdc3a4020003132323232323232323230503305e305f0093305e305f0083305e305f0073305e305f0063305e305f0053305e305f0043305e305f0033305e305f0023305e305f0013305e30503305e305f305c375401697ae030603060001305f001305e001305d001305c001305b001305a001305900130580013053375400715980099b874804800626464646464646464646460a2660be60c0014660be60c0012660be60c0010660be60c000e660be60c000c660be60c000a660be60c0008660be60c0006660be60c0004660be60c0002660be60a2660be60c060ba6ea80312f5c060c260c200260c000260be00260bc00260ba00260b800260b600260b400260b200260b000260a66ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c148cc180c18402ccc180c184028cc180c184024cc180c184020cc180c18401ccc180c184018cc180c184014cc180c184010cc180c18400ccc180c184008cc180c184004cc180c148cc180c184c178dd5006a5eb80c188c188004c184004c180004c17c004c178004c174004c170004c16c004c168004c164004c160004c14cdd5001c56600266e1d201600189919191919191919191919191829998309831006198309831005998309831005198309831004998309831004198309831003998309831003198309831002998309831002198309831001998309831001198309831000998309829998309831182f9baa00e4bd7018319831800983100098308009830000982f800982f000982e800982e000982d800982d000982c800982c00098299baa003899191919191919191919191918299983098310061983098310059983098310051983098310049983098310041983098310039983098310031983098310029983098310021983098310019983098310011983098310009983098311831800998309829998309831182f9baa00e4bd7025eb80c188004c184004c180004c17c004c178004c174004c170004c16c004c168004c164004c160004c14cdd5001a0a24144828905120a24144828905120a24144828905118289baa0013054002400c8290dd718289829000991acc004c07800e2653001001a5eb820088008889660026094003123233055374e002660aa6ea40092f5c065300100180252f5c080088896600200510018cc00400e60b2005330573058002001400c82b2246530010059982a982b0008024c11000e6eb8c158c15c0050051802800a09e8b2098375c60a260a4008530012232598009800a40211598009800a4001148002266e39220108010204081020408000002413d1598009800a408113370490400219801801980980144cdc124101010100406600600666e00009203f413c8278dc4000c888c8cc150c00cdd6982a8009982a182a982b000a5eb80c00c006660a06ea0cdc7000a4000660a06ea4cc034c0fcdc6800800a5eb81222323298009198029191982c1ba833794940dd7182c8009982c182c982d000a5eb816600260326e340062660ae6ea4c058004cc15cdd49980c180b9b8d0010014bd704590531191801acc004c13c006298103d87a8000898251982c1ba80014bd7020a830030019bad3056003911191acc006600260a06eb4c16800694294505544cc02000c8c014c130cc168dd4000a5eb8226016600898103d87a800041546eb8c168c16c004cc160dd419b8e00148000cc160dd49980a98239b8d0010014bd7024446b3001304f00289801918259982c800a5eb822b3001304c00289801918211982c800a5eb822b3001304e00289801919ba548010cc1640052f5c1159800982180144cc01c8c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001304e371a00313305937526040002660b26ea4cc098c094dc6800800a5eb822c82a88cdd2a400c660b26ea00052f5c1159800982100144cc01c8c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001304e371a00313305937526040002660b26ea4cc098c094dc6800800a5eb822c82a88cdd2a4010660b26ea16600266e20005208080048800c4cdc080098032404082a92f5c115980099b874802800a26006466e95200a330590014bd70456600266e1d200c002899800919ba548030cc1640052f5c0464660b46ea0c018dd6982d8009982d182d982e000a5eb80c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2b30013370e900700144cc0048cdd2a401c660b200297ae02323305a375066f29281bae305b0013305a305b305c0014bd702cc004c06cdc6800c4cc164dd4980c0009982c9ba93301a3019371a00200297ae08b20aa8acc004cdc3a402000513300123374a90081982c800a5eb808c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2b30013370e9009001448c8c8cc16ccdd2a4024660b660b800297ae03305b305c305d0014bd701800801198041191982d9ba833794940dd7182e0009982d982e182e800a5eb8166002609e6e340062660b46ea4c084004cc168dd49981398131b8d0010014bd7045905612cc004c1440062980103d87980008acc004c138006298103d87a80008acc004c140006298103d87b80008acc004c114006298103d87c80008acc004c110006298103d87d80008b20ac415882b105620ac8acc004cdc3a40280051300323374a900a1982c800a5eb822b30013370e900b00144c00c8cdd2a402c660b200297ae08acc004cdc3a403000513300123374a900c1982c800a5eb808c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2c82a105420a8415082a105420a8415082a105420a8415082a0dd7182c982d003096600266e2000520808080808080808080028800c4cdc0800980124100028288c00c00c6eb4c13800488cc13c008cc13cdd4800a5eb80c8cc134dd419b8e00148000cc134dd499805181e1b8d0010014bd701bae304d304e001323304c375066f29281bae304d0013304c304d304e0014bd702cc004c058dc6800c4cc12cdd49808800998259ba9330143013371a00200297ae08b208e411916410c6e3120024590391bae303e303f0015980098039b8d00189981e1ba930020013303c37526600a60086e340040052f5c11640e06eb8c0acc0e4dd5198171191acc004cdc79bae303e00148904b9011a820089191919191919199119823181c198231823803998231ba90013304630470024bd70198231823982400125eb80d660026024003125980099b89002371a00313304537526601e0040026608a6ea66002005337026e3400400a002b8c25eb822c820a2c8200dd7182298230011bae3045004375a608800264660866ea0cde5250375c6088002660866088608a00297ae059800981b9b8d0018998211ba930090013304237526601e601c6e340040052f5c11640f86eb8c108c10c004d6600294624b30013371290201b8d0018998209ba93300b48100004cc104dd4cc005204099b80371a002901fc0057184bd7045903d45903c1bae30413042001300100259800a51892cc004cdc4a4100026e3400626607e6ea4cc0252080010013303f37533001482000666e00dc6800a40ff0015c612f5c11640ed1640e91640e46eb8c0f8c0fc00566002600e6e340062660786ea4c008004cc0f0dd49980298021b8d0010014bd704590381bae303c00a300348010c00d200819801001181a000a062899180118198019bae303100240bc6eb0c0b8c0acdd5000c5902919199119801001000912cc004006298103d87a80008992cc004cdd78021816800c4c088cc0c0c0b80052f5c1133003003303200240b060600028170dd5981718179817981798179817981798179817981798159baa0033374a900219816180a99816181698171817181718151baa302d302a375400297ae04bd7045902819198008009bac301a302a375400444b30010018a6103d87a80008992cc006600266ebc00530103d87a8000a50a5140a91001899801801981800120543259800cc004dd5980e18161baa301c302c3754003374c6605c66ec0dd48031ba63302e3376098010b4a50797468205374617465004c010101004bd6f7b63025eb7bdb182449450124566002604460566ea8c0bcc0b0dd5181798161baa301c302c375400313259800981298161baa0018992cc004c09cc0b4dd5000c4c8c8c8c8cc89660026070007132598009817181a1baa0018991919194c004dd6981e000cdd7181e0024dd6981e001cdd7181e00124444b300130410058998181bab304000e225980080144cc0c8030896600200513035330430144bd7044c8c8cc07cc1080084c00cc11c010dd7182100098220012084899191980e98208010980198228021bae303f001304200241011640f8303c001303b001303a001303537540031640cc606e00d1640d46eb8c0d4004dd5981a801181a800981a000981980098171baa0018b20583030302d37540031640ac603c60586ea8c070c0b0dd5000c5902a4530103d87a800040a8605c0028160452689b2b200601", + "hash": "cdd7308205adaf89370d6f5fe5225b10876165977f2ce4836b67e645" + }, + { + "title": "market.market.spend", + "datum": { + "title": "op_datum", + "schema": { + "$ref": "#/definitions/hermes_types~1MarketDatum" + } + }, + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/hermes_types~1MarketRedeemer" + } + }, + "parameters": [ + { + "title": "start_time", + "schema": { + "$ref": "#/definitions/hermes_types~1PosixTime" + } + }, + { + "title": "pyth_policy", + "schema": { + "$ref": "#/definitions/cardano~1assets~1PolicyId" + } + } + ], + "compiledCode": "5925e90101002229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bad0039bae00248888888889660033001300537540172232330010010032259800800c52f5c11332259800980280144cc034008cc0100100062660080080028048c030004c03400500a4dc3a4001370e90024dc4a4009370e9001488c96600266e3d22100375c601660180031300b0018b200c30020019ba5480024464660020020064466006002600400523009300a300a0019b8048006460126014003371090004dc0a4001370e90034dc3a4011374a9001488c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a2003006402d1330050053011004402c6eb8c028004dd598058009806800a01614bd6f7b63024444444444444444453001301b012980d00948966002602460306ea800a2646464b30013020002899192cc004c05c0062b3001301e37540050068b203e8acc004c05000626464b300130240028044590211bad3022001301e3754005159800980b000c566002603c6ea800a00d16407d16407080e101c180e1baa001301f0038b203a3259800980e000c566002602660360031689809180d800a0348b203a3754603c002603c00260326ea800a2c80ba444b30010028a508994c004c966002602a60366ea800626eb4c070c07cdd5980f980e1baa0018a400080d0c0780066ebcc078c07c0066eac00d22259800800c566002600400d13300500348002294101c44c96600266ebcc0780053010140008acc004cc018010dd6980f98111bab301f001898019ba630230028a5040751598009980300224001130030078a50407480e8c08400501f0ca6002003004911980f8011980f9ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c0740066eacc07800660440069112cc004cdc8a441000038acc004cdc7a44100003899802980a998119ba60024bd70000c4cc015300103d87a8000006407d19800803c006446600e0046604a66ec0dd48029ba6004001401c80f8604000480f229422942294101f48896600266e2000520008a40011598009809800c520028992cc004c050cdc300124009198008024c00400e66e0c009200440111300198008024c00400e66e0cc0300092004401080c8dc1001203040612232330010010032259800800c530103d87a80008992cc004c010006260206603c00297ae089980180198100012034301e00140712300c3301a3750002660349810101004bd704888c8cc88cc008008004896600200300389919912cc004cdc8803801456600266e3c01c00a20030064079133005005302400440786eb8c074004dd6980f0009810000a03c330050040031480024464b300130130018acc004c068dd5001c00a2c80da2b30013010001899192cc004c08000a0091640746eb4c078004c068dd5001c56600260240031323259800981000140122c80e8dd6980f000980d1baa0038acc004c01c0062b3001301a37540070028b20368acc004c0180062b3001301a37540070028b20368b2030406080c1018203030183754005222598009809800c52f5bded8c113232330010014bd6f7b630112cc00400626603e66ec0dd48031ba60034bd6f7b63044ca60026eb8c0740066eacc07800660440049112cc004cdc8005001c4cc08ccdd81ba900a374c00e00b15980099b8f00a00389981199bb037520146e9801c00626604666ec0dd48019ba600233006006001407c80f8604000280f0c8cc0040052f5bded8c044b300100189980f19bb037520086ea000d2f5bded8c113298009bae301c0019bad301d00198108012444b300133720010007133022337606ea4020dd4003802c56600266e3c02000e26604466ec0dd48041ba800700189981119bb037520066ea0008cc01801800501e203c180f800a03a406122598009809180c1baa0028991919912cc004c08400e00b1640786eb4c078004dd6980f001180f000980c9baa0028b202e48888888888a6002604a0173025302600b912cc004c074c08cdd500144c8c8c966002605600513300e302a00313300e0010048b20503029001302900130243754005164089300700748888cc896600260420051329800899912cc004c0900062646644b300130320018991919912cc004c0a8c0c4dd50014566002605060626ea8c0d4c0d800e264b3001302c303237540031323232332259800981e001c4c8cc060004566002605e60706ea800a2b3001303937540051598009819001c4c966002607c0031325980098189bad303b0018acc004cdd7801cc0040de0710234051159800cc00402a6e9a600202748907434f4e54524f4c00a400480da4466e2400400902144cdc79bae303a001488107434f4e54524f4c008a5040e514a081ca2c81c8c0f40062c81d8cc08c0340462c81ba2c81d22c81b8c0ec0162c81c8dd6981c800981c801181c800981c00098199baa0018b20623035303237540051640c11640c060660026eacc0cc008c0cc004c0c8c0b8dd51818800c5902f1bab302f30303030001330263758605e002466ebcc0c0c0b4dd5181818169baa00130183302f375200a97ae0302f302f302b37540271598009810800c4cc00800c04e2b30013023001899191991194c00566002603e00313370e0033001003804522104444f574e00404914a08172660286eb0c0cc0148cdd7981a18189baa303430313754604260626ea8004c070cc0ccdd4804a5eb82605066004004660340060109112cc004c0b0c0c8dd500144c8cc8966002605e606a6ea8006264660300022b30010078acc0040162b3001003899baf0014c103d87d80008a5040d514a081aa2941035181b1919bb0303a001303a303b00137586072606c6ea80062c81a0cdc4a400530013756604860686ea8c090c0d0dd5000c032910107434f4e54524f4c00405864660020026eacc0e0c0e4c0e4c0e4c0e4c0e4024896600200314c0103d87a80008992cc004cdd7981b00098111981c981d181b9baa0044bd7044c0accc0e4dd39981c981b0009981c981b800a5eb812f5c1133003003303b00240d4607200281b8c0d8c0ccdd500145903126002005007a4410255500040446eacc0c00048966002003148002266e01200233002002303300140c0606060606060606000260566ea804e2660040060268149029205222329800800ccc058dd59817981818181818181818161baa002003a514004444b30010028800c4ca60020093033003992cc00400e266e20dd698180012400114a08170dd71817000a008303100240bc60506ea801e60506ea801e4464b300130250018acc004c0b0dd5001c00a2c816a2b300130220018acc004c0b0dd5001c00a2c816a2c815102a18151baa002488966002604a00515980098161baa00a801c5902d4566002604400515980098161baa00a801c5902d45660026048005132598009818800c4cc008c0c00040122c8170c0b0dd500545660026032005132598009818800c4cc008c0c00040122c8170c0b0dd500545902a205440a881506eb8c0acc0a0dd5002c566002603c00513233223300c009159800981218151baa001899912cc004c098c0b0dd5000c4c8c966002604a605c6ea800633001375c6064605e6ea80066eacc0c8c0cc00a53001488100a44100800a02091194c0040060070024004444b30010028800c4c8cc8a600200d303b0059919800800802912cc00400626607666ec0dd48021ba60034bd6f7b63044ca60026eb8c0e40066eacc0e8006607c0049112cc004cdc8004001c4cc0fccdd81ba9008374c00e00b15980099b8f0080038992cc0056600200314a314a081fa2005133040337606ea4024dd30008012078329800800c022006800888966002005100189919914c00401a608e00b32330010010052259800800c4cc11ccdd81ba9004375000697adef6c608994c004dd71822800cdd69823000cc1280092225980099b9000800389982599bb037520106ea001c0162b30013371e010007132598009821800c400a26609866ec0dd48049ba8001002412066e0001c00a26609666ec0dd48019ba800233006006001411c8238609000282310061bae3040001375a60820026086004820a26607e66ec0dd48019ba60023300600600140ec81d8607800281d10061bae30340013756606a002606e00481aa605c6ea803522222598009816800c4c96600260720031323232598009818181b9baa0018acc004c0b8c0dcdd5181d981e001456600266ebcc0ecc0e0dd500098161981d181d981c1baa00d3303a302c3303a980081a4cdc001aa41819e49020404497ae03303a302a3038375401a97ae08cc004dd5981d801cdd3004488cdc4800801203c8a5040d91640d91640d8607400260740026072606a6ea8c0e00062c81b0cc0b8dd6181b981c181c181a1baa01c23375e6070606a6ea8c0e0c0d4dd500098101981b9ba90064bd7044c9660026056005132332259800981e00144c8c8c966002606660746ea80062b30013031303a3754607c607e00513232332259800981c181f1baa002899912cc004c114006264b30013371e6eb8c1040056600266ebccc03800c01130103d87980008a4504444f574e008a4502555000410115980099b87375a6084002606001715980099baf304530423754010606c6608800866088606c6608800697ae033044375066e04dd698229823003005a5eb82330013756608a015374c660200246466002002602466e080312080897a2259800800c52f5bded8c1132330473376060880026e98c8cc004004dd59823001112cc004006297adef6c608991982519bb030470013750606c6eb4c120004cc00c00cc130008c1280050481980180198248011823800a08a9119b8900100240a114a0820229410404528208030440018b20843042303f3754004660526eacc108c10cc10c0280422c81e8c100004c100008c100004c0ecdd5008459039459039181e800981e800981e181c1baa303b0028b20723303037586072002466ebcc0e8c0dcdd5181d181b9baa001302233039375201097ae0375a6072606c6ea8050c0e4c0e4c0d4dd500ec566002605a005132332259800981e00144c8c8c966002606660746ea80062b30013031303a3754607c607e00513232332259800981c181f1baa002899912cc004c114006264b30013371e6eb8c1040056600266ebccc03800c01130103d87980008a45025550008a4504444f574e00410115980099b87375a6084002606001715980099baf304530423754010606c6608800866088606c6608800697ae033044375066e04dd698229823003005a5eb82330013756608a015374c025223371200200481422941040452820808a50410060880031641086084607e6ea8008cc0a4dd598211821982180500845903d182000098200011820000981d9baa0108b20728b2072303d001303d001303c3038375460760051640e4660606eb0c0e40048cdd7981d181b9baa303a303737540026044660726ea40212f5c06eb4c0e4c0d8dd500a181c981c981a9baa01d8acc004c08800a264b3001303a0018992cc004cdc3a40026eb4c0dc0062b30013371e6eb8c0d8005220107434f4e54524f4c00898181bad30293037375401914a081aa2c81a8c0e40062c81b8cc07cdd5981c181c981c981c981c981a9baa01d00689919912cc004c0f00062646644b30013033303a37540031323259800981b181e1baa002899191919912cc004c11800e266042608a00a264b3001303c0018992cc004c120006266046608e00201116411460866ea800a2b300130390018acc004c10cdd5001401e2c82222c820904118209baa0018b2086375a6086002608600460860026084002607a6ea800a2c81d84c966002605800315980099b870019800803c03a91104444f574e00407d159800cc0040126e98cc02c034c0300064466e24004009023456600266ebcc100c0f4dd50011820181e9baa0128acc004cdd79816981e9baa002302d303d375402513370e6eb4c0bcc0f4dd500119b80375a605e607a6ea8048006294103b452820768a5040ed14a081da294103b4c00401a01b489025550004078607c60766ea80062c81c8dd5981e000981e181e800981e181c1baa303b0018b20723756607260746074002660606eb0c0e40048cdd7981d181b9baa303a303737540026044660726ea40212f5c060726072606a6ea8075033206640cc446644b30013371000200514c0103d87b80008acc004cdc4001000c530103d87980008a6103d87a800040d881b0cdc11bad3039303637540046eb4c098c0d8dd500099b82375a6072606c6ea8004dd69813181b1baa00240c88b205a3031302e37546062002605a6ea8c0c0c0c4c0b4dd5181818169baa0018b2056302e302b37540026601e6eb0c0b8c0acdd5009919baf302f302c37540020071640a460580026058605a00260506ea80162c813102618129baa00322232598009817000c4c8c966002604a60566ea800626464b30013027302d375400313259800981418171baa0018992cc004c0a4c0bcdd5000c4c966002605460606ea8006264b30013370e6eb4c0d4c0c8dd500419b8200b483403e2604c66068606a60646ea8004cc0d0c088c0c8dd5000a5eb822c8180cc88c09ccc0d4dd419b82375a606c0046eb4c0d8004cc0d4dd419b82375a606c606e0046eb4c0d8c0dc0052f5c060626ea8c050dd6981a18189baa00330313754606860626ea80062c8178c8ca60026eb4c0d40066eb4c0d4c0d80066eb4c0d4c0c8dd5001a444b3001598009817001c4cdc4800a400114a0819a298103d87a80008acc004c090006260526606e60526606e6ea0cc04000c004cc0dcdd419808001000a5eb812f5c115980099b8800148002260526606e60526606e6ea0cc040008c08c004cc0dcdd4198080019811800a5eb812f5c114c010ad8799fd8799f0101ffff0040cc81990330c0c4dd50009809a40291640b8606460666066606660666066605e6ea800e2c8168c0c4c0b8dd5000c5902c180e98169baa001302f302c37540031640a86601e6eb0c074c0acdd5000918111bad302f302c3754002605a0031640ac64b300130233029375400313259800981218151baa0018991980f800912cc00400a2646600200200844b30010018a5eb822660653001371290004dc62400937009001cdc4a4011371890004dc62401137009003a444444466446605c4646b30013371e6eb8c0f80052210475d3c793008cc004888c8cc00cdd698210009bae3042304300130030019b89480426e3120109b804803e600e90082444446600a464660886ea0cde5250375c608a00266088608a608c00297ae05980098029b8d0018998219ba930020013304337526600860066e340040052f5c11640fc4646600e46608a6ea0cdc7000a40006608a6ea4cc008c0d0dc6800800a5eb808cc0208cc118dd419b8e00148000cc118dd499801981a9b8d0010014bd7011191919824981d998249ba800733049375000a66092609400297ae033049304a304b0014bd7018008012cc004c05400a2653001001a5eb82006800888966002608200312323304c374e002660986ea40092f5c065300100180252f5c080088896600200510018cc00400e60a00053304e304f002001400c826a246530010059982618268008024c0ec00e6eb8c134c138005005191919911919801194c0040066eb0c14800a6086660a260a400c660a2980103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a80004bd702002222598008014400633001003982a8014c8c966002609800313230483305630570013305630483305630573054375400697ae030583058001305337540071598009824800c4c8c8c124cc15cc160008cc15cc160004cc15cc124cc15cc160c154dd500225eb80c164c164004c160004c14cdd5001c56600260960031323232304a33058305900333058305900233058305900133058304a3305830593056375400a97ae0305a305a00130590013058001305337540071598009820000c4c8c8c8c8c12ccc164c168010cc164c16800ccc164c168008cc164c168004cc164c12ccc164c168c15cdd500325eb80c16cc16c004c168004c164004c160004c14cdd5001c566002607e00313232323232304c3305a305b0053305a305b0043305a305b0033305a305b0023305a305b0013305a304c3305a305b3058375400e97ae0305c305c001305b001305a001305900130580013053375400715980099b87480280062646464646464609a660b660b800c660b660b800a660b660b8008660b660b8006660b660b8004660b660b8002660b6609a660b660b860b26ea80212f5c060ba60ba00260b800260b600260b400260b200260b000260a66ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c138cc170c17401ccc170c174018cc170c174014cc170c174010cc170c17400ccc170c174008cc170c174004cc170c138cc170c174c168dd5004a5eb80c178c178004c174004c170004c16c004c168004c164004c160004c14cdd5001c56600266e1d200e0018991919191919191918279982e982f0041982e982f0039982e982f0031982e982f0029982e982f0021982e982f0019982e982f0011982e982f0009982e98279982e982f182d9baa00a4bd70182f982f800982f000982e800982e000982d800982d000982c800982c00098299baa0038acc004cdc3a4020003132323232323232323230503305e305f0093305e305f0083305e305f0073305e305f0063305e305f0053305e305f0043305e305f0033305e305f0023305e305f0013305e30503305e305f305c375401697ae030603060001305f001305e001305d001305c001305b001305a001305900130580013053375400715980099b874804800626464646464646464646460a2660be60c0014660be60c0012660be60c0010660be60c000e660be60c000c660be60c000a660be60c0008660be60c0006660be60c0004660be60c0002660be60a2660be60c060ba6ea80312f5c060c260c200260c000260be00260bc00260ba00260b800260b600260b400260b200260b000260a66ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c148cc180c18402ccc180c184028cc180c184024cc180c184020cc180c18401ccc180c184018cc180c184014cc180c184010cc180c18400ccc180c184008cc180c184004cc180c148cc180c184c178dd5006a5eb80c188c188004c184004c180004c17c004c178004c174004c170004c16c004c168004c164004c160004c14cdd5001c56600266e1d201600189919191919191919191919191829998309831006198309831005998309831005198309831004998309831004198309831003998309831003198309831002998309831002198309831001998309831001198309831000998309829998309831182f9baa00e4bd7018319831800983100098308009830000982f800982f000982e800982e000982d800982d000982c800982c00098299baa003899191919191919191919191918299983098310061983098310059983098310051983098310049983098310041983098310039983098310031983098310029983098310021983098310019983098310011983098310009983098311831800998309829998309831182f9baa00e4bd7025eb80c188004c184004c180004c17c004c178004c174004c170004c16c004c168004c164004c160004c14cdd5001a0a24144828905120a24144828905120a24144828905118289baa0013054002400c8290dd718289829000991acc004c07800e2653001001a5eb820088008889660026094003123233055374e002660aa6ea40092f5c065300100180252f5c080088896600200510018cc00400e60b2005330573058002001400c82b2246530010059982a982b0008024c11000e6eb8c158c15c0050051802800a09e8b2098375c60a260a4008530012232598009800a40211598009800a4001148002266e39220108010204081020408000002413d1598009800a408113370490400219801801980980144cdc124101010100406600600666e00009203f413c8278dc4000c888c8cc150c00cdd6982a8009982a182a982b000a5eb80c00c006660a06ea0cdc7000a4000660a06ea4cc034c0fcdc6800800a5eb81222323298009198029191982c1ba833794940dd7182c8009982c182c982d000a5eb816600260326e340062660ae6ea4c058004cc15cdd49980c180b9b8d0010014bd704590531191801acc004c13c006298103d87a8000898251982c1ba80014bd7020a830030019bad3056003911191acc006600260a06eb4c16800694294505544cc02000c8c014c130cc168dd4000a5eb8226016600898103d87a800041546eb8c168c16c004cc160dd419b8e00148000cc160dd49980a98239b8d0010014bd7024446b3001304f00289801918259982c800a5eb822b3001304c00289801918211982c800a5eb822b3001304e00289801919ba548010cc1640052f5c1159800982180144cc01c8c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001304e371a00313305937526040002660b26ea4cc098c094dc6800800a5eb822c82a88cdd2a400c660b26ea00052f5c1159800982100144cc01c8c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001304e371a00313305937526040002660b26ea4cc098c094dc6800800a5eb822c82a88cdd2a4010660b26ea16600266e20005208080048800c4cdc080098032404082a92f5c115980099b874802800a26006466e95200a330590014bd70456600266e1d200c002899800919ba548030cc1640052f5c0464660b46ea0c018dd6982d8009982d182d982e000a5eb80c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2b30013370e900700144cc0048cdd2a401c660b200297ae02323305a375066f29281bae305b0013305a305b305c0014bd702cc004c06cdc6800c4cc164dd4980c0009982c9ba93301a3019371a00200297ae08b20aa8acc004cdc3a402000513300123374a90081982c800a5eb808c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2b30013370e9009001448c8c8cc16ccdd2a4024660b660b800297ae03305b305c305d0014bd701800801198041191982d9ba833794940dd7182e0009982d982e182e800a5eb8166002609e6e340062660b46ea4c084004cc168dd49981398131b8d0010014bd7045905612cc004c1440062980103d87980008acc004c138006298103d87a80008acc004c140006298103d87b80008acc004c114006298103d87c80008acc004c110006298103d87d80008b20ac415882b105620ac8acc004cdc3a40280051300323374a900a1982c800a5eb822b30013370e900b00144c00c8cdd2a402c660b200297ae08acc004cdc3a403000513300123374a900c1982c800a5eb808c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2c82a105420a8415082a105420a8415082a105420a8415082a0dd7182c982d003096600266e2000520808080808080808080028800c4cdc0800980124100028288c00c00c6eb4c13800488cc13c008cc13cdd4800a5eb80c8cc134dd419b8e00148000cc134dd499805181e1b8d0010014bd701bae304d304e001323304c375066f29281bae304d0013304c304d304e0014bd702cc004c058dc6800c4cc12cdd49808800998259ba9330143013371a00200297ae08b208e411916410c6e3120024590391bae303e303f0015980098039b8d00189981e1ba930020013303c37526600a60086e340040052f5c11640e06eb8c0acc0e4dd5198171191acc004cdc79bae303e00148904b9011a820089191919191919199119823181c198231823803998231ba90013304630470024bd70198231823982400125eb80d660026024003125980099b89002371a00313304537526601e0040026608a6ea66002005337026e3400400a002b8c25eb822c820a2c8200dd7182298230011bae3045004375a608800264660866ea0cde5250375c6088002660866088608a00297ae059800981b9b8d0018998211ba930090013304237526601e601c6e340040052f5c11640f86eb8c108c10c004d6600294624b30013371290201b8d0018998209ba93300b48100004cc104dd4cc005204099b80371a002901fc0057184bd7045903d45903c1bae30413042001300100259800a51892cc004cdc4a4100026e3400626607e6ea4cc0252080010013303f37533001482000666e00dc6800a40ff0015c612f5c11640ed1640e91640e46eb8c0f8c0fc00566002600e6e340062660786ea4c008004cc0f0dd49980298021b8d0010014bd704590381bae303c00a300348010c00d200819801001181a000a062899180118198019bae303100240bc6eb0c0b8c0acdd5000c5902919199119801001000912cc004006298103d87a80008992cc004cdd78021816800c4c088cc0c0c0b80052f5c1133003003303200240b060600028170dd5981718179817981798179817981798179817981798159baa0033374a900219816180a99816181698171817181718151baa302d302a375400297ae04bd7045902819198008009bac301a302a375400444b30010018a6103d87a80008992cc006600266ebc00530103d87a8000a50a5140a91001899801801981800120543259800cc004dd5980e18161baa301c302c3754003374c6605c66ec0dd48031ba63302e3376098010b4a50797468205374617465004c010101004bd6f7b63025eb7bdb182449450124566002604460566ea8c0bcc0b0dd5181798161baa301c302c375400313259800981298161baa0018992cc004c09cc0b4dd5000c4c8c8c8c8cc89660026070007132598009817181a1baa0018991919194c004dd6981e000cdd7181e0024dd6981e001cdd7181e00124444b300130410058998181bab304000e225980080144cc0c8030896600200513035330430144bd7044c8c8cc07cc1080084c00cc11c010dd7182100098220012084899191980e98208010980198228021bae303f001304200241011640f8303c001303b001303a001303537540031640cc606e00d1640d46eb8c0d4004dd5981a801181a800981a000981980098171baa0018b20583030302d37540031640ac603c60586ea8c070c0b0dd5000c5902a4530103d87a800040a8605c0028160452689b2b200601", + "hash": "cdd7308205adaf89370d6f5fe5225b10876165977f2ce4836b67e645" + }, + { + "title": "market.market.else", + "redeemer": { + "schema": {} + }, + "parameters": [ + { + "title": "start_time", + "schema": { + "$ref": "#/definitions/hermes_types~1PosixTime" + } + }, + { + "title": "pyth_policy", + "schema": { + "$ref": "#/definitions/cardano~1assets~1PolicyId" + } + } + ], + "compiledCode": "5925e90101002229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bad0039bae00248888888889660033001300537540172232330010010032259800800c52f5c11332259800980280144cc034008cc0100100062660080080028048c030004c03400500a4dc3a4001370e90024dc4a4009370e9001488c96600266e3d22100375c601660180031300b0018b200c30020019ba5480024464660020020064466006002600400523009300a300a0019b8048006460126014003371090004dc0a4001370e90034dc3a4011374a9001488c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a2003006402d1330050053011004402c6eb8c028004dd598058009806800a01614bd6f7b63024444444444444444453001301b012980d00948966002602460306ea800a2646464b30013020002899192cc004c05c0062b3001301e37540050068b203e8acc004c05000626464b300130240028044590211bad3022001301e3754005159800980b000c566002603c6ea800a00d16407d16407080e101c180e1baa001301f0038b203a3259800980e000c566002602660360031689809180d800a0348b203a3754603c002603c00260326ea800a2c80ba444b30010028a508994c004c966002602a60366ea800626eb4c070c07cdd5980f980e1baa0018a400080d0c0780066ebcc078c07c0066eac00d22259800800c566002600400d13300500348002294101c44c96600266ebcc0780053010140008acc004cc018010dd6980f98111bab301f001898019ba630230028a5040751598009980300224001130030078a50407480e8c08400501f0ca6002003004911980f8011980f9ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c0740066eacc07800660440069112cc004cdc8a441000038acc004cdc7a44100003899802980a998119ba60024bd70000c4cc015300103d87a8000006407d19800803c006446600e0046604a66ec0dd48029ba6004001401c80f8604000480f229422942294101f48896600266e2000520008a40011598009809800c520028992cc004c050cdc300124009198008024c00400e66e0c009200440111300198008024c00400e66e0cc0300092004401080c8dc1001203040612232330010010032259800800c530103d87a80008992cc004c010006260206603c00297ae089980180198100012034301e00140712300c3301a3750002660349810101004bd704888c8cc88cc008008004896600200300389919912cc004cdc8803801456600266e3c01c00a20030064079133005005302400440786eb8c074004dd6980f0009810000a03c330050040031480024464b300130130018acc004c068dd5001c00a2c80da2b30013010001899192cc004c08000a0091640746eb4c078004c068dd5001c56600260240031323259800981000140122c80e8dd6980f000980d1baa0038acc004c01c0062b3001301a37540070028b20368acc004c0180062b3001301a37540070028b20368b2030406080c1018203030183754005222598009809800c52f5bded8c113232330010014bd6f7b630112cc00400626603e66ec0dd48031ba60034bd6f7b63044ca60026eb8c0740066eacc07800660440049112cc004cdc8005001c4cc08ccdd81ba900a374c00e00b15980099b8f00a00389981199bb037520146e9801c00626604666ec0dd48019ba600233006006001407c80f8604000280f0c8cc0040052f5bded8c044b300100189980f19bb037520086ea000d2f5bded8c113298009bae301c0019bad301d00198108012444b300133720010007133022337606ea4020dd4003802c56600266e3c02000e26604466ec0dd48041ba800700189981119bb037520066ea0008cc01801800501e203c180f800a03a406122598009809180c1baa0028991919912cc004c08400e00b1640786eb4c078004dd6980f001180f000980c9baa0028b202e48888888888a6002604a0173025302600b912cc004c074c08cdd500144c8c8c966002605600513300e302a00313300e0010048b20503029001302900130243754005164089300700748888cc896600260420051329800899912cc004c0900062646644b300130320018991919912cc004c0a8c0c4dd50014566002605060626ea8c0d4c0d800e264b3001302c303237540031323232332259800981e001c4c8cc060004566002605e60706ea800a2b3001303937540051598009819001c4c966002607c0031325980098189bad303b0018acc004cdd7801cc0040de0710234051159800cc00402a6e9a600202748907434f4e54524f4c00a400480da4466e2400400902144cdc79bae303a001488107434f4e54524f4c008a5040e514a081ca2c81c8c0f40062c81d8cc08c0340462c81ba2c81d22c81b8c0ec0162c81c8dd6981c800981c801181c800981c00098199baa0018b20623035303237540051640c11640c060660026eacc0cc008c0cc004c0c8c0b8dd51818800c5902f1bab302f30303030001330263758605e002466ebcc0c0c0b4dd5181818169baa00130183302f375200a97ae0302f302f302b37540271598009810800c4cc00800c04e2b30013023001899191991194c00566002603e00313370e0033001003804522104444f574e00404914a08172660286eb0c0cc0148cdd7981a18189baa303430313754604260626ea8004c070cc0ccdd4804a5eb82605066004004660340060109112cc004c0b0c0c8dd500144c8cc8966002605e606a6ea8006264660300022b30010078acc0040162b3001003899baf0014c103d87d80008a5040d514a081aa2941035181b1919bb0303a001303a303b00137586072606c6ea80062c81a0cdc4a400530013756604860686ea8c090c0d0dd5000c032910107434f4e54524f4c00405864660020026eacc0e0c0e4c0e4c0e4c0e4c0e4024896600200314c0103d87a80008992cc004cdd7981b00098111981c981d181b9baa0044bd7044c0accc0e4dd39981c981b0009981c981b800a5eb812f5c1133003003303b00240d4607200281b8c0d8c0ccdd500145903126002005007a4410255500040446eacc0c00048966002003148002266e01200233002002303300140c0606060606060606000260566ea804e2660040060268149029205222329800800ccc058dd59817981818181818181818161baa002003a514004444b30010028800c4ca60020093033003992cc00400e266e20dd698180012400114a08170dd71817000a008303100240bc60506ea801e60506ea801e4464b300130250018acc004c0b0dd5001c00a2c816a2b300130220018acc004c0b0dd5001c00a2c816a2c815102a18151baa002488966002604a00515980098161baa00a801c5902d4566002604400515980098161baa00a801c5902d45660026048005132598009818800c4cc008c0c00040122c8170c0b0dd500545660026032005132598009818800c4cc008c0c00040122c8170c0b0dd500545902a205440a881506eb8c0acc0a0dd5002c566002603c00513233223300c009159800981218151baa001899912cc004c098c0b0dd5000c4c8c966002604a605c6ea800633001375c6064605e6ea80066eacc0c8c0cc00a53001488100a44100800a02091194c0040060070024004444b30010028800c4c8cc8a600200d303b0059919800800802912cc00400626607666ec0dd48021ba60034bd6f7b63044ca60026eb8c0e40066eacc0e8006607c0049112cc004cdc8004001c4cc0fccdd81ba9008374c00e00b15980099b8f0080038992cc0056600200314a314a081fa2005133040337606ea4024dd30008012078329800800c022006800888966002005100189919914c00401a608e00b32330010010052259800800c4cc11ccdd81ba9004375000697adef6c608994c004dd71822800cdd69823000cc1280092225980099b9000800389982599bb037520106ea001c0162b30013371e010007132598009821800c400a26609866ec0dd48049ba8001002412066e0001c00a26609666ec0dd48019ba800233006006001411c8238609000282310061bae3040001375a60820026086004820a26607e66ec0dd48019ba60023300600600140ec81d8607800281d10061bae30340013756606a002606e00481aa605c6ea803522222598009816800c4c96600260720031323232598009818181b9baa0018acc004c0b8c0dcdd5181d981e001456600266ebcc0ecc0e0dd500098161981d181d981c1baa00d3303a302c3303a980081a4cdc001aa41819e49020404497ae03303a302a3038375401a97ae08cc004dd5981d801cdd3004488cdc4800801203c8a5040d91640d91640d8607400260740026072606a6ea8c0e00062c81b0cc0b8dd6181b981c181c181a1baa01c23375e6070606a6ea8c0e0c0d4dd500098101981b9ba90064bd7044c9660026056005132332259800981e00144c8c8c966002606660746ea80062b30013031303a3754607c607e00513232332259800981c181f1baa002899912cc004c114006264b30013371e6eb8c1040056600266ebccc03800c01130103d87980008a4504444f574e008a4502555000410115980099b87375a6084002606001715980099baf304530423754010606c6608800866088606c6608800697ae033044375066e04dd698229823003005a5eb82330013756608a015374c660200246466002002602466e080312080897a2259800800c52f5bded8c1132330473376060880026e98c8cc004004dd59823001112cc004006297adef6c608991982519bb030470013750606c6eb4c120004cc00c00cc130008c1280050481980180198248011823800a08a9119b8900100240a114a0820229410404528208030440018b20843042303f3754004660526eacc108c10cc10c0280422c81e8c100004c100008c100004c0ecdd5008459039459039181e800981e800981e181c1baa303b0028b20723303037586072002466ebcc0e8c0dcdd5181d181b9baa001302233039375201097ae0375a6072606c6ea8050c0e4c0e4c0d4dd500ec566002605a005132332259800981e00144c8c8c966002606660746ea80062b30013031303a3754607c607e00513232332259800981c181f1baa002899912cc004c114006264b30013371e6eb8c1040056600266ebccc03800c01130103d87980008a45025550008a4504444f574e00410115980099b87375a6084002606001715980099baf304530423754010606c6608800866088606c6608800697ae033044375066e04dd698229823003005a5eb82330013756608a015374c025223371200200481422941040452820808a50410060880031641086084607e6ea8008cc0a4dd598211821982180500845903d182000098200011820000981d9baa0108b20728b2072303d001303d001303c3038375460760051640e4660606eb0c0e40048cdd7981d181b9baa303a303737540026044660726ea40212f5c06eb4c0e4c0d8dd500a181c981c981a9baa01d8acc004c08800a264b3001303a0018992cc004cdc3a40026eb4c0dc0062b30013371e6eb8c0d8005220107434f4e54524f4c00898181bad30293037375401914a081aa2c81a8c0e40062c81b8cc07cdd5981c181c981c981c981c981a9baa01d00689919912cc004c0f00062646644b30013033303a37540031323259800981b181e1baa002899191919912cc004c11800e266042608a00a264b3001303c0018992cc004c120006266046608e00201116411460866ea800a2b300130390018acc004c10cdd5001401e2c82222c820904118209baa0018b2086375a6086002608600460860026084002607a6ea800a2c81d84c966002605800315980099b870019800803c03a91104444f574e00407d159800cc0040126e98cc02c034c0300064466e24004009023456600266ebcc100c0f4dd50011820181e9baa0128acc004cdd79816981e9baa002302d303d375402513370e6eb4c0bcc0f4dd500119b80375a605e607a6ea8048006294103b452820768a5040ed14a081da294103b4c00401a01b489025550004078607c60766ea80062c81c8dd5981e000981e181e800981e181c1baa303b0018b20723756607260746074002660606eb0c0e40048cdd7981d181b9baa303a303737540026044660726ea40212f5c060726072606a6ea8075033206640cc446644b30013371000200514c0103d87b80008acc004cdc4001000c530103d87980008a6103d87a800040d881b0cdc11bad3039303637540046eb4c098c0d8dd500099b82375a6072606c6ea8004dd69813181b1baa00240c88b205a3031302e37546062002605a6ea8c0c0c0c4c0b4dd5181818169baa0018b2056302e302b37540026601e6eb0c0b8c0acdd5009919baf302f302c37540020071640a460580026058605a00260506ea80162c813102618129baa00322232598009817000c4c8c966002604a60566ea800626464b30013027302d375400313259800981418171baa0018992cc004c0a4c0bcdd5000c4c966002605460606ea8006264b30013370e6eb4c0d4c0c8dd500419b8200b483403e2604c66068606a60646ea8004cc0d0c088c0c8dd5000a5eb822c8180cc88c09ccc0d4dd419b82375a606c0046eb4c0d8004cc0d4dd419b82375a606c606e0046eb4c0d8c0dc0052f5c060626ea8c050dd6981a18189baa00330313754606860626ea80062c8178c8ca60026eb4c0d40066eb4c0d4c0d80066eb4c0d4c0c8dd5001a444b3001598009817001c4cdc4800a400114a0819a298103d87a80008acc004c090006260526606e60526606e6ea0cc04000c004cc0dcdd419808001000a5eb812f5c115980099b8800148002260526606e60526606e6ea0cc040008c08c004cc0dcdd4198080019811800a5eb812f5c114c010ad8799fd8799f0101ffff0040cc81990330c0c4dd50009809a40291640b8606460666066606660666066605e6ea800e2c8168c0c4c0b8dd5000c5902c180e98169baa001302f302c37540031640a86601e6eb0c074c0acdd5000918111bad302f302c3754002605a0031640ac64b300130233029375400313259800981218151baa0018991980f800912cc00400a2646600200200844b30010018a5eb822660653001371290004dc62400937009001cdc4a4011371890004dc62401137009003a444444466446605c4646b30013371e6eb8c0f80052210475d3c793008cc004888c8cc00cdd698210009bae3042304300130030019b89480426e3120109b804803e600e90082444446600a464660886ea0cde5250375c608a00266088608a608c00297ae05980098029b8d0018998219ba930020013304337526600860066e340040052f5c11640fc4646600e46608a6ea0cdc7000a40006608a6ea4cc008c0d0dc6800800a5eb808cc0208cc118dd419b8e00148000cc118dd499801981a9b8d0010014bd7011191919824981d998249ba800733049375000a66092609400297ae033049304a304b0014bd7018008012cc004c05400a2653001001a5eb82006800888966002608200312323304c374e002660986ea40092f5c065300100180252f5c080088896600200510018cc00400e60a00053304e304f002001400c826a246530010059982618268008024c0ec00e6eb8c134c138005005191919911919801194c0040066eb0c14800a6086660a260a400c660a2980103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a8000330514c103d87a80004bd702002222598008014400633001003982a8014c8c966002609800313230483305630570013305630483305630573054375400697ae030583058001305337540071598009824800c4c8c8c124cc15cc160008cc15cc160004cc15cc124cc15cc160c154dd500225eb80c164c164004c160004c14cdd5001c56600260960031323232304a33058305900333058305900233058305900133058304a3305830593056375400a97ae0305a305a00130590013058001305337540071598009820000c4c8c8c8c8c12ccc164c168010cc164c16800ccc164c168008cc164c168004cc164c12ccc164c168c15cdd500325eb80c16cc16c004c168004c164004c160004c14cdd5001c566002607e00313232323232304c3305a305b0053305a305b0043305a305b0033305a305b0023305a305b0013305a304c3305a305b3058375400e97ae0305c305c001305b001305a001305900130580013053375400715980099b87480280062646464646464609a660b660b800c660b660b800a660b660b8008660b660b8006660b660b8004660b660b8002660b6609a660b660b860b26ea80212f5c060ba60ba00260b800260b600260b400260b200260b000260a66ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c138cc170c17401ccc170c174018cc170c174014cc170c174010cc170c17400ccc170c174008cc170c174004cc170c138cc170c174c168dd5004a5eb80c178c178004c174004c170004c16c004c168004c164004c160004c14cdd5001c56600266e1d200e0018991919191919191918279982e982f0041982e982f0039982e982f0031982e982f0029982e982f0021982e982f0019982e982f0011982e982f0009982e98279982e982f182d9baa00a4bd70182f982f800982f000982e800982e000982d800982d000982c800982c00098299baa0038acc004cdc3a4020003132323232323232323230503305e305f0093305e305f0083305e305f0073305e305f0063305e305f0053305e305f0043305e305f0033305e305f0023305e305f0013305e30503305e305f305c375401697ae030603060001305f001305e001305d001305c001305b001305a001305900130580013053375400715980099b874804800626464646464646464646460a2660be60c0014660be60c0012660be60c0010660be60c000e660be60c000c660be60c000a660be60c0008660be60c0006660be60c0004660be60c0002660be60a2660be60c060ba6ea80312f5c060c260c200260c000260be00260bc00260ba00260b800260b600260b400260b200260b000260a66ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c148cc180c18402ccc180c184028cc180c184024cc180c184020cc180c18401ccc180c184018cc180c184014cc180c184010cc180c18400ccc180c184008cc180c184004cc180c148cc180c184c178dd5006a5eb80c188c188004c184004c180004c17c004c178004c174004c170004c16c004c168004c164004c160004c14cdd5001c56600266e1d201600189919191919191919191919191829998309831006198309831005998309831005198309831004998309831004198309831003998309831003198309831002998309831002198309831001998309831001198309831000998309829998309831182f9baa00e4bd7018319831800983100098308009830000982f800982f000982e800982e000982d800982d000982c800982c00098299baa003899191919191919191919191918299983098310061983098310059983098310051983098310049983098310041983098310039983098310031983098310029983098310021983098310019983098310011983098310009983098311831800998309829998309831182f9baa00e4bd7025eb80c188004c184004c180004c17c004c178004c174004c170004c16c004c168004c164004c160004c14cdd5001a0a24144828905120a24144828905120a24144828905118289baa0013054002400c8290dd718289829000991acc004c07800e2653001001a5eb820088008889660026094003123233055374e002660aa6ea40092f5c065300100180252f5c080088896600200510018cc00400e60b2005330573058002001400c82b2246530010059982a982b0008024c11000e6eb8c158c15c0050051802800a09e8b2098375c60a260a4008530012232598009800a40211598009800a4001148002266e39220108010204081020408000002413d1598009800a408113370490400219801801980980144cdc124101010100406600600666e00009203f413c8278dc4000c888c8cc150c00cdd6982a8009982a182a982b000a5eb80c00c006660a06ea0cdc7000a4000660a06ea4cc034c0fcdc6800800a5eb81222323298009198029191982c1ba833794940dd7182c8009982c182c982d000a5eb816600260326e340062660ae6ea4c058004cc15cdd49980c180b9b8d0010014bd704590531191801acc004c13c006298103d87a8000898251982c1ba80014bd7020a830030019bad3056003911191acc006600260a06eb4c16800694294505544cc02000c8c014c130cc168dd4000a5eb8226016600898103d87a800041546eb8c168c16c004cc160dd419b8e00148000cc160dd49980a98239b8d0010014bd7024446b3001304f00289801918259982c800a5eb822b3001304c00289801918211982c800a5eb822b3001304e00289801919ba548010cc1640052f5c1159800982180144cc01c8c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001304e371a00313305937526040002660b26ea4cc098c094dc6800800a5eb822c82a88cdd2a400c660b26ea00052f5c1159800982100144cc01c8c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001304e371a00313305937526040002660b26ea4cc098c094dc6800800a5eb822c82a88cdd2a4010660b26ea16600266e20005208080048800c4cdc080098032404082a92f5c115980099b874802800a26006466e95200a330590014bd70456600266e1d200c002899800919ba548030cc1640052f5c0464660b46ea0c018dd6982d8009982d182d982e000a5eb80c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2b30013370e900700144cc0048cdd2a401c660b200297ae02323305a375066f29281bae305b0013305a305b305c0014bd702cc004c06cdc6800c4cc164dd4980c0009982c9ba93301a3019371a00200297ae08b20aa8acc004cdc3a402000513300123374a90081982c800a5eb808c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2b30013370e9009001448c8c8cc16ccdd2a4024660b660b800297ae03305b305c305d0014bd701800801198041191982d9ba833794940dd7182e0009982d982e182e800a5eb8166002609e6e340062660b46ea4c084004cc168dd49981398131b8d0010014bd7045905612cc004c1440062980103d87980008acc004c138006298103d87a80008acc004c140006298103d87b80008acc004c114006298103d87c80008acc004c110006298103d87d80008b20ac415882b105620ac8acc004cdc3a40280051300323374a900a1982c800a5eb822b30013370e900b00144c00c8cdd2a402c660b200297ae08acc004cdc3a403000513300123374a900c1982c800a5eb808c8cc168dd419bca4a06eb8c16c004cc168c16cc1700052f5c0b3001301b371a00313305937526030002660b26ea4cc068c064dc6800800a5eb822c82aa2c82a105420a8415082a105420a8415082a105420a8415082a0dd7182c982d003096600266e2000520808080808080808080028800c4cdc0800980124100028288c00c00c6eb4c13800488cc13c008cc13cdd4800a5eb80c8cc134dd419b8e00148000cc134dd499805181e1b8d0010014bd701bae304d304e001323304c375066f29281bae304d0013304c304d304e0014bd702cc004c058dc6800c4cc12cdd49808800998259ba9330143013371a00200297ae08b208e411916410c6e3120024590391bae303e303f0015980098039b8d00189981e1ba930020013303c37526600a60086e340040052f5c11640e06eb8c0acc0e4dd5198171191acc004cdc79bae303e00148904b9011a820089191919191919199119823181c198231823803998231ba90013304630470024bd70198231823982400125eb80d660026024003125980099b89002371a00313304537526601e0040026608a6ea66002005337026e3400400a002b8c25eb822c820a2c8200dd7182298230011bae3045004375a608800264660866ea0cde5250375c6088002660866088608a00297ae059800981b9b8d0018998211ba930090013304237526601e601c6e340040052f5c11640f86eb8c108c10c004d6600294624b30013371290201b8d0018998209ba93300b48100004cc104dd4cc005204099b80371a002901fc0057184bd7045903d45903c1bae30413042001300100259800a51892cc004cdc4a4100026e3400626607e6ea4cc0252080010013303f37533001482000666e00dc6800a40ff0015c612f5c11640ed1640e91640e46eb8c0f8c0fc00566002600e6e340062660786ea4c008004cc0f0dd49980298021b8d0010014bd704590381bae303c00a300348010c00d200819801001181a000a062899180118198019bae303100240bc6eb0c0b8c0acdd5000c5902919199119801001000912cc004006298103d87a80008992cc004cdd78021816800c4c088cc0c0c0b80052f5c1133003003303200240b060600028170dd5981718179817981798179817981798179817981798159baa0033374a900219816180a99816181698171817181718151baa302d302a375400297ae04bd7045902819198008009bac301a302a375400444b30010018a6103d87a80008992cc006600266ebc00530103d87a8000a50a5140a91001899801801981800120543259800cc004dd5980e18161baa301c302c3754003374c6605c66ec0dd48031ba63302e3376098010b4a50797468205374617465004c010101004bd6f7b63025eb7bdb182449450124566002604460566ea8c0bcc0b0dd5181798161baa301c302c375400313259800981298161baa0018992cc004c09cc0b4dd5000c4c8c8c8c8cc89660026070007132598009817181a1baa0018991919194c004dd6981e000cdd7181e0024dd6981e001cdd7181e00124444b300130410058998181bab304000e225980080144cc0c8030896600200513035330430144bd7044c8c8cc07cc1080084c00cc11c010dd7182100098220012084899191980e98208010980198228021bae303f001304200241011640f8303c001303b001303a001303537540031640cc606e00d1640d46eb8c0d4004dd5981a801181a800981a000981980098171baa0018b20583030302d37540031640ac603c60586ea8c070c0b0dd5000c5902a4530103d87a800040a8605c0028160452689b2b200601", + "hash": "cdd7308205adaf89370d6f5fe5225b10876165977f2ce4836b67e645" + }, + { + "title": "order.order.mint", + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/hermes_types~1OrderMintRedeemer" + } + }, + "parameters": [ + { + "title": "market_script_hash", + "schema": { + "$ref": "#/definitions/aiken~1crypto~1ScriptHash" + } + } + ], + "compiledCode": "5912ab010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888889660033001300437540152232330010010032259800800c52f5c11332259800980280144cc030008cc0100100062660080080028040c02c004c0300050094dc3a4001374a9000488c8cc00400400c896600200314a115980099b8f375c601600200714a3133002002300c0014018804a460106012003370e9001488c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a20030064029133005005301000440286eb8c024004dd598050009806000a01414bd6f7b630496600200314a314a080324444646600200200a44b300100189980619bb0375200a6ea00112f5bded8c113298009bae300a0019bad300b00198078012444b300133720012007133010337606ea4024dd4004002c56600266e3c02400e33001009804400a46602266ec0dd48051ba80010028800a00e89980819bb037520066ea0008cc01801800500c20181806800a01691111919800800802912cc00400626601866ec0dd48029ba60044bd6f7b63044ca60026eb8c0280066eacc02c006601e0049112cc004cdc8004801c4cc040cdd81ba9009374c01000b15980099b8f0090038cc00402601100291980899bb037520146e9800400a2002803a26602066ec0dd48019ba60023300600600140308060601a002805a6e9520029b874801122222222222229800980a806cc050036444b30010028a508994c004c9660026020602a6ea800626eb4c058c064dd5980c980b1baa0018a400080a0c0600066ebcc060c0640066eac00d22259800800c566002600400d13300500348002294101644c96600266ebcc0600053010140008acc004cc018010dd6980c980e1bab3019001898019ba6301d0028a50405d1598009980300224001130030078a50405c80b8c06c0050190ca6002003004911980c8011980c9ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c05c0066eacc06000660380069112cc004cdc8a441000038acc004cdc7a44100003899802980a1980e9ba60024bd70000c4cc015300103d87a8000006406519800803c006446600e0046603e66ec0dd48029ba6004001401c80c8603400480c2294229422941019488c8cc00400400c896600200314c0103d87a80008992cc004c0100062601e6603000297ae0899801801980d001202830180014059222598009807000c52f5bded8c113232330010014bd6f7b630112cc00400626603266ec0dd48031ba60034bd6f7b63044ca60026eb8c05c0066eacc06000660380049112cc004cdc8005001c4cc074cdd81ba900a374c00e00b15980099b8f00a00389980e99bb037520146e9801c00626603a66ec0dd48019ba600233006006001406480c8603400280c0c8cc0040052f5bded8c044b300100189980c19bb037520086ea000d2f5bded8c113298009bae30160019bad3017001980d8012444b30013372001000713301c337606ea4020dd4003802c56600266e3c02000e26603866ec0dd48041ba800700189980e19bb037520066ea0008cc0180180050182030180c800a02e40492232598009807000c56600260286ea800e0051640551598009805000c56600260286ea800e0051640551640488090c048dd5001488c966002601c003159800980a1baa00380145901545660026014003159800980a1baa0038014590154590122024301237540052259800980698091baa0028991919912cc004c06c00e00b1640606eb4c060004dd6980c001180c00098099baa0028b2022891111192cc004c04400600513003001405466e0001000d22222222233229800980d9baa002911112cc004c06cc080dd500244c018cdc199b82002375a604860426ea800cdd6980c18109baa0038acc004c06cc080dd5002c6600200348810255500080120188cc004006910104444f574e008012018407c80fa603e0169112cc004c06400e2646644b3001301c0018992cc004c09c006264b3001301e30233754003132323322598009816001c0222c8148dd698148009bae3029002302900130243754003164088604c00316409060446ea80122b300130180018acc004c088dd5002400a2c811a2c81010200acc004c068c07cdd500144cc88c8ca60026eacc09c0066eb0c09cc0a0c0a0c0a0c0a0006604e60486ea801a60080093301f3758604e004466ebcc0a0c094dd5181418129baa001301633027375200c97ae048888966002605a003159800981198141baa3301537586058010466ebcc0b4c0a8dd500080244c8c8cc8966002603a60586ea800a2b30013023302c37546060606200713259800981418169baa001899191919194c004dd6981b000cc0d8012606c007375c606c00491112cc004c0ec01626466044002266042008266040006264b3001303d001899192cc004c0c4dd6981d80145660026606602c00b159800cc00403e6e98c966002942200319800800c0766464004602c0026607c66ec0dd480126010101004bd6f7b630488888c966002606c00300289801800a0803298008024022900148888a600200b003802400a00280310352814205c40e93001004803c01a011038407922337120020048142266e3c004dca1bb30158a5040e514a081ca2c81c8dd7181c800981e000c5903a1981680a00c981d004c590380c0d8004c0d4004c0d0004c0cc004c0b8dd5000c5902c181818169baa0028b20568b2056302e0013756605c004605c002605a60526ea8c0b00062c813a2c8150604e604e002604c604c00244b30010018a4d13259800800c5268992cc004cdc81bae30233027003375c60460031330040043302600130280028b204430260014090604c0028118c080dd500744ca60020033301637566048604a604a604a604a60426ea803c00a9450011112cc00400a200313298008024c0a000e64b3001003899b88375a604a004900045282046375c60460028020c098009024203c301f37540046eb8c088c07cdd5002c566002602a0071323322332259800980f000c56600260486ea801a005164095159800980d000c56600260486ea801a005164095159800980a000c4c8c96600260540050048b204e375a605000260486ea801a2c81110222044159800980e18109baa001899912cc004c078c08cdd5000c4c8c9660026038604a6ea800633001375c6052604c6ea80066eacc0a4c0a800a44653001001801c0090011112cc00400a200313298008024c0c000f30010029bae302b0019bab302c00191111192cc004c0980060051300300140c06465300100180340150011112cc00400a200313298008024c0e800f30010029bae30350019bad3036001802a0524010607000481b1406101e2008302e00240b1232330010010022259800800c52f5bded8c11323302c3376060520026e98c8cc004004dd59815801112cc004006297adef6c608991981799bb0302c001375066e052000375a605a002660060066062004605e0028168cc00c00cc0b8008c0b000502a488c8cc00400400c896600200314a115980098019816800c528c4cc008008c0b8005028205691119199119801001000912cc00400600713233225980099b910070028acc004cdc78038014400600c816a26600a00a60660088168dd718160009bad302d001302f00140b46603e008006290004c094dd500448c0a8c0acc0acc0ac0052222222259800981400144c9660026604e6eb0c0c8c0ccc0ccc0ccc0cc004dd7180118179baa00d8cc004dd59819000cdd3198121803004004c88cdc3801000a0388a5040b46064606460646064605c6ea80722b300130240028cc00489660026054605e6ea800a264646464653001375a60700033038004981c001cdd7181c00124444b3001303d005899811981e00489981100189981080100545903a0c0e0004c0dc004c0d8004c0d4004c0c0dd500145902e48c0c8c0ccc0cc006460646066606660666066003302e375403891111991194c004c0e40066eacc0e0c0e4c0e400e6eb0c0e000d22259800981e001c4c8cc8966002605660746ea80062646644b3001302e303d37540031332233012001133012002159800cc004cdd7982198201baa0013043304037540054a14a281f22b30013375e606e60806ea800530103d87980008acc004cdd7981b98201baa0024c0103d87980008acc004cdc399b80337046eb4c10cc100dd5180898201baa001375a606e60806ea8c044c100dd500119b82375a608660806ea8c044c100dd50011bad303730403754602260806ea8004cdc11bad303730403754602260806ea8004dd6981b98201baa30113040375400519800acc004cdc49bad3010304037540046eb4c040c100dd5000c4cc108004cc108dd300399821001198211ba60044bd7044cc108008cc108dd300219821000998211ba60074bd70207cacc004c0e8c0fcdd5182198201baa0018a45025550008a4504444f574e0040f959800981d181f9baa3043304037540051489025550008a4504444f574e0040f93302c00d23375e608860826ea8c110c104dd5181c18209baa001303233043375207c97ae048888c8cc88c9660026084608e6ea801626464b300159800801c528c4cc88cc0880548c8c96600266ebcc148c13cdd518290011820198289ba90294bd7044c9660026080609e6ea80062b300198009bab30530029ba60059119b8900100240f513375e60a660a06ea800401a294104e45904e18291829800c528209a3052001304d3754002646464608c6609e60a00066609e60a00046609e60a00026609e60a060a20026609e6ea0cdc09bad301d304d375400e01097ae03050001304f001304a3754008660446eacc134018c084c0bccdc198011bad304d304a3754603660946ea8010dd6982098251baa301b304a375400882422b30013370e6530010019982000a812d20004004444b30010028800c4ca600200930520039919b80003375a609e0046eb8c1340050041828001209c59800801c520038a400282422b3001330200132325980099baf304f304c3754609e002608a6609c603e60986ea80352f5c1198009bab304f30500019ba69800824c02e00e81ba4466e2400400903945282094304b3754003159800998100099192cc004cdd7982798261baa304f00130453304e301f304c375401c97ae08cc004dd598279828000cdd34c00412601500740dd223371200200481ca294104a18259baa0018acc004cdc3cc00405208f488102555000407c00b15980099b87980080a411e91104444f574e00407c00b1330200132325980099baf304f304c3754609e002607a6609c6ea41252f5c1198009bab304f30500019ba60039119b8900100240e514a08250c12cdd5000c52820908a50412114a082422941048452820908a504120660426eacc100c124dd5182018249baa304c3049375400c605c66e00cdc198009bad304c30493754603460926ea8028dd6982018249baa301a3049375401466e0cc004dd6982618249baa301a304937540166eb4c100c124dd5180d18249baa00b370400716411866e1cdd6980b98239baa001002375a602a608a6ea8c120c124004c120014c1200111640f91640f91640f91640f86082607c6ea8004c104c0f8dd500245903c1bab303f001303f3040001303f303b3754607c607e60766ea8c0f801a2c81c8dd5981e000981e181e800981e181c1baa303b303c3038375460760091640e43302f00123375e6070606a6ea8c0e0c0d4dd51816181a9baa001302633037375201e97ae0303630360013758606a0028994c004dd61819000ccc0900200266eb4c0c8c0bcdd5008a444b300130360028992cc004c0a4dd69819800c4c8c8ca600260740033039001981c801cc0e4009222298009bae303d0049bad303d303e004acc004c0d0c0e4dd5000c566002606860726ea800a33001037a4502555000804a04a8cc0040de910104444f574e00804a04a40e11301f3370666e08024dd6981e981d1baa003375a606260746ea800d0382444b30013301300e2325980099baf3042303f375460840026070660826ea40152f5c1198009bab304230430019ba60039119b8900100240b114a081e8c0f8dd5000c566002b30013370e00401913370f3001375660806082608201f0179bae303c00b40489000c52820768a51899911980a808119192cc004cdd7982298211baa3045002303333044375203897ae08992cc004c0ccc108dd5000c56600330013756608c005374c00b22337120020048182266ebcc118c10cdd5000803452820828b2082304530460018a504100608a00260806ea8004c8c8c8c0e4cc108c10c00ccc108c10c008cc108c10c004cc108c10cc110004cc108dd419b8100500f4bd7018218009821000981e9baa01b3301501630149800802c01200d00c81d204040ed14a081d830390013038001303337540231640c4606a0051640cc30323032302e3754038816102c22c8120c0a0c094dd5181400098121baa3027302830243754604e60486ea80062c8110c094c088dd5000998071bac302530223754020466ebcc098c08cdd5000801c5902018109baa004302300130233024001301f375400b16407480e8603a603c01253001488100a44100800a00c229344d95900201", + "hash": "1d9670358959872ba038d87e894961616d1ec86c29b06eae77039134" + }, + { + "title": "order.order.spend", + "datum": { + "title": "op_datum", + "schema": { + "$ref": "#/definitions/hermes_types~1OrderDatum" + } + }, + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/hermes_types~1OrderRedeemer" + } + }, + "parameters": [ + { + "title": "market_script_hash", + "schema": { + "$ref": "#/definitions/aiken~1crypto~1ScriptHash" + } + } + ], + "compiledCode": "5912ab010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888889660033001300437540152232330010010032259800800c52f5c11332259800980280144cc030008cc0100100062660080080028040c02c004c0300050094dc3a4001374a9000488c8cc00400400c896600200314a115980099b8f375c601600200714a3133002002300c0014018804a460106012003370e9001488c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a20030064029133005005301000440286eb8c024004dd598050009806000a01414bd6f7b630496600200314a314a080324444646600200200a44b300100189980619bb0375200a6ea00112f5bded8c113298009bae300a0019bad300b00198078012444b300133720012007133010337606ea4024dd4004002c56600266e3c02400e33001009804400a46602266ec0dd48051ba80010028800a00e89980819bb037520066ea0008cc01801800500c20181806800a01691111919800800802912cc00400626601866ec0dd48029ba60044bd6f7b63044ca60026eb8c0280066eacc02c006601e0049112cc004cdc8004801c4cc040cdd81ba9009374c01000b15980099b8f0090038cc00402601100291980899bb037520146e9800400a2002803a26602066ec0dd48019ba60023300600600140308060601a002805a6e9520029b874801122222222222229800980a806cc050036444b30010028a508994c004c9660026020602a6ea800626eb4c058c064dd5980c980b1baa0018a400080a0c0600066ebcc060c0640066eac00d22259800800c566002600400d13300500348002294101644c96600266ebcc0600053010140008acc004cc018010dd6980c980e1bab3019001898019ba6301d0028a50405d1598009980300224001130030078a50405c80b8c06c0050190ca6002003004911980c8011980c9ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c05c0066eacc06000660380069112cc004cdc8a441000038acc004cdc7a44100003899802980a1980e9ba60024bd70000c4cc015300103d87a8000006406519800803c006446600e0046603e66ec0dd48029ba6004001401c80c8603400480c2294229422941019488c8cc00400400c896600200314c0103d87a80008992cc004c0100062601e6603000297ae0899801801980d001202830180014059222598009807000c52f5bded8c113232330010014bd6f7b630112cc00400626603266ec0dd48031ba60034bd6f7b63044ca60026eb8c05c0066eacc06000660380049112cc004cdc8005001c4cc074cdd81ba900a374c00e00b15980099b8f00a00389980e99bb037520146e9801c00626603a66ec0dd48019ba600233006006001406480c8603400280c0c8cc0040052f5bded8c044b300100189980c19bb037520086ea000d2f5bded8c113298009bae30160019bad3017001980d8012444b30013372001000713301c337606ea4020dd4003802c56600266e3c02000e26603866ec0dd48041ba800700189980e19bb037520066ea0008cc0180180050182030180c800a02e40492232598009807000c56600260286ea800e0051640551598009805000c56600260286ea800e0051640551640488090c048dd5001488c966002601c003159800980a1baa00380145901545660026014003159800980a1baa0038014590154590122024301237540052259800980698091baa0028991919912cc004c06c00e00b1640606eb4c060004dd6980c001180c00098099baa0028b2022891111192cc004c04400600513003001405466e0001000d22222222233229800980d9baa002911112cc004c06cc080dd500244c018cdc199b82002375a604860426ea800cdd6980c18109baa0038acc004c06cc080dd5002c6600200348810255500080120188cc004006910104444f574e008012018407c80fa603e0169112cc004c06400e2646644b3001301c0018992cc004c09c006264b3001301e30233754003132323322598009816001c0222c8148dd698148009bae3029002302900130243754003164088604c00316409060446ea80122b300130180018acc004c088dd5002400a2c811a2c81010200acc004c068c07cdd500144cc88c8ca60026eacc09c0066eb0c09cc0a0c0a0c0a0c0a0006604e60486ea801a60080093301f3758604e004466ebcc0a0c094dd5181418129baa001301633027375200c97ae048888966002605a003159800981198141baa3301537586058010466ebcc0b4c0a8dd500080244c8c8cc8966002603a60586ea800a2b30013023302c37546060606200713259800981418169baa001899191919194c004dd6981b000cc0d8012606c007375c606c00491112cc004c0ec01626466044002266042008266040006264b3001303d001899192cc004c0c4dd6981d80145660026606602c00b159800cc00403e6e98c966002942200319800800c0766464004602c0026607c66ec0dd480126010101004bd6f7b630488888c966002606c00300289801800a0803298008024022900148888a600200b003802400a00280310352814205c40e93001004803c01a011038407922337120020048142266e3c004dca1bb30158a5040e514a081ca2c81c8dd7181c800981e000c5903a1981680a00c981d004c590380c0d8004c0d4004c0d0004c0cc004c0b8dd5000c5902c181818169baa0028b20568b2056302e0013756605c004605c002605a60526ea8c0b00062c813a2c8150604e604e002604c604c00244b30010018a4d13259800800c5268992cc004cdc81bae30233027003375c60460031330040043302600130280028b204430260014090604c0028118c080dd500744ca60020033301637566048604a604a604a604a60426ea803c00a9450011112cc00400a200313298008024c0a000e64b3001003899b88375a604a004900045282046375c60460028020c098009024203c301f37540046eb8c088c07cdd5002c566002602a0071323322332259800980f000c56600260486ea801a005164095159800980d000c56600260486ea801a005164095159800980a000c4c8c96600260540050048b204e375a605000260486ea801a2c81110222044159800980e18109baa001899912cc004c078c08cdd5000c4c8c9660026038604a6ea800633001375c6052604c6ea80066eacc0a4c0a800a44653001001801c0090011112cc00400a200313298008024c0c000f30010029bae302b0019bab302c00191111192cc004c0980060051300300140c06465300100180340150011112cc00400a200313298008024c0e800f30010029bae30350019bad3036001802a0524010607000481b1406101e2008302e00240b1232330010010022259800800c52f5bded8c11323302c3376060520026e98c8cc004004dd59815801112cc004006297adef6c608991981799bb0302c001375066e052000375a605a002660060066062004605e0028168cc00c00cc0b8008c0b000502a488c8cc00400400c896600200314a115980098019816800c528c4cc008008c0b8005028205691119199119801001000912cc00400600713233225980099b910070028acc004cdc78038014400600c816a26600a00a60660088168dd718160009bad302d001302f00140b46603e008006290004c094dd500448c0a8c0acc0acc0ac0052222222259800981400144c9660026604e6eb0c0c8c0ccc0ccc0ccc0cc004dd7180118179baa00d8cc004dd59819000cdd3198121803004004c88cdc3801000a0388a5040b46064606460646064605c6ea80722b300130240028cc00489660026054605e6ea800a264646464653001375a60700033038004981c001cdd7181c00124444b3001303d005899811981e00489981100189981080100545903a0c0e0004c0dc004c0d8004c0d4004c0c0dd500145902e48c0c8c0ccc0cc006460646066606660666066003302e375403891111991194c004c0e40066eacc0e0c0e4c0e400e6eb0c0e000d22259800981e001c4c8cc8966002605660746ea80062646644b3001302e303d37540031332233012001133012002159800cc004cdd7982198201baa0013043304037540054a14a281f22b30013375e606e60806ea800530103d87980008acc004cdd7981b98201baa0024c0103d87980008acc004cdc399b80337046eb4c10cc100dd5180898201baa001375a606e60806ea8c044c100dd500119b82375a608660806ea8c044c100dd50011bad303730403754602260806ea8004cdc11bad303730403754602260806ea8004dd6981b98201baa30113040375400519800acc004cdc49bad3010304037540046eb4c040c100dd5000c4cc108004cc108dd300399821001198211ba60044bd7044cc108008cc108dd300219821000998211ba60074bd70207cacc004c0e8c0fcdd5182198201baa0018a45025550008a4504444f574e0040f959800981d181f9baa3043304037540051489025550008a4504444f574e0040f93302c00d23375e608860826ea8c110c104dd5181c18209baa001303233043375207c97ae048888c8cc88c9660026084608e6ea801626464b300159800801c528c4cc88cc0880548c8c96600266ebcc148c13cdd518290011820198289ba90294bd7044c9660026080609e6ea80062b300198009bab30530029ba60059119b8900100240f513375e60a660a06ea800401a294104e45904e18291829800c528209a3052001304d3754002646464608c6609e60a00066609e60a00046609e60a00026609e60a060a20026609e6ea0cdc09bad301d304d375400e01097ae03050001304f001304a3754008660446eacc134018c084c0bccdc198011bad304d304a3754603660946ea8010dd6982098251baa301b304a375400882422b30013370e6530010019982000a812d20004004444b30010028800c4ca600200930520039919b80003375a609e0046eb8c1340050041828001209c59800801c520038a400282422b3001330200132325980099baf304f304c3754609e002608a6609c603e60986ea80352f5c1198009bab304f30500019ba69800824c02e00e81ba4466e2400400903945282094304b3754003159800998100099192cc004cdd7982798261baa304f00130453304e301f304c375401c97ae08cc004dd598279828000cdd34c00412601500740dd223371200200481ca294104a18259baa0018acc004cdc3cc00405208f488102555000407c00b15980099b87980080a411e91104444f574e00407c00b1330200132325980099baf304f304c3754609e002607a6609c6ea41252f5c1198009bab304f30500019ba60039119b8900100240e514a08250c12cdd5000c52820908a50412114a082422941048452820908a504120660426eacc100c124dd5182018249baa304c3049375400c605c66e00cdc198009bad304c30493754603460926ea8028dd6982018249baa301a3049375401466e0cc004dd6982618249baa301a304937540166eb4c100c124dd5180d18249baa00b370400716411866e1cdd6980b98239baa001002375a602a608a6ea8c120c124004c120014c1200111640f91640f91640f91640f86082607c6ea8004c104c0f8dd500245903c1bab303f001303f3040001303f303b3754607c607e60766ea8c0f801a2c81c8dd5981e000981e181e800981e181c1baa303b303c3038375460760091640e43302f00123375e6070606a6ea8c0e0c0d4dd51816181a9baa001302633037375201e97ae0303630360013758606a0028994c004dd61819000ccc0900200266eb4c0c8c0bcdd5008a444b300130360028992cc004c0a4dd69819800c4c8c8ca600260740033039001981c801cc0e4009222298009bae303d0049bad303d303e004acc004c0d0c0e4dd5000c566002606860726ea800a33001037a4502555000804a04a8cc0040de910104444f574e00804a04a40e11301f3370666e08024dd6981e981d1baa003375a606260746ea800d0382444b30013301300e2325980099baf3042303f375460840026070660826ea40152f5c1198009bab304230430019ba60039119b8900100240b114a081e8c0f8dd5000c566002b30013370e00401913370f3001375660806082608201f0179bae303c00b40489000c52820768a51899911980a808119192cc004cdd7982298211baa3045002303333044375203897ae08992cc004c0ccc108dd5000c56600330013756608c005374c00b22337120020048182266ebcc118c10cdd5000803452820828b2082304530460018a504100608a00260806ea8004c8c8c8c0e4cc108c10c00ccc108c10c008cc108c10c004cc108c10cc110004cc108dd419b8100500f4bd7018218009821000981e9baa01b3301501630149800802c01200d00c81d204040ed14a081d830390013038001303337540231640c4606a0051640cc30323032302e3754038816102c22c8120c0a0c094dd5181400098121baa3027302830243754604e60486ea80062c8110c094c088dd5000998071bac302530223754020466ebcc098c08cdd5000801c5902018109baa004302300130233024001301f375400b16407480e8603a603c01253001488100a44100800a00c229344d95900201", + "hash": "1d9670358959872ba038d87e894961616d1ec86c29b06eae77039134" + }, + { + "title": "order.order.else", + "redeemer": { + "schema": {} + }, + "parameters": [ + { + "title": "market_script_hash", + "schema": { + "$ref": "#/definitions/aiken~1crypto~1ScriptHash" + } + } + ], + "compiledCode": "5912ab010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888889660033001300437540152232330010010032259800800c52f5c11332259800980280144cc030008cc0100100062660080080028040c02c004c0300050094dc3a4001374a9000488c8cc00400400c896600200314a115980099b8f375c601600200714a3133002002300c0014018804a460106012003370e9001488c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a20030064029133005005301000440286eb8c024004dd598050009806000a01414bd6f7b630496600200314a314a080324444646600200200a44b300100189980619bb0375200a6ea00112f5bded8c113298009bae300a0019bad300b00198078012444b300133720012007133010337606ea4024dd4004002c56600266e3c02400e33001009804400a46602266ec0dd48051ba80010028800a00e89980819bb037520066ea0008cc01801800500c20181806800a01691111919800800802912cc00400626601866ec0dd48029ba60044bd6f7b63044ca60026eb8c0280066eacc02c006601e0049112cc004cdc8004801c4cc040cdd81ba9009374c01000b15980099b8f0090038cc00402601100291980899bb037520146e9800400a2002803a26602066ec0dd48019ba60023300600600140308060601a002805a6e9520029b874801122222222222229800980a806cc050036444b30010028a508994c004c9660026020602a6ea800626eb4c058c064dd5980c980b1baa0018a400080a0c0600066ebcc060c0640066eac00d22259800800c566002600400d13300500348002294101644c96600266ebcc0600053010140008acc004cc018010dd6980c980e1bab3019001898019ba6301d0028a50405d1598009980300224001130030078a50405c80b8c06c0050190ca6002003004911980c8011980c9ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c05c0066eacc06000660380069112cc004cdc8a441000038acc004cdc7a44100003899802980a1980e9ba60024bd70000c4cc015300103d87a8000006406519800803c006446600e0046603e66ec0dd48029ba6004001401c80c8603400480c2294229422941019488c8cc00400400c896600200314c0103d87a80008992cc004c0100062601e6603000297ae0899801801980d001202830180014059222598009807000c52f5bded8c113232330010014bd6f7b630112cc00400626603266ec0dd48031ba60034bd6f7b63044ca60026eb8c05c0066eacc06000660380049112cc004cdc8005001c4cc074cdd81ba900a374c00e00b15980099b8f00a00389980e99bb037520146e9801c00626603a66ec0dd48019ba600233006006001406480c8603400280c0c8cc0040052f5bded8c044b300100189980c19bb037520086ea000d2f5bded8c113298009bae30160019bad3017001980d8012444b30013372001000713301c337606ea4020dd4003802c56600266e3c02000e26603866ec0dd48041ba800700189980e19bb037520066ea0008cc0180180050182030180c800a02e40492232598009807000c56600260286ea800e0051640551598009805000c56600260286ea800e0051640551640488090c048dd5001488c966002601c003159800980a1baa00380145901545660026014003159800980a1baa0038014590154590122024301237540052259800980698091baa0028991919912cc004c06c00e00b1640606eb4c060004dd6980c001180c00098099baa0028b2022891111192cc004c04400600513003001405466e0001000d22222222233229800980d9baa002911112cc004c06cc080dd500244c018cdc199b82002375a604860426ea800cdd6980c18109baa0038acc004c06cc080dd5002c6600200348810255500080120188cc004006910104444f574e008012018407c80fa603e0169112cc004c06400e2646644b3001301c0018992cc004c09c006264b3001301e30233754003132323322598009816001c0222c8148dd698148009bae3029002302900130243754003164088604c00316409060446ea80122b300130180018acc004c088dd5002400a2c811a2c81010200acc004c068c07cdd500144cc88c8ca60026eacc09c0066eb0c09cc0a0c0a0c0a0c0a0006604e60486ea801a60080093301f3758604e004466ebcc0a0c094dd5181418129baa001301633027375200c97ae048888966002605a003159800981198141baa3301537586058010466ebcc0b4c0a8dd500080244c8c8cc8966002603a60586ea800a2b30013023302c37546060606200713259800981418169baa001899191919194c004dd6981b000cc0d8012606c007375c606c00491112cc004c0ec01626466044002266042008266040006264b3001303d001899192cc004c0c4dd6981d80145660026606602c00b159800cc00403e6e98c966002942200319800800c0766464004602c0026607c66ec0dd480126010101004bd6f7b630488888c966002606c00300289801800a0803298008024022900148888a600200b003802400a00280310352814205c40e93001004803c01a011038407922337120020048142266e3c004dca1bb30158a5040e514a081ca2c81c8dd7181c800981e000c5903a1981680a00c981d004c590380c0d8004c0d4004c0d0004c0cc004c0b8dd5000c5902c181818169baa0028b20568b2056302e0013756605c004605c002605a60526ea8c0b00062c813a2c8150604e604e002604c604c00244b30010018a4d13259800800c5268992cc004cdc81bae30233027003375c60460031330040043302600130280028b204430260014090604c0028118c080dd500744ca60020033301637566048604a604a604a604a60426ea803c00a9450011112cc00400a200313298008024c0a000e64b3001003899b88375a604a004900045282046375c60460028020c098009024203c301f37540046eb8c088c07cdd5002c566002602a0071323322332259800980f000c56600260486ea801a005164095159800980d000c56600260486ea801a005164095159800980a000c4c8c96600260540050048b204e375a605000260486ea801a2c81110222044159800980e18109baa001899912cc004c078c08cdd5000c4c8c9660026038604a6ea800633001375c6052604c6ea80066eacc0a4c0a800a44653001001801c0090011112cc00400a200313298008024c0c000f30010029bae302b0019bab302c00191111192cc004c0980060051300300140c06465300100180340150011112cc00400a200313298008024c0e800f30010029bae30350019bad3036001802a0524010607000481b1406101e2008302e00240b1232330010010022259800800c52f5bded8c11323302c3376060520026e98c8cc004004dd59815801112cc004006297adef6c608991981799bb0302c001375066e052000375a605a002660060066062004605e0028168cc00c00cc0b8008c0b000502a488c8cc00400400c896600200314a115980098019816800c528c4cc008008c0b8005028205691119199119801001000912cc00400600713233225980099b910070028acc004cdc78038014400600c816a26600a00a60660088168dd718160009bad302d001302f00140b46603e008006290004c094dd500448c0a8c0acc0acc0ac0052222222259800981400144c9660026604e6eb0c0c8c0ccc0ccc0ccc0cc004dd7180118179baa00d8cc004dd59819000cdd3198121803004004c88cdc3801000a0388a5040b46064606460646064605c6ea80722b300130240028cc00489660026054605e6ea800a264646464653001375a60700033038004981c001cdd7181c00124444b3001303d005899811981e00489981100189981080100545903a0c0e0004c0dc004c0d8004c0d4004c0c0dd500145902e48c0c8c0ccc0cc006460646066606660666066003302e375403891111991194c004c0e40066eacc0e0c0e4c0e400e6eb0c0e000d22259800981e001c4c8cc8966002605660746ea80062646644b3001302e303d37540031332233012001133012002159800cc004cdd7982198201baa0013043304037540054a14a281f22b30013375e606e60806ea800530103d87980008acc004cdd7981b98201baa0024c0103d87980008acc004cdc399b80337046eb4c10cc100dd5180898201baa001375a606e60806ea8c044c100dd500119b82375a608660806ea8c044c100dd50011bad303730403754602260806ea8004cdc11bad303730403754602260806ea8004dd6981b98201baa30113040375400519800acc004cdc49bad3010304037540046eb4c040c100dd5000c4cc108004cc108dd300399821001198211ba60044bd7044cc108008cc108dd300219821000998211ba60074bd70207cacc004c0e8c0fcdd5182198201baa0018a45025550008a4504444f574e0040f959800981d181f9baa3043304037540051489025550008a4504444f574e0040f93302c00d23375e608860826ea8c110c104dd5181c18209baa001303233043375207c97ae048888c8cc88c9660026084608e6ea801626464b300159800801c528c4cc88cc0880548c8c96600266ebcc148c13cdd518290011820198289ba90294bd7044c9660026080609e6ea80062b300198009bab30530029ba60059119b8900100240f513375e60a660a06ea800401a294104e45904e18291829800c528209a3052001304d3754002646464608c6609e60a00066609e60a00046609e60a00026609e60a060a20026609e6ea0cdc09bad301d304d375400e01097ae03050001304f001304a3754008660446eacc134018c084c0bccdc198011bad304d304a3754603660946ea8010dd6982098251baa301b304a375400882422b30013370e6530010019982000a812d20004004444b30010028800c4ca600200930520039919b80003375a609e0046eb8c1340050041828001209c59800801c520038a400282422b3001330200132325980099baf304f304c3754609e002608a6609c603e60986ea80352f5c1198009bab304f30500019ba69800824c02e00e81ba4466e2400400903945282094304b3754003159800998100099192cc004cdd7982798261baa304f00130453304e301f304c375401c97ae08cc004dd598279828000cdd34c00412601500740dd223371200200481ca294104a18259baa0018acc004cdc3cc00405208f488102555000407c00b15980099b87980080a411e91104444f574e00407c00b1330200132325980099baf304f304c3754609e002607a6609c6ea41252f5c1198009bab304f30500019ba60039119b8900100240e514a08250c12cdd5000c52820908a50412114a082422941048452820908a504120660426eacc100c124dd5182018249baa304c3049375400c605c66e00cdc198009bad304c30493754603460926ea8028dd6982018249baa301a3049375401466e0cc004dd6982618249baa301a304937540166eb4c100c124dd5180d18249baa00b370400716411866e1cdd6980b98239baa001002375a602a608a6ea8c120c124004c120014c1200111640f91640f91640f91640f86082607c6ea8004c104c0f8dd500245903c1bab303f001303f3040001303f303b3754607c607e60766ea8c0f801a2c81c8dd5981e000981e181e800981e181c1baa303b303c3038375460760091640e43302f00123375e6070606a6ea8c0e0c0d4dd51816181a9baa001302633037375201e97ae0303630360013758606a0028994c004dd61819000ccc0900200266eb4c0c8c0bcdd5008a444b300130360028992cc004c0a4dd69819800c4c8c8ca600260740033039001981c801cc0e4009222298009bae303d0049bad303d303e004acc004c0d0c0e4dd5000c566002606860726ea800a33001037a4502555000804a04a8cc0040de910104444f574e00804a04a40e11301f3370666e08024dd6981e981d1baa003375a606260746ea800d0382444b30013301300e2325980099baf3042303f375460840026070660826ea40152f5c1198009bab304230430019ba60039119b8900100240b114a081e8c0f8dd5000c566002b30013370e00401913370f3001375660806082608201f0179bae303c00b40489000c52820768a51899911980a808119192cc004cdd7982298211baa3045002303333044375203897ae08992cc004c0ccc108dd5000c56600330013756608c005374c00b22337120020048182266ebcc118c10cdd5000803452820828b2082304530460018a504100608a00260806ea8004c8c8c8c0e4cc108c10c00ccc108c10c008cc108c10c004cc108c10cc110004cc108dd419b8100500f4bd7018218009821000981e9baa01b3301501630149800802c01200d00c81d204040ed14a081d830390013038001303337540231640c4606a0051640cc30323032302e3754038816102c22c8120c0a0c094dd5181400098121baa3027302830243754604e60486ea80062c8110c094c088dd5000998071bac302530223754020466ebcc098c08cdd5000801c5902018109baa004302300130233024001301f375400b16407480e8603a603c01253001488100a44100800a00c229344d95900201", + "hash": "1d9670358959872ba038d87e894961616d1ec86c29b06eae77039134" + } + ], + "definitions": { + "ByteArray": { + "title": "ByteArray", + "dataType": "bytes" + }, + "Int": { + "dataType": "integer" + }, + "Option": { + "title": "Option", + "anyOf": [ + { + "title": "Some", + "description": "An optional value.", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "$ref": "#/definitions/hermes_types~1Price" + } + ] + }, + { + "title": "None", + "description": "Nothing.", + "dataType": "constructor", + "index": 1, + "fields": [] + } + ] + }, + "aiken/crypto/ScriptHash": { + "title": "ScriptHash", + "dataType": "bytes" + }, + "aiken/crypto/VerificationKeyHash": { + "title": "VerificationKeyHash", + "dataType": "bytes" + }, + "cardano/assets/PolicyId": { + "title": "PolicyId", + "dataType": "bytes" + }, + "cardano/transaction/OutputReference": { + "title": "OutputReference", + "description": "An `OutputReference` is a unique reference to an output on-chain. The `output_index`\n corresponds to the position in the output list of the transaction (identified by its id)\n that produced that output", + "anyOf": [ + { + "title": "OutputReference", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "transaction_id", + "$ref": "#/definitions/ByteArray" + }, + { + "title": "output_index", + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "hermes_types/Direction": { + "title": "Direction", + "anyOf": [ + { + "title": "Up", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "Down", + "dataType": "constructor", + "index": 1, + "fields": [] + } + ] + }, + "hermes_types/MarketDatum": { + "title": "MarketDatum", + "anyOf": [ + { + "title": "MarketDatum", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "start_price", + "$ref": "#/definitions/hermes_types~1Price" + }, + { + "title": "end_price", + "$ref": "#/definitions/Option" + }, + { + "title": "remaining_shares", + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "hermes_types/MarketMintRedeemer": { + "title": "MarketMintRedeemer", + "anyOf": [ + { + "title": "MintControlToken", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "BurnControlToken", + "dataType": "constructor", + "index": 1, + "fields": [] + }, + { + "title": "MintPositionToken", + "dataType": "constructor", + "index": 2, + "fields": [ + { + "$ref": "#/definitions/hermes_types~1Direction" + } + ] + }, + { + "title": "BurnPositionToken", + "dataType": "constructor", + "index": 3, + "fields": [ + { + "$ref": "#/definitions/hermes_types~1Direction" + } + ] + } + ] + }, + "hermes_types/MarketRedeemer": { + "title": "MarketRedeemer", + "anyOf": [ + { + "title": "RecordFinalPrice", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "ClaimWinnings", + "dataType": "constructor", + "index": 1, + "fields": [ + { + "$ref": "#/definitions/Int" + } + ] + }, + { + "title": "ClaimLosings", + "dataType": "constructor", + "index": 2, + "fields": [ + { + "$ref": "#/definitions/Int" + } + ] + }, + { + "title": "CloseMarket", + "dataType": "constructor", + "index": 3, + "fields": [] + }, + { + "title": "ProcessMatch", + "dataType": "constructor", + "index": 4, + "fields": [] + } + ] + }, + "hermes_types/Operation": { + "title": "Operation", + "anyOf": [ + { + "title": "Buy", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "Sell", + "dataType": "constructor", + "index": 1, + "fields": [] + } + ] + }, + "hermes_types/OrderDatum": { + "title": "OrderDatum", + "anyOf": [ + { + "title": "OrderDatum", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "direction", + "$ref": "#/definitions/hermes_types~1Direction" + }, + { + "title": "operation", + "$ref": "#/definitions/hermes_types~1Operation" + }, + { + "title": "price", + "$ref": "#/definitions/hermes_types~1Price" + }, + { + "title": "owner", + "$ref": "#/definitions/aiken~1crypto~1VerificationKeyHash" + }, + { + "title": "expected_tokens", + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "hermes_types/OrderMintRedeemer": { + "title": "OrderMintRedeemer", + "anyOf": [ + { + "title": "Mint", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "$ref": "#/definitions/cardano~1transaction~1OutputReference" + } + ] + }, + { + "title": "Burn", + "dataType": "constructor", + "index": 1, + "fields": [] + } + ] + }, + "hermes_types/OrderRedeemer": { + "title": "OrderRedeemer", + "anyOf": [ + { + "title": "Cancel", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "Match", + "dataType": "constructor", + "index": 1, + "fields": [] + }, + { + "title": "Fill", + "dataType": "constructor", + "index": 2, + "fields": [ + { + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "hermes_types/PosixTime": { + "title": "PosixTime", + "dataType": "integer" + }, + "hermes_types/Price": { + "title": "Price", + "anyOf": [ + { + "title": "Price", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "numerator", + "$ref": "#/definitions/Int" + }, + { + "title": "denominator", + "$ref": "#/definitions/Int" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/lazer/cardano/hermes/onchain/validators/market.ak b/lazer/cardano/hermes/onchain/validators/market.ak new file mode 100644 index 00000000..8719ece7 --- /dev/null +++ b/lazer/cardano/hermes/onchain/validators/market.ak @@ -0,0 +1,82 @@ +use aiken/collection/list +use cardano/address.{Address, Script} +use cardano/assets.{PolicyId} +use cardano/transaction.{Input, Output, OutputReference, Transaction} +use hermes_types.{ + BurnControlToken, BurnPositionToken, ClaimLosings, ClaimWinnings, CloseMarket, + MarketDatum, MarketMintRedeemer, MarketRedeemer, MintControlToken, + MintPositionToken, PosixTime, ProcessMatch, RecordFinalPrice, +} +use subvalidators/common_checks.{validate_only_burn} +use subvalidators/market_checks.{ + validate_claim_losings, validate_claim_winnings, validate_close_market, + validate_init_market, validate_mint_position_tokens, validate_process_match, + validate_record_final_price, +} + +validator market(start_time: PosixTime, pyth_policy: PolicyId) { + mint(redeemer: MarketMintRedeemer, policy_id: PolicyId, self: Transaction) { + when redeemer is { + MintControlToken -> + validate_init_market(pyth_policy, start_time, policy_id, self) + BurnControlToken -> validate_only_burn(policy_id, self) + MintPositionToken(_dir) -> validate_mint_position_tokens(policy_id, self) + BurnPositionToken(_dir) -> validate_only_burn(policy_id, self) + } + } + + spend( + op_datum: Option, + redeemer: MarketRedeemer, + utxo: OutputReference, + self: Transaction, + ) { + expect Some(datum) = op_datum + + let Transaction { inputs, .. } = self + + expect Some(Input { + output: Output { + address: Address { payment_credential: Script(own_script_hash), .. }, + value: i_val, + .. + }, + .. + }) = list.find(inputs, fn(input) { input.output_reference == utxo }) + + when redeemer is { + RecordFinalPrice -> + validate_record_final_price( + pyth_policy, + start_time, + own_script_hash, + datum, + i_val, + self, + ) + ClaimWinnings(claimed_tokens) -> + validate_claim_winnings( + i_val, + claimed_tokens, + datum, + own_script_hash, + self, + ) + ClaimLosings(claimed_tokens) -> + validate_claim_losings( + i_val, + claimed_tokens, + datum, + own_script_hash, + self, + ) + CloseMarket -> validate_close_market(own_script_hash, datum, self) + ProcessMatch -> + validate_process_match(datum, i_val, own_script_hash, self) + } + } + + else(_) { + fail + } +} diff --git a/lazer/cardano/hermes/onchain/validators/order.ak b/lazer/cardano/hermes/onchain/validators/order.ak new file mode 100644 index 00000000..f7e1ee09 --- /dev/null +++ b/lazer/cardano/hermes/onchain/validators/order.ak @@ -0,0 +1,60 @@ +use aiken/collection/list +use aiken/crypto.{ScriptHash} +use cardano/address.{Address, Script} +use cardano/assets.{PolicyId} +use cardano/transaction.{Input, Output, OutputReference, Transaction} +use hermes_types.{ + Cancel, Fill, Match, OrderDatum, OrderMintRedeemer, OrderRedeemer, +} +use subvalidators/common_checks.{validate_only_burn} +use subvalidators/order_checks.{ + validate_cancel, validate_create_order, validate_fill, validate_match, +} + +validator order(market_script_hash: ScriptHash) { + mint(redeemer: OrderMintRedeemer, policy_id: PolicyId, self: Transaction) { + when redeemer is { + OrderMintRedeemer.Mint(seed) -> + validate_create_order(seed, market_script_hash, policy_id, self) + OrderMintRedeemer.Burn -> validate_only_burn(policy_id, self) + } + } + + spend( + op_datum: Option, + redeemer: OrderRedeemer, + utxo: OutputReference, + self: Transaction, + ) { + expect Some(datum) = op_datum + + let Transaction { inputs, .. } = self + + expect Some(Input { + output: Output { + address: Address { payment_credential: Script(own_script_hash), .. }, + value: i_val, + .. + }, + .. + }) = list.find(inputs, fn(input) { input.output_reference == utxo }) + + when redeemer is { + Cancel -> validate_cancel(datum, own_script_hash, i_val, self) + Match -> validate_match(own_script_hash, market_script_hash, self) + Fill(filled_amount) -> + validate_fill( + datum, + i_val, + own_script_hash, + filled_amount, + market_script_hash, + self, + ) + } + } + + else(_) { + fail + } +} diff --git a/lazer/cardano/hermes/server/.env.example b/lazer/cardano/hermes/server/.env.example new file mode 100644 index 00000000..beef2df8 --- /dev/null +++ b/lazer/cardano/hermes/server/.env.example @@ -0,0 +1,4 @@ +PYTH_ACCESS_TOKEN="Complete it yourself" +PYTH_STATE_ASSET_UNIT="d799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e650797468205374617465" +HYDRA_NODE_PRIVATE_KEY="5820245120cdf333f8ea69114a2b3f05bcbc0d5c8e8486ca94c020623d5cca822e04" +CONTROL_TOKEN_POLICY_ID="186e32faa80a26810392fda6d559c7ed4721a65ce1c9d4ef3e1c87b4" diff --git a/lazer/cardano/hermes/server/.gitignore b/lazer/cardano/hermes/server/.gitignore new file mode 100644 index 00000000..9c97bbd4 --- /dev/null +++ b/lazer/cardano/hermes/server/.gitignore @@ -0,0 +1,3 @@ +node_modules +dist +.env diff --git a/lazer/cardano/hermes/server/package.json b/lazer/cardano/hermes/server/package.json new file mode 100644 index 00000000..a204b370 --- /dev/null +++ b/lazer/cardano/hermes/server/package.json @@ -0,0 +1,29 @@ +{ + "name": "hermes-server", + "version": "0.0.1", + "type": "module", + "scripts": { + "postinstall": "node scripts/patch-libsodium-esm.mjs", + "api": "tsx watch src/index.ts", + "matcher": "tsx watch src/matcher.ts", + "build": "tsc", + "start": "node dist/index.js", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@lucid-evolution/lucid": "^0.4.29", + "@pythnetwork/pyth-lazer-sdk": "^6.2.1", + "axios": "^1.13.6", + "bignumber.js": "^10.0.2", + "blake2b": "^2.1.4", + "dotenv": "^17.3.1", + "ws": "^8.18.2" + }, + "devDependencies": { + "@types/blake2b": "^2.1.3", + "@types/ws": "^8.5.14", + "prettier": "^3.8.1", + "tsx": "^4.19.4", + "typescript": "~5.9.3" + } +} diff --git a/lazer/cardano/hermes/server/pnpm-lock.yaml b/lazer/cardano/hermes/server/pnpm-lock.yaml new file mode 100644 index 00000000..54eea32c --- /dev/null +++ b/lazer/cardano/hermes/server/pnpm-lock.yaml @@ -0,0 +1,2025 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@lucid-evolution/lucid': + specifier: ^0.4.29 + version: 0.4.29(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)(fast-check@3.23.2) + '@pythnetwork/pyth-lazer-sdk': + specifier: ^6.2.1 + version: 6.2.1 + axios: + specifier: ^1.13.6 + version: 1.13.6 + bignumber.js: + specifier: ^10.0.2 + version: 10.0.2 + blake2b: + specifier: ^2.1.4 + version: 2.1.4 + dotenv: + specifier: ^17.3.1 + version: 17.3.1 + ws: + specifier: ^8.18.2 + version: 8.20.0 + devDependencies: + '@types/blake2b': + specifier: ^2.1.3 + version: 2.1.3 + '@types/ws': + specifier: ^8.5.14 + version: 8.18.1 + prettier: + specifier: ^3.8.1 + version: 3.8.1 + tsx: + specifier: ^4.19.4 + version: 4.21.0 + typescript: + specifier: ~5.9.3 + version: 5.9.3 + +packages: + + '@anastasia-labs/cardano-multiplatform-lib-browser@6.0.2-2': + resolution: {integrity: sha512-sSPPjO1Zye82YVqrUGIKrli/Zt2pPkZkQd/jv9k6AzjIZdNPD3hvuB2yH6RHeZUO8+K57bu9r7Rlyf7VGbhhTQ==} + + '@anastasia-labs/cardano-multiplatform-lib-browser@6.0.2-3': + resolution: {integrity: sha512-EP5Kr21xPtfEuCM3lR5tCIUQpMQ4Moisig8zD9BqUmBhQr/2ddxuE+MWhBF6tqH1AepzeXqRuTD1ozvdRn49Bw==} + + '@anastasia-labs/cardano-multiplatform-lib-nodejs@6.0.2-2': + resolution: {integrity: sha512-KLYHyJWtFsTUUbIVz9dn5GiCbI4Mrx5mRpDWXa3lVLWFKok6AkvYlyHk4OH4NNa4JBerrHTB6ZJrk75UgKAaMA==} + + '@anastasia-labs/cardano-multiplatform-lib-nodejs@6.0.2-3': + resolution: {integrity: sha512-Jy7QKahRQJgX6OFeuQvPXO0ejKfT9cQ8m3PFLBhbM04jjzFnaxlJJJ5+7qNHe3xdy40fMbMMe2SgAYPJ4gZ2Xw==} + + '@biglup/is-cid@1.0.3': + resolution: {integrity: sha512-R0XPZ/IQhU2TtetSFI9vI+7kJOJYNiCncn5ixEBW+/LNaZCo2HK37Mq3pRNzrM4FryuAkyeqY7Ujmj3I3e3t9g==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@cardano-ogmios/client@6.9.0': + resolution: {integrity: sha512-IsoUVsaMXiYyhWrdVKYOA5PDlX0EZ2gaq4lfk4JelRw6mcWVxemUrMaU2ndvugO9LQ3SCM1nESPgMIU0xe5FWw==} + engines: {node: '>=14'} + + '@cardano-ogmios/schema@6.9.0': + resolution: {integrity: sha512-e7QVLF+dQMIv9p+p5CWQjMfBmkERYRa2wK2AjyehQZCJnecZ0gvTbRqewdX5VW4mVXf6KUfFyphsxWK46Pg6LA==} + engines: {node: '>=14'} + + '@cardano-sdk/core@0.45.10': + resolution: {integrity: sha512-PU/onQuPgsy0CtFKDlHcozGHMTHrigWztTmKq54tL0TdWRcClXbMh5Q63ALcP388ZouPC1nKomOAooVgyrrEfw==} + engines: {node: '>=16.20.2'} + peerDependencies: + rxjs: ^7.4.0 + peerDependenciesMeta: + rxjs: + optional: true + + '@cardano-sdk/crypto@0.2.3': + resolution: {integrity: sha512-jTl8rbocV1XO5DBR6+lGY6Owc/bP+wBg5eO3PttTeKhx/J7o99pyuTa5H36a/XTJwqDwKIXV922QxZR+rfjVbA==} + engines: {node: '>=16.20.2'} + peerDependencies: + '@dcspark/cardano-multiplatform-lib-asmjs': ^3.1.1 + '@dcspark/cardano-multiplatform-lib-browser': ^3.1.1 + '@dcspark/cardano-multiplatform-lib-nodejs': ^3.1.1 + peerDependenciesMeta: + '@dcspark/cardano-multiplatform-lib-asmjs': + optional: true + '@dcspark/cardano-multiplatform-lib-browser': + optional: true + '@dcspark/cardano-multiplatform-lib-nodejs': + optional: true + + '@cardano-sdk/util@0.16.0': + resolution: {integrity: sha512-f0tfX8oiauqAFCyyc/o2Ouezyk83QD4zqLl4DUjZNyCtITL8gBHh25Bkw7RUCGEZ+hf6Qms1n0ui0j3wVY7zRg==} + engines: {node: '>=16.20.2'} + + '@cardanosolutions/json-bigint@1.1.0': + resolution: {integrity: sha512-Pdgz18cSwLKKgheOqW/dqbzNI+CliNT4AdaKaKY/P++J9qLxIB8MITCurlzbaFWV3W4nmK0CRQwI1yvuArmjFg==} + + '@cbor-extract/cbor-extract-darwin-arm64@2.2.2': + resolution: {integrity: sha512-ZKZ/F8US7JR92J4DMct6cLW/Y66o2K576+zjlEN/MevH70bFIsB10wkZEQPLzl2oNh2SMGy55xpJ9JoBRl5DOA==} + cpu: [arm64] + os: [darwin] + + '@cbor-extract/cbor-extract-darwin-x64@2.2.2': + resolution: {integrity: sha512-32b1mgc+P61Js+KW9VZv/c+xRw5EfmOcPx990JbCBSkYJFY0l25VinvyyWfl+3KjibQmAcYwmyzKF9J4DyKP/Q==} + cpu: [x64] + os: [darwin] + + '@cbor-extract/cbor-extract-linux-arm64@2.2.2': + resolution: {integrity: sha512-wfqgzqCAy/Vn8i6WVIh7qZd0DdBFaWBjPdB6ma+Wihcjv0gHqD/mw3ouVv7kbbUNrab6dKEx/w3xQZEdeXIlzg==} + cpu: [arm64] + os: [linux] + + '@cbor-extract/cbor-extract-linux-arm@2.2.2': + resolution: {integrity: sha512-tNg0za41TpQfkhWjptD+0gSD2fggMiDCSacuIeELyb2xZhr7PrhPe5h66Jc67B/5dmpIhI2QOUtv4SBsricyYQ==} + cpu: [arm] + os: [linux] + + '@cbor-extract/cbor-extract-linux-x64@2.2.2': + resolution: {integrity: sha512-rpiLnVEsqtPJ+mXTdx1rfz4RtUGYIUg2rUAZgd1KjiC1SehYUSkJN7Yh+aVfSjvCGtVP0/bfkQkXpPXKbmSUaA==} + cpu: [x64] + os: [linux] + + '@cbor-extract/cbor-extract-win32-x64@2.2.2': + resolution: {integrity: sha512-dI+9P7cfWxkTQ+oE+7Aa6onEn92PHgfWXZivjNheCRmTBDBf2fx6RyTi0cmgpYLnD1KLZK9ZYrMxaPZ4oiXhGA==} + cpu: [x64] + os: [win32] + + '@chainsafe/is-ip@2.1.0': + resolution: {integrity: sha512-KIjt+6IfysQ4GCv66xihEitBjvhU/bixbbbFxdJ1sqCp4uJ0wuZiYBPhksZoy4lfaF0k9cwNzY5upEW/VWdw3w==} + + '@chainsafe/netmask@2.0.0': + resolution: {integrity: sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==} + + '@dnsquery/dns-packet@6.1.1': + resolution: {integrity: sha512-WXTuFvL3G+74SchFAtz3FgIYVOe196ycvGsMgvSH/8Goptb1qpIQtIuM4SOK9G9lhMWYpHxnXyy544ZhluFOew==} + engines: {node: '>=6'} + + '@effect/platform@0.71.7': + resolution: {integrity: sha512-Ttw8OhbcP1x5cPgcX4VdnDSWrskVdUrf9bO3eDd++TTcQzEiYVu9GZJaSMvz6Yqzfzt+1tIKoKi2jp6dLdJ9dg==} + peerDependencies: + effect: ^3.11.10 + + '@effect/schema@0.66.16': + resolution: {integrity: sha512-sT/k5NOgKslGPzs3DUaCFuM6g2JQoIIT8jpwEorAZooplPIMK2xIspr7ECz6pp6Dc7Wz/ppXGk7HVyGZQsIYEQ==} + deprecated: this package has been merged into the main effect package + peerDependencies: + effect: ^3.1.3 + fast-check: ^3.13.2 + + '@effect/schema@0.68.27': + resolution: {integrity: sha512-/rmIb+4QaQTecdTfeYSZtNikIV+BeIbYDl/hpgBTaS96en7pKNW5hcygFQhdocjKguIL7Y/be+oUrVafWV60ew==} + deprecated: this package has been merged into the main effect package + peerDependencies: + effect: ^3.5.7 + + '@emurgo/cardano-message-signing-browser@1.1.0': + resolution: {integrity: sha512-LyeiGIqCyZu9DZnKsi4wlBjZA1MN+uy3Cqpb5J6RZWvFXDJnCoxrYB/EixUiGRD/la4WsldBgtPsrIHyGsVkpg==} + + '@emurgo/cardano-message-signing-nodejs@1.1.0': + resolution: {integrity: sha512-PQRc8K8wZshEdmQenNUzVtiI8oJNF/1uAnBhidee5C4o1l2mDLOW+ur46HWHIFKQ6x8mSJTllcjMscHgzju0gQ==} + + '@esbuild/aix-ppc64@0.27.4': + resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.4': + resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.4': + resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.4': + resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.4': + resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.4': + resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.4': + resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.4': + resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.4': + resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.4': + resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.4': + resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.4': + resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.4': + resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.4': + resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.4': + resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.4': + resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.4': + resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.4': + resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.4': + resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.4': + resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.4': + resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.4': + resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.4': + resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.4': + resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.4': + resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.4': + resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@foxglove/crc@0.0.3': + resolution: {integrity: sha512-DjIZsnL3CyP/yQ/vUYA9cjrD0a/8YXejI5ZmsaOiT16cLfZcTwaCxIN01/ys4jsy+dZCQ/9DnWFn7AEFbiMDaA==} + + '@harmoniclabs/bigint-utils@1.0.0': + resolution: {integrity: sha512-OhZMHcdtH2hHKMlxWFHf71PmKHdoi9ARpjS9mUu0/cd8VWDDjT7VQoQwC5NN/68iyO4O5Dojrvrp9tjG5BDABA==} + + '@harmoniclabs/biguint@1.0.0': + resolution: {integrity: sha512-5DyCIBDL4W+7ffR1IJSbGrCG4xEYxAlFH5gCNF42qtyL5ltwZ92Ae1MyXpHM2TUPy7ocSTqlLUsOdy+SvqVVPw==} + + '@harmoniclabs/bitstream@1.0.0': + resolution: {integrity: sha512-Ed/I46IuCiytE5QiMmmUo9kPJcypM7OuUqoRaAXUALL5C6LKLpT6kYE1qeuhLkx2/WvkHT18jcOX6jhM/nmqoA==} + + '@harmoniclabs/bytestring@1.0.0': + resolution: {integrity: sha512-d5m10O0okKc6QNX0pSRriFTkk/kNMnMBGbo5X3kEZwKaXTI4tDVoTZBL7bwbYHwOEdSxWJjVtlO9xtB7ZrYZNg==} + + '@harmoniclabs/cbor@1.6.6': + resolution: {integrity: sha512-nOcts7PhkKCbqPKwP3/IsIQACwJvqchpT88cwvKspB+oR09YfB1LC1NrUTsFg1DusLRydVsOwR07KgYTF5uNOA==} + + '@harmoniclabs/crypto@0.2.5': + resolution: {integrity: sha512-t2saWMFWBx8tOHotiYTTfQKhPGpWT4AMLXxq3u0apShVXNV0vgL0gEgSMudBjES/wrKByCqa2xmU70gadz26hA==} + + '@harmoniclabs/obj-utils@1.0.0': + resolution: {integrity: sha512-EO1bQBZAORrutcP+leP5YNDwNd/9TOE23VEvs3ktniXg6w0knUrLjUIl2Pkcbs/D1VQxqmsNpXho+vaMj00qxA==} + + '@harmoniclabs/pair@1.0.0': + resolution: {integrity: sha512-D9OBowsUsy1LctHxWzd9AngTzoo5x3rBiJ0gu579t41Q23pb+VNx1euEfluUEiaYbgljcl1lb/4D1fFTZd1tRQ==} + + '@harmoniclabs/plutus-data@1.2.6': + resolution: {integrity: sha512-rF046GZ07XDpjZBNybALKYSycjxCLzXKbhLylu9pRuZiii5fVXReEfgtLB29TsPBvGY6ZBeiyHgJnLgm+huZBw==} + peerDependencies: + '@harmoniclabs/bytestring': ^1.0.0 + '@harmoniclabs/cbor': ^1.3.0 + + '@harmoniclabs/uint8array-utils@1.0.4': + resolution: {integrity: sha512-Z454prSbX4geXGHyjjcn9vm6u9NsD3VJykv8f8yE1VjIXSPitaLPEnm8u2+B+GMp1chYlLilOq+kW4OvJ6y28A==} + + '@harmoniclabs/uplc@1.4.1': + resolution: {integrity: sha512-sELKStjxPBPBxBMylU4oBSUe0/8eJe2HqRblNSwrMu8Fso4YpSPDqHZ33iDZ8QAadVUsT5r2EQKX0TLrj7qXvQ==} + peerDependencies: + '@harmoniclabs/bytestring': ^1.0.0 + '@harmoniclabs/cbor': ^1.3.0 + '@harmoniclabs/crypto': ^0.3.0-dev0 + '@harmoniclabs/pair': ^1.0.0 + '@harmoniclabs/plutus-data': ^1.2.4 + + '@isaacs/ttlcache@1.4.1': + resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} + engines: {node: '>=12'} + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + + '@libp2p/interface@3.1.0': + resolution: {integrity: sha512-RE7/XyvC47fQBe1cHxhMvepYKa5bFCUyFrrpj8PuM0E7JtzxU7F+Du5j4VXbg2yLDcToe0+j8mB7jvwE2AThYw==} + + '@lucid-evolution/core-types@0.1.22': + resolution: {integrity: sha512-2ffw82PAjB9wdnW62zWh5J8Wkqrr+sMrdXtndejdu4UYmTdmf7rIClr+AfKO8IStCciVcNT/wQj59PyYu/Jg1Q==} + + '@lucid-evolution/core-utils@0.1.16': + resolution: {integrity: sha512-fNKZiGl1h6tf48bji067uxHZpDlhkrIDrwhZLt5DQC/c6GVdZb4TSvqgs7MOmMqp1dj9dy6NDYWnCHeTqZAhJw==} + + '@lucid-evolution/crc8@0.1.8': + resolution: {integrity: sha512-88+/S6n+sPgxYtG05rvbJDVb8MoFGzckkR3p26uGrzngYzlJGfxBWIzNhVwfI2mgINPo2C5lkZW3GYnfY0MjuA==} + + '@lucid-evolution/lucid@0.4.29': + resolution: {integrity: sha512-+9pXlHivIGE4xJC6EZ62vtOBfgHgPpbJHgd7d6Ztk3lmbBwsM1PZVQ1WSE2upXSvqGE8KT/99IxmZ3kKfbtDUg==} + + '@lucid-evolution/plutus@0.1.29': + resolution: {integrity: sha512-GHmq9Pso+xeFszwKAd9jvRFnmnV4fRKdm+OHYLrS58yh3uazKr9VR+amtT9SmKufoLy/gNo5sL7i6gcNSW+yIg==} + + '@lucid-evolution/provider@0.1.90': + resolution: {integrity: sha512-8vzVDlWJiDfuvuE2Un18N5uTK8qDkVB5GiglwoDV/qgBNRljQjiih53LbhcGa4KMXgufjZNyNDH854jFkJ95cg==} + + '@lucid-evolution/sign_data@0.1.25': + resolution: {integrity: sha512-ZDDl3SyO3Lf+/ji9u0Fg6I9oNs+tW//aHkgz4NlS+9xbx2bT9YU+mV9ZLLjWSZVGTb0TbzT4NGvVqdgRNspdYQ==} + + '@lucid-evolution/uplc@0.2.20': + resolution: {integrity: sha512-+40qeHmjMnM4Sjdq9JAf190a1t3TMbV1vegVLQGqt2AouOkIunZfziBZwuaqcgUVVbynW+j2Qx2ijK83Pap4XQ==} + + '@lucid-evolution/utils@0.1.66': + resolution: {integrity: sha512-sp6vsxrc0u9rYgb4ExRP4LRQM0oK6mVxqt70axK0T4DSS06KYtCqUWX6kjcOHY8jxDGfjK5RLh9hBY+Gul4OSQ==} + + '@lucid-evolution/wallet@0.1.72': + resolution: {integrity: sha512-keGeDV4jUX2MAld79zAGja4mFNQ9FP4HJM8OB8DEnakewTVG4fk38SMSfvuQAh6yH8ZxTNoGUphrMSeVFU4OjQ==} + + '@multiformats/dns@1.0.13': + resolution: {integrity: sha512-yr4bxtA3MbvJ+2461kYIYMsiiZj/FIqKI64hE4SdvWJUdWF9EtZLar38juf20Sf5tguXKFUruluswAO6JsjS2w==} + + '@multiformats/mafmt@12.1.6': + resolution: {integrity: sha512-tlJRfL21X+AKn9b5i5VnaTD6bNttpSpcqwKVmDmSHLwxoz97fAHaepqFOk/l1fIu94nImIXneNbhsJx/RQNIww==} + + '@multiformats/multiaddr@12.5.1': + resolution: {integrity: sha512-+DDlr9LIRUS8KncI1TX/FfUn8F2dl6BIxJgshS/yFQCNB5IAF0OGzcwB39g5NLE22s4qqDePv0Qof6HdpJ/4aQ==} + + '@multiformats/multiaddr@13.0.1': + resolution: {integrity: sha512-XToN915cnfr6Lr9EdGWakGJbPT0ghpg/850HvdC+zFX8XvpLZElwa8synCiwa8TuvKNnny6m8j8NVBNCxhIO3g==} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@pythnetwork/pyth-lazer-sdk@6.2.1': + resolution: {integrity: sha512-+d+ATApOBF5z3YvqwP/5R42xr9vWpLOvbAFWDWldYiltlH8eU9PaGgeczgCs3it3STpnL+8jTXsUBhqv9T94Aw==} + engines: {node: ^24.0.0} + + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + + '@sinclair/typebox@0.32.35': + resolution: {integrity: sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@types/blake2b@2.1.3': + resolution: {integrity: sha512-MFCdX0MNxFBP/xEILO5Td0kv6nI7+Q2iRWZbTL/yzH2/eDVZS5Wd1LHdsmXClvsCyzqaZfHFzZaN6BUeUCfSDA==} + + '@types/json-bigint@1.0.4': + resolution: {integrity: sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==} + + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@zxing/text-encoding@0.9.0': + resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} + + abort-error@1.0.1: + resolution: {integrity: sha512-fxqCblJiIPdSXIUrxI0PL+eJG49QdP9SQ70qtB65MVAoMr2rASlOyAbJFOylfB467F/f+5BCLJJq58RYi7mGfg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@1.13.6: + resolution: {integrity: sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==} + + b4a@1.8.0: + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bech32@2.0.0: + resolution: {integrity: sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==} + + bignumber.js@10.0.2: + resolution: {integrity: sha512-E8Wp9O06QA6lneJ4aRUXKYf/1GIomqUEmUMwtIOMtDxf1U52ffJY+y7JBk/8wRafA8qOIqLnXQGqonYXZdBnFQ==} + + bip39@3.1.0: + resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==} + + blake2b-wasm@2.4.0: + resolution: {integrity: sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==} + + blake2b@2.1.4: + resolution: {integrity: sha512-AyBuuJNI64gIvwx13qiICz6H6hpmjvYS5DGkG6jbXMOT8Z3WUJ3V1X0FlhIoT1b/5JtHE3ki+xjtMvu1nn+t9A==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + cbor-extract@2.2.2: + resolution: {integrity: sha512-hlSxxI9XO2yQfe9g6msd3g4xCfDqK5T5P0fRMLuaLHhxn4ViPrm+a+MUfhrvH2W962RGxcBwEGzLQyjbDG1gng==} + hasBin: true + + cbor-x@1.6.4: + resolution: {integrity: sha512-UGKHjp6RHC6QuZ2yy5LCKm7MojM4716DwoSaqwQpaH4DvZvbBTGcoDNTiG9Y2lByXZYFEs9WRkS5tLl96IrF1Q==} + + cipher-base@1.0.7: + resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} + engines: {node: '>= 0.10'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dotenv@17.3.1: + resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + effect@3.21.0: + resolution: {integrity: sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.27.4: + resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} + engines: {node: '>=18'} + hasBin: true + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + fast-check@3.23.2: + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} + engines: {node: '>=8.0.0'} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + find-my-way-ts@0.1.6: + resolution: {integrity: sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + fraction.js@4.0.1: + resolution: {integrity: sha512-NQYzZw8MUsxSZFQo6E8tKOlmSd/BlDTNOR4puXFSHSwFwNaIlmbortQy5PDN/KnVQ4xWG2NtN0J0hjPw7eE06A==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.13.7: + resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hash-base@3.1.2: + resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} + engines: {node: '>= 0.8'} + + hashlru@2.3.0: + resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + i@0.3.7: + resolution: {integrity: sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==} + engines: {node: '>=0.4'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + iso-url@1.2.1: + resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} + engines: {node: '>=12'} + + isomorphic-ws@4.0.1: + resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} + peerDependencies: + ws: '*' + + isomorphic-ws@5.0.0: + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + libsodium-sumo@0.7.16: + resolution: {integrity: sha512-x6atrz2AdXCJg6G709x9W9TTJRI6/0NcL5dD0l5GGVqNE48UJmDsjO4RUWYTeyXXUpg+NXZ2SHECaZnFRYzwGA==} + + libsodium-wrappers-sumo@0.7.16: + resolution: {integrity: sha512-gR0JEFPeN3831lB9+ogooQk0KH4K5LSMIO5Prd5Q5XYR2wHFtZfPg0eP7t1oJIWq+UIzlU4WVeBxZ97mt28tXw==} + + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + + main-event@1.0.1: + resolution: {integrity: sha512-NWtdGrAca/69fm6DIVd8T9rtfDII4Q8NQbIbsKQq2VzS9eqOGYs8uaNQjcuaCq/d9H/o625aOTJX2Qoxzqw0Pw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + multiformats@13.4.2: + resolution: {integrity: sha512-eh6eHCrRi1+POZ3dA+Dq1C6jhP1GNtr9CRINMb67OKzqW9I5DUuZM/3jLPlzhgpGeiNUlEGEbkCYChXMCc/8DQ==} + + multipasta@0.2.7: + resolution: {integrity: sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==} + + nanoassert@2.0.0: + resolution: {integrity: sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build-optional-packages@5.1.1: + resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} + hasBin: true + + npm@9.9.4: + resolution: {integrity: sha512-NzcQiLpqDuLhavdyJ2J3tGJ/ni/ebcqHVFZkv1C4/6lblraUPbPgCJ4Vhb4oa3FFhRa2Yj9gA58jGH/ztKueNQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/config' + - '@npmcli/fs' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/promise-spawn' + - '@npmcli/run-script' + - abbrev + - archy + - cacache + - chalk + - ci-info + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - fs-minipass + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minimatch + - minipass + - minipass-pipeline + - ms + - node-gyp + - nopt + - normalize-package-data + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - p-map + - pacote + - parse-conflict-json + - proc-log + - qrcode-terminal + - read + - semver + - sigstore + - spdx-expression-parse + - ssri + - supports-color + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + + p-queue@9.1.0: + resolution: {integrity: sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==} + engines: {node: '>=20'} + + p-timeout@7.0.1: + resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} + engines: {node: '>=20'} + + pbkdf2@3.1.5: + resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} + engines: {node: '>= 0.10'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + progress-events@1.0.1: + resolution: {integrity: sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + ripemd160@2.0.3: + resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} + engines: {node: '>= 0.8'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + serialize-error@8.1.0: + resolution: {integrity: sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==} + engines: {node: '>=10'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + sha.js@2.4.12: + resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} + engines: {node: '>= 0.10'} + hasBin: true + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + to-buffer@1.2.2: + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} + engines: {node: '>= 0.4'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-custom-error@3.3.1: + resolution: {integrity: sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==} + engines: {node: '>=14.0.0'} + + ts-log@2.2.7: + resolution: {integrity: sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg==} + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + uint8-varint@2.0.4: + resolution: {integrity: sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==} + + uint8arraylist@2.4.8: + resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} + + uint8arrays@5.1.0: + resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + utf8-codec@1.0.0: + resolution: {integrity: sha512-S/QSLezp3qvG4ld5PUfXiH7mCFxLKjSVZRFkB3DOjgwHuJPFDkInAXc/anf7BAbHt/D38ozDzL+QMZ6/7gsI6w==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + web-encoding@1.1.5: + resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-typed-array@1.1.20: + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + engines: {node: '>= 0.4'} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@anastasia-labs/cardano-multiplatform-lib-browser@6.0.2-2': {} + + '@anastasia-labs/cardano-multiplatform-lib-browser@6.0.2-3': {} + + '@anastasia-labs/cardano-multiplatform-lib-nodejs@6.0.2-2': {} + + '@anastasia-labs/cardano-multiplatform-lib-nodejs@6.0.2-3': {} + + '@biglup/is-cid@1.0.3': + dependencies: + '@multiformats/mafmt': 12.1.6 + '@multiformats/multiaddr': 12.5.1 + iso-url: 1.2.1 + multiformats: 13.4.2 + uint8arrays: 5.1.0 + + '@cardano-ogmios/client@6.9.0': + dependencies: + '@cardano-ogmios/schema': 6.9.0 + '@cardanosolutions/json-bigint': 1.1.0 + '@types/json-bigint': 1.0.4 + bech32: 2.0.0 + cross-fetch: 3.2.0 + fastq: 1.20.1 + isomorphic-ws: 4.0.1(ws@7.5.10) + nanoid: 3.3.11 + ts-custom-error: 3.3.1 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + + '@cardano-ogmios/schema@6.9.0': {} + + '@cardano-sdk/core@0.45.10': + dependencies: + '@biglup/is-cid': 1.0.3 + '@cardano-ogmios/client': 6.9.0 + '@cardano-ogmios/schema': 6.9.0 + '@cardano-sdk/crypto': 0.2.3 + '@cardano-sdk/util': 0.16.0 + '@foxglove/crc': 0.0.3 + '@scure/base': 1.2.6 + fraction.js: 4.0.1 + ip-address: 9.0.5 + lodash: 4.17.23 + ts-custom-error: 3.3.1 + ts-log: 2.2.7 + web-encoding: 1.1.5 + transitivePeerDependencies: + - '@dcspark/cardano-multiplatform-lib-asmjs' + - '@dcspark/cardano-multiplatform-lib-browser' + - '@dcspark/cardano-multiplatform-lib-nodejs' + - bufferutil + - encoding + - react-native-b4a + - utf-8-validate + + '@cardano-sdk/crypto@0.2.3': + dependencies: + '@cardano-sdk/util': 0.16.0 + blake2b: 2.1.4 + i: 0.3.7 + libsodium-wrappers-sumo: 0.7.16 + lodash: 4.17.23 + npm: 9.9.4 + pbkdf2: 3.1.5 + ts-custom-error: 3.3.1 + ts-log: 2.2.7 + transitivePeerDependencies: + - react-native-b4a + + '@cardano-sdk/util@0.16.0': + dependencies: + bech32: 2.0.0 + lodash: 4.17.23 + serialize-error: 8.1.0 + ts-custom-error: 3.3.1 + ts-log: 2.2.7 + type-fest: 2.19.0 + + '@cardanosolutions/json-bigint@1.1.0': {} + + '@cbor-extract/cbor-extract-darwin-arm64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-darwin-x64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-arm64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-arm@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-x64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-win32-x64@2.2.2': + optional: true + + '@chainsafe/is-ip@2.1.0': {} + + '@chainsafe/netmask@2.0.0': + dependencies: + '@chainsafe/is-ip': 2.1.0 + + '@dnsquery/dns-packet@6.1.1': + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + utf8-codec: 1.0.0 + + '@effect/platform@0.71.7(effect@3.21.0)': + dependencies: + effect: 3.21.0 + find-my-way-ts: 0.1.6 + multipasta: 0.2.7 + + '@effect/schema@0.66.16(effect@3.21.0)(fast-check@3.23.2)': + dependencies: + effect: 3.21.0 + fast-check: 3.23.2 + + '@effect/schema@0.68.27(effect@3.21.0)': + dependencies: + effect: 3.21.0 + fast-check: 3.23.2 + + '@emurgo/cardano-message-signing-browser@1.1.0': {} + + '@emurgo/cardano-message-signing-nodejs@1.1.0': {} + + '@esbuild/aix-ppc64@0.27.4': + optional: true + + '@esbuild/android-arm64@0.27.4': + optional: true + + '@esbuild/android-arm@0.27.4': + optional: true + + '@esbuild/android-x64@0.27.4': + optional: true + + '@esbuild/darwin-arm64@0.27.4': + optional: true + + '@esbuild/darwin-x64@0.27.4': + optional: true + + '@esbuild/freebsd-arm64@0.27.4': + optional: true + + '@esbuild/freebsd-x64@0.27.4': + optional: true + + '@esbuild/linux-arm64@0.27.4': + optional: true + + '@esbuild/linux-arm@0.27.4': + optional: true + + '@esbuild/linux-ia32@0.27.4': + optional: true + + '@esbuild/linux-loong64@0.27.4': + optional: true + + '@esbuild/linux-mips64el@0.27.4': + optional: true + + '@esbuild/linux-ppc64@0.27.4': + optional: true + + '@esbuild/linux-riscv64@0.27.4': + optional: true + + '@esbuild/linux-s390x@0.27.4': + optional: true + + '@esbuild/linux-x64@0.27.4': + optional: true + + '@esbuild/netbsd-arm64@0.27.4': + optional: true + + '@esbuild/netbsd-x64@0.27.4': + optional: true + + '@esbuild/openbsd-arm64@0.27.4': + optional: true + + '@esbuild/openbsd-x64@0.27.4': + optional: true + + '@esbuild/openharmony-arm64@0.27.4': + optional: true + + '@esbuild/sunos-x64@0.27.4': + optional: true + + '@esbuild/win32-arm64@0.27.4': + optional: true + + '@esbuild/win32-ia32@0.27.4': + optional: true + + '@esbuild/win32-x64@0.27.4': + optional: true + + '@foxglove/crc@0.0.3': {} + + '@harmoniclabs/bigint-utils@1.0.0': + dependencies: + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@harmoniclabs/biguint@1.0.0': {} + + '@harmoniclabs/bitstream@1.0.0': + dependencies: + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@harmoniclabs/bytestring@1.0.0': + dependencies: + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@harmoniclabs/cbor@1.6.6': + dependencies: + '@harmoniclabs/bytestring': 1.0.0 + '@harmoniclabs/obj-utils': 1.0.0 + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@harmoniclabs/crypto@0.2.5': + dependencies: + '@harmoniclabs/bitstream': 1.0.0 + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@harmoniclabs/obj-utils@1.0.0': {} + + '@harmoniclabs/pair@1.0.0': {} + + '@harmoniclabs/plutus-data@1.2.6(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)': + dependencies: + '@harmoniclabs/biguint': 1.0.0 + '@harmoniclabs/bytestring': 1.0.0 + '@harmoniclabs/cbor': 1.6.6 + '@harmoniclabs/crypto': 0.2.5 + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@harmoniclabs/uint8array-utils@1.0.4': {} + + '@harmoniclabs/uplc@1.4.1(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)(@harmoniclabs/plutus-data@1.2.6(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6))': + dependencies: + '@harmoniclabs/bigint-utils': 1.0.0 + '@harmoniclabs/bytestring': 1.0.0 + '@harmoniclabs/cbor': 1.6.6 + '@harmoniclabs/crypto': 0.2.5 + '@harmoniclabs/pair': 1.0.0 + '@harmoniclabs/plutus-data': 1.2.6(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6) + '@harmoniclabs/uint8array-utils': 1.0.4 + + '@isaacs/ttlcache@1.4.1': {} + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@libp2p/interface@3.1.0': + dependencies: + '@multiformats/dns': 1.0.13 + '@multiformats/multiaddr': 13.0.1 + main-event: 1.0.1 + multiformats: 13.4.2 + progress-events: 1.0.1 + uint8arraylist: 2.4.8 + + '@lucid-evolution/core-types@0.1.22': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + + '@lucid-evolution/core-utils@0.1.16': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-2 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-2 + + '@lucid-evolution/crc8@0.1.8': {} + + '@lucid-evolution/lucid@0.4.29(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)(fast-check@3.23.2)': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + '@effect/schema': 0.66.16(effect@3.21.0)(fast-check@3.23.2) + '@emurgo/cardano-message-signing-nodejs': 1.1.0 + '@lucid-evolution/core-types': 0.1.22 + '@lucid-evolution/core-utils': 0.1.16 + '@lucid-evolution/plutus': 0.1.29 + '@lucid-evolution/provider': 0.1.90(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0) + '@lucid-evolution/sign_data': 0.1.25 + '@lucid-evolution/uplc': 0.2.20 + '@lucid-evolution/utils': 0.1.66(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0) + '@lucid-evolution/wallet': 0.1.72(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0) + effect: 3.21.0 + transitivePeerDependencies: + - '@dcspark/cardano-multiplatform-lib-asmjs' + - '@dcspark/cardano-multiplatform-lib-browser' + - '@dcspark/cardano-multiplatform-lib-nodejs' + - '@harmoniclabs/bytestring' + - '@harmoniclabs/cbor' + - '@harmoniclabs/crypto' + - '@harmoniclabs/pair' + - bufferutil + - encoding + - fast-check + - react-native-b4a + - rxjs + - utf-8-validate + + '@lucid-evolution/plutus@0.1.29': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + '@lucid-evolution/core-types': 0.1.22 + '@lucid-evolution/core-utils': 0.1.16 + '@sinclair/typebox': 0.32.35 + + '@lucid-evolution/provider@0.1.90(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + '@effect/platform': 0.71.7(effect@3.21.0) + '@effect/schema': 0.68.27(effect@3.21.0) + '@lucid-evolution/core-types': 0.1.22 + '@lucid-evolution/core-utils': 0.1.16 + '@lucid-evolution/utils': 0.1.66(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0) + '@lucid-evolution/wallet': 0.1.72(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0) + effect: 3.21.0 + transitivePeerDependencies: + - '@dcspark/cardano-multiplatform-lib-asmjs' + - '@dcspark/cardano-multiplatform-lib-browser' + - '@dcspark/cardano-multiplatform-lib-nodejs' + - '@harmoniclabs/bytestring' + - '@harmoniclabs/cbor' + - '@harmoniclabs/crypto' + - '@harmoniclabs/pair' + - bufferutil + - encoding + - react-native-b4a + - rxjs + - utf-8-validate + + '@lucid-evolution/sign_data@0.1.25': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + '@emurgo/cardano-message-signing-browser': 1.1.0 + '@emurgo/cardano-message-signing-nodejs': 1.1.0 + '@lucid-evolution/core-types': 0.1.22 + '@lucid-evolution/core-utils': 0.1.16 + + '@lucid-evolution/uplc@0.2.20': {} + + '@lucid-evolution/utils@0.1.66(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + '@cardano-sdk/core': 0.45.10 + '@effect/schema': 0.68.27(effect@3.21.0) + '@harmoniclabs/plutus-data': 1.2.6(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6) + '@harmoniclabs/uplc': 1.4.1(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)(@harmoniclabs/plutus-data@1.2.6(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)) + '@lucid-evolution/core-types': 0.1.22 + '@lucid-evolution/core-utils': 0.1.16 + '@lucid-evolution/crc8': 0.1.8 + '@lucid-evolution/plutus': 0.1.29 + '@lucid-evolution/uplc': 0.2.20 + bip39: 3.1.0 + cbor-x: 1.6.4 + effect: 3.21.0 + transitivePeerDependencies: + - '@dcspark/cardano-multiplatform-lib-asmjs' + - '@dcspark/cardano-multiplatform-lib-browser' + - '@dcspark/cardano-multiplatform-lib-nodejs' + - '@harmoniclabs/bytestring' + - '@harmoniclabs/cbor' + - '@harmoniclabs/crypto' + - '@harmoniclabs/pair' + - bufferutil + - encoding + - react-native-b4a + - rxjs + - utf-8-validate + + '@lucid-evolution/wallet@0.1.72(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0)': + dependencies: + '@anastasia-labs/cardano-multiplatform-lib-browser': 6.0.2-3 + '@anastasia-labs/cardano-multiplatform-lib-nodejs': 6.0.2-3 + '@lucid-evolution/core-types': 0.1.22 + '@lucid-evolution/core-utils': 0.1.16 + '@lucid-evolution/sign_data': 0.1.25 + '@lucid-evolution/utils': 0.1.66(@harmoniclabs/bytestring@1.0.0)(@harmoniclabs/cbor@1.6.6)(@harmoniclabs/crypto@0.2.5)(@harmoniclabs/pair@1.0.0) + bip39: 3.1.0 + transitivePeerDependencies: + - '@dcspark/cardano-multiplatform-lib-asmjs' + - '@dcspark/cardano-multiplatform-lib-browser' + - '@dcspark/cardano-multiplatform-lib-nodejs' + - '@harmoniclabs/bytestring' + - '@harmoniclabs/cbor' + - '@harmoniclabs/crypto' + - '@harmoniclabs/pair' + - bufferutil + - encoding + - react-native-b4a + - rxjs + - utf-8-validate + + '@multiformats/dns@1.0.13': + dependencies: + '@dnsquery/dns-packet': 6.1.1 + '@libp2p/interface': 3.1.0 + hashlru: 2.3.0 + p-queue: 9.1.0 + progress-events: 1.0.1 + uint8arrays: 5.1.0 + + '@multiformats/mafmt@12.1.6': + dependencies: + '@multiformats/multiaddr': 12.5.1 + + '@multiformats/multiaddr@12.5.1': + dependencies: + '@chainsafe/is-ip': 2.1.0 + '@chainsafe/netmask': 2.0.0 + '@multiformats/dns': 1.0.13 + abort-error: 1.0.1 + multiformats: 13.4.2 + uint8-varint: 2.0.4 + uint8arrays: 5.1.0 + + '@multiformats/multiaddr@13.0.1': + dependencies: + '@chainsafe/is-ip': 2.1.0 + multiformats: 13.4.2 + uint8-varint: 2.0.4 + uint8arrays: 5.1.0 + + '@noble/hashes@1.8.0': {} + + '@pythnetwork/pyth-lazer-sdk@6.2.1': + dependencies: + '@isaacs/ttlcache': 1.4.1 + buffer: 6.0.3 + isomorphic-ws: 5.0.0(ws@8.20.0) + ts-log: 2.2.7 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@scure/base@1.2.6': {} + + '@sinclair/typebox@0.32.35': {} + + '@standard-schema/spec@1.1.0': {} + + '@types/blake2b@2.1.3': {} + + '@types/json-bigint@1.0.4': {} + + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + + '@types/ws@8.18.1': + dependencies: + '@types/node': 25.5.0 + + '@zxing/text-encoding@0.9.0': + optional: true + + abort-error@1.0.1: {} + + asynckit@0.4.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axios@1.13.6: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + b4a@1.8.0: {} + + base64-js@1.5.1: {} + + bech32@2.0.0: {} + + bignumber.js@10.0.2: {} + + bip39@3.1.0: + dependencies: + '@noble/hashes': 1.8.0 + + blake2b-wasm@2.4.0: + dependencies: + b4a: 1.8.0 + nanoassert: 2.0.0 + transitivePeerDependencies: + - react-native-b4a + + blake2b@2.1.4: + dependencies: + blake2b-wasm: 2.4.0 + nanoassert: 2.0.0 + transitivePeerDependencies: + - react-native-b4a + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + cbor-extract@2.2.2: + dependencies: + node-gyp-build-optional-packages: 5.1.1 + optionalDependencies: + '@cbor-extract/cbor-extract-darwin-arm64': 2.2.2 + '@cbor-extract/cbor-extract-darwin-x64': 2.2.2 + '@cbor-extract/cbor-extract-linux-arm': 2.2.2 + '@cbor-extract/cbor-extract-linux-arm64': 2.2.2 + '@cbor-extract/cbor-extract-linux-x64': 2.2.2 + '@cbor-extract/cbor-extract-win32-x64': 2.2.2 + optional: true + + cbor-x@1.6.4: + optionalDependencies: + cbor-extract: 2.2.2 + + cipher-base@1.0.7: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + core-util-is@1.0.3: {} + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.7 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.3 + sha.js: 2.4.12 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.7 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + delayed-stream@1.0.0: {} + + detect-libc@2.1.2: + optional: true + + dotenv@17.3.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + effect@3.21.0: + dependencies: + '@standard-schema/spec': 1.1.0 + fast-check: 3.23.2 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.27.4: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.4 + '@esbuild/android-arm': 0.27.4 + '@esbuild/android-arm64': 0.27.4 + '@esbuild/android-x64': 0.27.4 + '@esbuild/darwin-arm64': 0.27.4 + '@esbuild/darwin-x64': 0.27.4 + '@esbuild/freebsd-arm64': 0.27.4 + '@esbuild/freebsd-x64': 0.27.4 + '@esbuild/linux-arm': 0.27.4 + '@esbuild/linux-arm64': 0.27.4 + '@esbuild/linux-ia32': 0.27.4 + '@esbuild/linux-loong64': 0.27.4 + '@esbuild/linux-mips64el': 0.27.4 + '@esbuild/linux-ppc64': 0.27.4 + '@esbuild/linux-riscv64': 0.27.4 + '@esbuild/linux-s390x': 0.27.4 + '@esbuild/linux-x64': 0.27.4 + '@esbuild/netbsd-arm64': 0.27.4 + '@esbuild/netbsd-x64': 0.27.4 + '@esbuild/openbsd-arm64': 0.27.4 + '@esbuild/openbsd-x64': 0.27.4 + '@esbuild/openharmony-arm64': 0.27.4 + '@esbuild/sunos-x64': 0.27.4 + '@esbuild/win32-arm64': 0.27.4 + '@esbuild/win32-ia32': 0.27.4 + '@esbuild/win32-x64': 0.27.4 + + eventemitter3@5.0.4: {} + + fast-check@3.23.2: + dependencies: + pure-rand: 6.1.0 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + find-my-way-ts@0.1.6: {} + + follow-redirects@1.15.11: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + fraction.js@4.0.1: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + generator-function@2.0.1: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-tsconfig@4.13.7: + dependencies: + resolve-pkg-maps: 1.0.0 + + gopd@1.2.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash-base@3.1.2: + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + hashlru@2.3.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + i@0.3.7: {} + + ieee754@1.2.1: {} + + inherits@2.0.4: {} + + ip-address@9.0.5: + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.20 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + iso-url@1.2.1: {} + + isomorphic-ws@4.0.1(ws@7.5.10): + dependencies: + ws: 7.5.10 + + isomorphic-ws@5.0.0(ws@8.20.0): + dependencies: + ws: 8.20.0 + + jsbn@1.1.0: {} + + libsodium-sumo@0.7.16: {} + + libsodium-wrappers-sumo@0.7.16: + dependencies: + libsodium-sumo: 0.7.16 + + lodash@4.17.23: {} + + main-event@1.0.1: {} + + math-intrinsics@1.1.0: {} + + md5.js@1.3.5: + dependencies: + hash-base: 3.1.2 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + multiformats@13.4.2: {} + + multipasta@0.2.7: {} + + nanoassert@2.0.0: {} + + nanoid@3.3.11: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build-optional-packages@5.1.1: + dependencies: + detect-libc: 2.1.2 + optional: true + + npm@9.9.4: {} + + p-queue@9.1.0: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 7.0.1 + + p-timeout@7.0.1: {} + + pbkdf2@3.1.5: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + to-buffer: 1.2.2 + + possible-typed-array-names@1.1.0: {} + + prettier@3.8.1: {} + + process-nextick-args@2.0.1: {} + + progress-events@1.0.1: {} + + proxy-from-env@1.1.0: {} + + pure-rand@6.1.0: {} + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + resolve-pkg-maps@1.0.0: {} + + reusify@1.1.0: {} + + ripemd160@2.0.3: + dependencies: + hash-base: 3.1.2 + inherits: 2.0.4 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + serialize-error@8.1.0: + dependencies: + type-fest: 0.20.2 + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + sha.js@2.4.12: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + sprintf-js@1.1.3: {} + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + to-buffer@1.2.2: + dependencies: + isarray: 2.0.5 + safe-buffer: 5.2.1 + typed-array-buffer: 1.0.3 + + tr46@0.0.3: {} + + ts-custom-error@3.3.1: {} + + ts-log@2.2.7: {} + + tsx@4.21.0: + dependencies: + esbuild: 0.27.4 + get-tsconfig: 4.13.7 + optionalDependencies: + fsevents: 2.3.3 + + type-fest@0.20.2: {} + + type-fest@2.19.0: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typescript@5.9.3: {} + + uint8-varint@2.0.4: + dependencies: + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + + uint8arraylist@2.4.8: + dependencies: + uint8arrays: 5.1.0 + + uint8arrays@5.1.0: + dependencies: + multiformats: 13.4.2 + + undici-types@7.18.2: {} + + utf8-codec@1.0.0: {} + + util-deprecate@1.0.2: {} + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.2 + is-typed-array: 1.1.15 + which-typed-array: 1.1.20 + + web-encoding@1.1.5: + dependencies: + util: 0.12.5 + optionalDependencies: + '@zxing/text-encoding': 0.9.0 + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-typed-array@1.1.20: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + ws@7.5.10: {} + + ws@8.20.0: {} diff --git a/lazer/cardano/hermes/server/scripts/patch-libsodium-esm.mjs b/lazer/cardano/hermes/server/scripts/patch-libsodium-esm.mjs new file mode 100644 index 00000000..ae4ba314 --- /dev/null +++ b/lazer/cardano/hermes/server/scripts/patch-libsodium-esm.mjs @@ -0,0 +1,85 @@ +/** + * libsodium-wrappers-sumo ESM entry imports "./libsodium-sumo.mjs" from the same + * directory as libsodium-wrappers.mjs, but the published package only ships the + * wrapper file; the real module lives in libsodium-sumo. Bare Node + pnpm hit + * ERR_MODULE_NOT_FOUND without this symlink. + * + * The wrappers package may only appear under .pnpm (not hoisted to root + * node_modules), so we locate it explicitly. + */ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const serverRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); + +function findWrappersPkgRoot() { + const direct = path.join(serverRoot, "node_modules", "libsodium-wrappers-sumo"); + if (fs.existsSync(path.join(direct, "package.json"))) { + return fs.realpathSync(direct); + } + + const pnpmDir = path.join(serverRoot, "node_modules", ".pnpm"); + if (!fs.existsSync(pnpmDir)) { + return null; + } + for (const name of fs.readdirSync(pnpmDir, { withFileTypes: true })) { + if (!name.isDirectory() || !name.name.startsWith("libsodium-wrappers-sumo@")) { + continue; + } + const candidate = path.join(pnpmDir, name.name, "node_modules", "libsodium-wrappers-sumo"); + if (fs.existsSync(path.join(candidate, "package.json"))) { + return fs.realpathSync(candidate); + } + } + return null; +} + +function main() { + const wsPkgRoot = findWrappersPkgRoot(); + if (!wsPkgRoot) { + console.warn("[patch-libsodium-esm] libsodium-wrappers-sumo not found, skip"); + return; + } + + const sumoPkgRoot = path.join(wsPkgRoot, "..", "libsodium-sumo"); + + const esmDir = path.join(wsPkgRoot, "dist", "modules-sumo-esm"); + const linkPath = path.join(esmDir, "libsodium-sumo.mjs"); + const targetPath = path.join(sumoPkgRoot, "dist", "modules-sumo-esm", "libsodium-sumo.mjs"); + + if (!fs.existsSync(path.join(sumoPkgRoot, "package.json"))) { + console.warn("[patch-libsodium-esm] sibling libsodium-sumo not found:", sumoPkgRoot); + return; + } + if (!fs.existsSync(targetPath)) { + console.warn("[patch-libsodium-esm] missing target:", targetPath); + return; + } + if (!fs.existsSync(esmDir)) { + console.warn("[patch-libsodium-esm] missing dir:", esmDir); + return; + } + + const relTarget = path.relative(esmDir, targetPath); + + try { + if (fs.existsSync(linkPath)) { + const st = fs.lstatSync(linkPath); + if (st.isSymbolicLink()) { + const resolved = path.resolve(esmDir, fs.readlinkSync(linkPath)); + if (resolved === path.resolve(targetPath)) { + return; + } + } + fs.unlinkSync(linkPath); + } + fs.symlinkSync(relTarget, linkPath); + console.log("[patch-libsodium-esm] OK", linkPath, "->", relTarget); + } catch (e) { + console.error("[patch-libsodium-esm]", e); + process.exitCode = 1; + } +} + +main(); diff --git a/lazer/cardano/hermes/server/src/index.ts b/lazer/cardano/hermes/server/src/index.ts new file mode 100644 index 00000000..8ddea60e --- /dev/null +++ b/lazer/cardano/hermes/server/src/index.ts @@ -0,0 +1,203 @@ +import "dotenv/config"; +import { createServer } from "node:http"; +import { WebSocketServer } from "ws"; +import type WebSocket from "ws"; +import type { + Action, + ClientMessage, + Fill, + Order, + PositionSummary, + RollingAverages, + ServerMessage, + Side, +} from "./types.js"; +import { createBtcPriceStream } from "./streams/btcPrice.js"; +import { createOrderbookStream } from "./streams/orderbook.js"; +import { createPositionsStream } from "./streams/positions.js"; +import { createMarket } from "./offchain/index.js"; +import { handleRestRequest } from "./rest.js"; + +const PORT = 8080; +const AVG_WINDOW = 20; +const MAX_ORDERS_SERVER = 50; // kept in memory for rolling average computation + +// ── State ───────────────────────────────────────────────────────────────────── + +// eslint-disable-next-line prefer-const +let currentMarket!: import("./types.js").Market; // set in async IIFE before first WS connection +let orderWindow: Order[] = []; +let positionSummary: PositionSummary = { + upContracts: 0, + upAvgPrice: 0, + downContracts: 0, + downAvgPrice: 0, +}; + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +function computeRollingAverages(orders: Order[]): RollingAverages { + const window = orders.slice(0, AVG_WINDOW); + const avg = (side: Side, action: Action): number => { + const bucket = window.filter((o) => o.side === side && o.action === action); + if (bucket.length === 0) return 0.5; + return bucket.reduce((sum, o) => sum + o.price, 0) / bucket.length; + }; + return { + upBuyAvg: avg("UP", "BUY"), + upSellAvg: avg("UP", "SELL"), + downBuyAvg: avg("DOWN", "BUY"), + downSellAvg: avg("DOWN", "SELL"), + }; +} + +function updatePositionSummary( + prev: PositionSummary, + fill: Fill, +): PositionSummary { + if (fill.side === "UP") { + const total = prev.upContracts + fill.quantity; + const avgPrice = + total === 0 + ? 0 + : (prev.upAvgPrice * prev.upContracts + fill.price * fill.quantity) / + total; + return { ...prev, upContracts: total, upAvgPrice: avgPrice }; + } else { + const total = prev.downContracts + fill.quantity; + const avgPrice = + total === 0 + ? 0 + : (prev.downAvgPrice * prev.downContracts + + fill.price * fill.quantity) / + total; + return { ...prev, downContracts: total, downAvgPrice: avgPrice }; + } +} + +function send(ws: WebSocket, msg: ServerMessage): void { + if (ws.readyState === ws.OPEN) { + ws.send(JSON.stringify(msg)); + } +} + +function broadcast(wss: WebSocketServer, msg: ServerMessage): void { + wss.clients.forEach((client) => send(client, msg)); +} + +// ── Server ──────────────────────────────────────────────────────────────────── + +const httpServer = createServer(handleRestRequest); +const wss = new WebSocketServer({ server: httpServer }); +httpServer.listen(PORT, () => { + console.log(`[server] listening on http://localhost:${PORT}`); +}); + +// ── Market lifecycle ────────────────────────────────────────────────────────── + +function resetMarketState(): void { + orderWindow = []; + positionSummary = { + upContracts: 0, + upAvgPrice: 0, + downContracts: 0, + downAvgPrice: 0, + }; +} + +async function startNextMarket(): Promise { + currentMarket = await createMarket(); + resetMarketState(); + console.log( + `[server] market ${currentMarket.id} started, strikePrice=${currentMarket.strikePrice}, ends ${new Date(currentMarket.endTime).toISOString()}`, + ); + broadcast(wss, { type: "market_started", data: { market: currentMarket } }); + scheduleNextMarket(); +} + +function scheduleNextMarket(): void { + const remaining = Math.max(0, currentMarket.endTime - Date.now()); + setTimeout(startNextMarket, remaining); +} + +// ── Streams + initial market ────────────────────────────────────────────────── + +void (async () => { + currentMarket = await createMarket(); + console.log( + `[server] market ${currentMarket.id} started, strikePrice=${currentMarket.strikePrice}, ends ${new Date(currentMarket.endTime).toISOString()}`, + ); + scheduleNextMarket(); + + const { emitter: priceEmitter, getPrice } = await createBtcPriceStream(); + const { emitter: orderbookEmitter, getLatestOrder } = + createOrderbookStream(getPrice); + const positionsEmitter = createPositionsStream(getLatestOrder); + + priceEmitter.on("tick", (tick) => { + broadcast(wss, { type: "price_tick", data: tick }); + }); + + orderbookEmitter.on("order", (order: Order) => { + orderWindow = [order, ...orderWindow].slice(0, MAX_ORDERS_SERVER); + broadcast(wss, { type: "order", data: order }); + broadcast(wss, { + type: "rolling_averages", + data: computeRollingAverages(orderWindow), + }); + }); + + positionsEmitter.on("fill", (fill: Fill) => { + positionSummary = updatePositionSummary(positionSummary, fill); + broadcast(wss, { type: "fill", data: fill }); + broadcast(wss, { type: "position_summary", data: positionSummary }); + }); +})(); + +// ── Connection handling ─────────────────────────────────────────────────────── + +wss.on("connection", (ws) => { + console.log("[server] client connected"); + + // Send initial handshake with the current active market + send(ws, { type: "connected", data: { market: currentMarket } }); + + ws.on("message", (raw) => { + let msg: ClientMessage; + try { + msg = JSON.parse(raw.toString()) as ClientMessage; + } catch { + console.warn("[server] received non-JSON message, ignoring"); + return; + } + + if (msg.type === "place_order") { + const { side, action, price, quantity } = msg.data; + console.log( + `[server] place_order received: ${action} ${quantity} ${side} @ ${price.toFixed(4)}`, + ); + + // TODO: Submit the order to the Orderbook smart contract instead of logging. + // + // import { ethers } from "ethers" + // + // const ORDERBOOK_ADDRESS = "0x..." // TODO: deployed contract address + // const ABI = [...] // TODO: contract ABI + // const provider = new ethers.JsonRpcProvider("https://your-rpc-url") + // const signer = new ethers.Wallet(process.env.SIGNER_PRIVATE_KEY!, provider) + // const contract = new ethers.Contract(ORDERBOOK_ADDRESS, ABI, signer) + // + // const tx = await contract.placeOrder( + // side === "UP" ? 0 : 1, + // action === "BUY" ? 0 : 1, + // ethers.parseEther(price.toString()), + // quantity + // ) + // await tx.wait() + // console.log(`[server] order submitted: ${tx.hash}`) + } + }); + + ws.on("close", () => console.log("[server] client disconnected")); + ws.on("error", (err) => console.error("[server] client error:", err.message)); +}); diff --git a/lazer/cardano/hermes/server/src/market.ts b/lazer/cardano/hermes/server/src/market.ts new file mode 100644 index 00000000..d956be8f --- /dev/null +++ b/lazer/cardano/hermes/server/src/market.ts @@ -0,0 +1,171 @@ +import { HydraHandler } from "./offchain/hydra/handler.js"; +import { HydraProvider } from "./offchain/hydra/provider.js"; +import type { Market } from "./types.js"; +import { CML, Lucid, Data, validatorToAddress, credentialToRewardAddress } from '@lucid-evolution/lucid' +import fs from 'fs' +import path from 'path' +import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk"; +import assert from "assert"; + +export const MARKET_DURATION_MS = 5 * 60 * 1000; // 5 minutes + + +assert(process.env.PYTH_STATE_ASSET_UNIT) +assert(process.env.HYDRA_NODE_PRIVATE_KEY) +assert(process.env.CONTROL_TOKEN_POLICY_ID) + +const PYTH_STATE_ASSET_UNIT = process.env.PYTH_STATE_ASSET_UNIT; +const HYDRA_NODE_PRIVATE_KEY = process.env.HYDRA_NODE_PRIVATE_KEY; +const CONTROL_TOKEN_POLICY_ID = process.env.CONTROL_TOKEN_POLICY_ID; +const BTC_PRICE_FEED = 1; + +export async function createMarket(strikePrice: number): Promise { + // TODO: change to env var + const HYDRA_NODE_URL = "ws://localhost:4011" + const handler = new HydraHandler(HYDRA_NODE_URL) + const provider = new HydraProvider(handler) + // TODO: setup testnet id + const lucid = await Lucid(provider, "Preprod") + + // TODO: change to env var + const pythStateUtxo = await lucid.utxoByUnit(PYTH_STATE_ASSET_UNIT) + console.log("pythStateUtxo:", pythStateUtxo) + // TODO: parse pyth state datum to get withdraw script field + const pythStateDatum = Data.from(pythStateUtxo.datum ?? "", PythStateDatum) + + + // connect "admin" wallet: hydra credentials wallet + + const sk = Buffer.from(HYDRA_NODE_PRIVATE_KEY, 'hex') + const privateKey = CML.PrivateKey.from_normal_bytes(sk.subarray(2)) + lucid.selectWallet.fromPrivateKey(privateKey.to_bech32()) + console.log(await lucid.wallet().getUtxos()) + const [seedUtxo,] = await lucid.wallet().getUtxos() + + // TODO: get market script address + // instantiate market script (with timestamp parameter) + const marketScriptAddress = await lucid.wallet().address() + + const lazer = await PythLazerClient.create({ token: process.env.PYTH_ACCESS_TOKEN ?? "", webSocketPoolConfig: {} }); + + const latestPrice = await lazer.getLatestPrice({ + channel: "fixed_rate@200ms", + formats: ["solana"], + jsonBinaryEncoding: "hex", + priceFeedIds: [BTC_PRICE_FEED], + properties: ["price", "exponent", "feedUpdateTimestamp"], + }); + + if (!latestPrice.solana?.data) { + throw new Error("Missing update payload"); + } + + // const update = Data.fromJson(`0x${latestPrice.solana.data}`) + // console.log("latestPrice:", latestPrice) + // console.log("update:", update) + // + const maybeParsedPrice = latestPrice.parsed?.priceFeeds?.at(0); + assert(maybeParsedPrice, "Could not find latest price for feed",); + const price = maybeParsedPrice.price; + const exponent = maybeParsedPrice.exponent; + + assert(price && exponent, "Price not found"); + + + const rawSignature = [latestPrice.solana.data] + const update = Data.to(rawSignature as any, Data.Array(Data.Bytes())) + console.log("pythStateDatum.withdraw_script", pythStateDatum.withdraw_script) + + + // TODO: get control token policy, form plutus json ?? + const controlTokenAsset = `${CONTROL_TOKEN_POLICY_ID}${seedUtxo.txHash}` + + + const marketInlineDatum = Data.to({ + startPrice: { + numerator: BigInt(price), + denominator: BigInt((10 ** exponent).toFixed(0)), + }, + endPrice: null, + remainingShares: 0n, + }, MarketDatum) + + const now = Date.now(); + const tx = await lucid + .newTx() + .readFrom([pythStateUtxo]) + .collectFrom([seedUtxo]) + .mintAssets({ [controlTokenAsset]: 1n }, Data.void()) + .attach.Script({ type: "PlutusV3", script: "46450101002499" }) + .pay.ToContract(marketScriptAddress, { kind: "inline", value: marketInlineDatum }, { [controlTokenAsset]: 1n }) + .withdraw( + credentialToRewardAddress("Preprod", { type: "Script", hash: pythStateDatum.withdraw_script }), + 0n, + update + ) + .attach.WithdrawalValidator({ type: "PlutusV3", script: "590ab60101003229800aba4aba2aba1aba0aab9faab9eaab9dab9a9bae002488888888966002646465300130063754003370e90014dc3a4001300a0039805001244444b30013370e9003002c4c8c966002600c601a6ea800e2b3001300e3754007159800980298069baa301130120028a518b20188b201e8b2018375a602000260186ea801a264b300130010068cc004c040c034dd5003cdd6001488c8cc00400400c88cc00c004c0080092223300100222598008014660024602c602e602e0032301630170019ba54800244b3001300b30133754005132323259800980d80144c8c9660026020003159800980c9baa00280345901a456600260220031323259800980f80140222c80e0dd6980e800980c9baa0028acc004c0340062b3001301937540050068b20348b202e405c80b8c05cdd5000980d001c59018192cc004c05c0062b3001337129002180b000c5a2601e602c00280aa2c80c0dd5180c800980c800980a1baa0028b202448888cc8966002601e602e6ea800a2646464646644b300130220038992cc004c058c078dd5000c4c8c8c8ca60026eb4c0980066eb8c0980126eb4c09800e6eb8c0980092222598009815802c4cc060dd59815007112cc00400a26603401844b30010028acc004c08cc0a8dd500f44cc88cc89660026644b30013371e6eb8c0d0c0d4c0d4c0d4c0c4dd500d800c528c4c8cc004004dd5981018191baa01c2259800800c528456600264b30013371e6eb8c0d000401226600e606600200b14a08190c0d80062946266004004606e0028189034205e3001302f375404a6eb8c0c8c0bcdd501144c9289919800800811112cc00400629344c8cc89263259800cc004dd7181018199baa0019bae302130333754003375c606c60666ea800572a8acc004c8c966002605a60686ea800629422605a60686ea8c0e0c0d4dd5000a06632598009816981a1baa0018a60103d87a8000898109981bcc004cc020c0e0c0d4dd50009803981a9baa02ba6103d87a8000a60103d879800040cc97ae040cc64660020026eacc088c0d4dd500f912cc004006298103d87a80008992cc004cdc78021bae3036001898119981c981b800a5eb82266006006607600481a8c0e40050371bae30203033375400310018b20628b2062325980099b8f48900375c606c606e003130360018b2062323235980099b8f375c606e00291104b9011a82008919191919191919911981f98149981f98200039981f9ba90013303f30400024bd701981f9820182080125eb80d6600266e252000001892cc004cdc48011b8d00189981f1ba93300a0020013303e3753300100299b81371a0020050015c612f5c11640e91640e46eb8c0f8c0fc008dd7181f0021bad303d001323303c375066f29281bae303d0013303c303d303e0014bd702cc004cdc4a40086e340062660766ea4cc01d20040013303b375330014801266e00dc6800a40070015c612f5c11640dc6eb8c0ecc0f0004d6600294624b30013371290201b8d00189981d1ba93300648100004cc0e8dd4cc005204099b80371a002901fc0057184bd704590364590351bae303a303b001300100259800a51892cc004cdc4a4100026e340062660706ea4cc0112080010013303837533001482000666e00dc6800a40ff0015c612f5c11640d11640cd1640c86eb8c0dcc0e00056600266e252008371a00513303537526600290040011981a9ba99800a4011337006e3400920078012e3097ae08b20623718900019801801981b0011bae303400140c91640b444b300130040018a518acc004c01000a29422b3001980099baf9800981918179baa002981918179baa001919192cc004c0a8c0c4dd5181a981b00144006264b3001302b001899ba548008cc0d4dd419b80375a606c60666ea800920024bd704566002605400310028801206240c460626ea8005030181a00098181baa001400c98103d87b8000a50a5140b51980099baf9800980e18179baa002980e18179baa001919192cc004c0a8c0c4dd5181a981b00144006264b3001302b001899ba548008cc0d4dd419b80375a606c60666ea800920014bd704566002605400310028801206240c460626ea8005030181a00098181baa001400c98103d8798000a50a5140b514a0816902d205a2303130323032303230323032303230320012323232332259800981400145284566002604a0051980099baf30343031375400298103d87b8000a50a5140bd13233225980098158014528c566002605800513322598009817181a9baa30233036375400d13371000400313371200400281a0dd6981b981a1baa00359800981618199baa30213034375400f1001899b80001480090324528206440c860626ea8004dd6981a98191baa004303430313754002817902f18171baa001303230330033031302e3754002606000260586ea8004888c8cc89660026050005159800981418181baa0018a60103d87a80008a6103d879800040bd15980098128014566002604a60606ea80062980103d87a80008a6103d87b800040bd13322598009815000c530103d87b80008acc004c0ac006264b30013371000600314c0103d87980008acc004cdc4000801c530103d87b80008a6103d87a800040c88190dd6981b18199baa0038a6103d879800040c48188dd6981a18189baa00330303754002817902f18171baa001300200330010038b2052899191980b18160010980198188021bae302c001302e00240b11323233014302b00213003302f004375c6052002605800481522c8140604c002604a0026048002603e6ea80062c80e8c08401a2c80f8dd7180f8009bab301f002301f001301e001301d0013018375400516405864b3001300e301637540031301a3017375400316405464660020026eb0c010c05cdd5006912cc004006298103d87a80008992cc006600266ebc00530103d87a8000a50a51405d1001899801801980e801202e325980099912cc00400a294226530013259800980a180e1baa00189bad301d302037566040603a6ea8006290002036301f0019baf301f30200019bab003488966002003159800980100344cc01400d20008a5040751325980099baf301f0014c010140008acc004cc018010dd6981018119bab3020001898019ba630240028a5040791598009980300224001130030078a50407880f0c0880050200ca60020033756601260386ea8c024c070dd5002488cc080008cc080dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c0780066eacc07c00660460069112cc004cdc8a441000038acc004cdc7a441000038998029807198121ba60024bd70000c4cc015300103d87a8000006408119800803c006446600e0046604c66ec0dd48029ba6004001401c8100604200480fa2942294229410201ba63301b337606ea4058dd31980d99bb0301c3019375498118d8799f4a507974682053746174654850797468204f7073ff004c010101004bd6f7b63025eb7bdb1808928c566002602260306ea8c070c064dd5180e180c9baa300630193754003132598009807180c9baa001898031980e180e980d1baa0014bd704590181803980c9baa30063019375400316405d14c103d87a8000405c603600280c88966002601e602e6ea800a2646464b3001301f002899803180f00189980300080245901c180e800980e800980c1baa0028b202c44c8c008c05c00cdd7180a801202645900b1b874801100a0c024c028004c024004c010dd5005452689b2b20042611e581cd799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e60001" }) + .validFrom(now - 60_000) + .validTo(now + 60_000) + .complete() + + console.log(tx.toJSON()) + + + + return { + id: crypto.randomUUID(), + startTime: now, + endTime: now + MARKET_DURATION_MS, + strikePrice, + }; +} + +/** + * Load user's public key from credentials file + * TODO there's a better way to do this? + */ +export function loadHydraCredentialsPublicKey(): string { + console.log("loadHydraCredentialsPublicKey cwd:", process.cwd()) + const vkPath = path.join(process.cwd(), '../infra/credentials', 'hydra-funds.sk') + const vk = JSON.parse(fs.readFileSync(vkPath, 'utf8')) + const vkBytes = Buffer.from("5820245120cdf333f8ea69114a2b3f05bcbc0d5c8e8486ca94c020623d5cca822e04", 'hex') + const publicKey = CML.PublicKey.from_bytes(vkBytes.subarray(2)) + return publicKey.to_bech32() +} + +// Minimal schema matching the on-chain Pyth state datum layout. +// Only the `withdraw_script` field is used; the preceding fields +// are defined to keep positional alignment with the Plutus struct. +// biome-ignore assist/source/useSortedKeys: order-sensistive + + +const PythStateDatumSchema = Data.Object({ + governance: Data.Object({ + wormhole: Data.Bytes(), + emitter_chain: Data.Integer(), + emitter_address: Data.Bytes(), + seen_sequence: Data.Integer(), + }), + trusted_signers: Data.Map(Data.Any(), Data.Any()), + deprecated_withdraw_scripts: Data.Map(Data.Any(), Data.Any()), + withdraw_script: Data.Bytes(), +}); +type PythStateDatum = Data.Static; +const PythStateDatum = PythStateDatumSchema as unknown as PythStateDatum + + +const MarketDatumSchema = Data.Object({ + startPrice: Data.Object({ + numerator: Data.Integer(), + denominator: Data.Integer(), + }), + endPrice: Data.Nullable( + Data.Object({ + numerator: Data.Integer(), + denominator: Data.Integer(), + }) + ), + remainingShares: Data.Integer(), +}); +type MarketDatum = Data.Static; +const MarketDatum = MarketDatumSchema as unknown as MarketDatum diff --git a/lazer/cardano/hermes/server/src/matcher.ts b/lazer/cardano/hermes/server/src/matcher.ts new file mode 100644 index 00000000..c17e8d23 --- /dev/null +++ b/lazer/cardano/hermes/server/src/matcher.ts @@ -0,0 +1,45 @@ +import "dotenv/config"; +import { getOpenOrders, removeOrder } from "./offchain/index.js"; + +const POLL_INTERVAL_MS = 500; + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +async function runMatcher(): Promise { + console.log("[matcher] starting, polling every", POLL_INTERVAL_MS, "ms"); + + while (true) { + const orders = getOpenOrders(); + // Only BUY orders on both sides participate in matching + const upBuys = orders.filter((o) => o.side === "UP" && o.action === "BUY"); + const downBuys = orders.filter( + (o) => o.side === "DOWN" && o.action === "BUY", + ); + + for (const up of upBuys) { + for (const down of downBuys) { + if (up.price + down.price !== 1) continue; + + const qty = Math.min(up.quantity, down.quantity); + console.log( + `[matcher] matched UP@${up.price.toFixed(4)} + DOWN@${down.price.toFixed(4)}` + + ` qty=${qty} buyer=${up.ownerAddress} vs ${down.ownerAddress}`, + ); + + // TODO: Replace with on-chain match call: + // await contract.matchOrders(up.id, down.id, qty) + removeOrder(up.id); + removeOrder(down.id); + } + } + + await sleep(POLL_INTERVAL_MS); + } +} + +runMatcher().catch((err: unknown) => { + console.error("[matcher] fatal:", err); + process.exit(1); +}); diff --git a/lazer/cardano/hermes/server/src/offchain/claims.ts b/lazer/cardano/hermes/server/src/offchain/claims.ts new file mode 100644 index 00000000..044463a7 --- /dev/null +++ b/lazer/cardano/hermes/server/src/offchain/claims.ts @@ -0,0 +1,15 @@ +// TODO: Replace with on-chain claim: +// +// export async function claimWonShares(marketId: string, ownerAddress: string): Promise { +// const tx = await contract.claimShares(marketId, ownerAddress) +// await tx.wait() +// } + +// ── MOCK ────────────────────────────────────────────────────────────────────── +export function claimWonShares(marketId: string, ownerAddress: string): void { + // MOCK: no-op — in production this calls the settlement contract + console.log( + `[offchain] claimWonShares: market=${marketId} owner=${ownerAddress} (mock)`, + ); +} +// ── END MOCK ────────────────────────────────────────────────────────────────── diff --git a/lazer/cardano/hermes/server/src/offchain/hydra/handler.ts b/lazer/cardano/hermes/server/src/offchain/hydra/handler.ts new file mode 100644 index 00000000..27a10fb1 --- /dev/null +++ b/lazer/cardano/hermes/server/src/offchain/hydra/handler.ts @@ -0,0 +1,344 @@ +import Websocket from 'ws'; +import axios from 'axios'; +import { + Assets, + CBORHex, + CML, + fromUnit, + UTxO, +} from '@lucid-evolution/lucid'; +import blake2b from 'blake2b'; + +const ERROR_TAGS = [ + 'PeerHandshakeFailure', + 'TxInvalid', + 'InvalidInput', + 'PostTxOnChainFailed', + 'CommandFailed', + 'DecommitInvalid', +]; + +/** + * Listen and send messages to a Hydra node. + */ +class HydraHandler { + private connection: Websocket; + private url: URL; + private isReady: boolean = false; + + /** + * @constructor + * @param url - The URL of the Hydra node WebSocket server. + * Initializes the HydraHandler class and sets up the WebSocket connection. + */ + constructor(url: string) { + const wsURL = new URL(url); + wsURL.protocol = wsURL.protocol.replace('http', 'ws'); + + this.url = wsURL; + this.connection = new Websocket(wsURL + '?history=no'); + this.setupEventHandlers(); + } + + private async ensureConnectionReady(): Promise { + if (!this.isReady) { + await new Promise((resolve) => (this.connection.onopen = resolve)); + } + } + + private setupEventHandlers() { + this.connection.onopen = () => { + console.debug('WebSocket connection opened.'); + this.isReady = true; + }; + + this.connection.onerror = () => { + console.error('Error on Hydra websocket'); + }; + + this.connection.onclose = () => { + console.debug('WebSocket connection closed.'); + this.isReady = false; + }; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private waitForMessage(tag: string, timeout = 10000): Promise { + return new Promise((resolve) => { + const timeoutId = setTimeout(() => { + resolve(`Timeout waiting for tag: ${tag}`); + }, timeout); + + this.connection.onmessage = (msg: Websocket.MessageEvent) => { + const data = JSON.parse(msg.data.toString()); + if (data.tag === tag) { + console.debug(`Received ${tag}`); + clearTimeout(timeoutId); + resolve(data); + } else if (ERROR_TAGS.includes(data.tag)) { + console.error(`Received ${data.tag}`); + } else { + console.debug(`Received ${data.tag} while waiting for ${tag}`); + } + }; + }); + } + + /** + * Listens for a specific tag from the Hydra node's WebSocket. + * + * @param tag - The tag to listen for in incoming messages. + * @returns the tag when it is received from the Hydra node. + */ + public async listen(tag: string): Promise { + return new Promise((resolve) => { + this.connection.onopen = () => { + console.debug(`Awaiting for ${tag} events...`); + }; + this.connection.onmessage = async (msg: Websocket.MessageEvent) => { + const data = JSON.parse(msg.data.toString()); + if (ERROR_TAGS.includes(data.tag)) { + console.error(`Received: ${data.tag}`); + resolve(data.tag); + } + console.debug(`Received: ${data.tag}`); + resolve(data.tag); + }; + }); + } + + /** + * Closes the WebSocket connection to the Hydra node. + * @returns A promise that resolves when the connection is closed. + */ + public async stop(): Promise { + return new Promise((resolve) => { + this.connection.close(); + resolve(); + }); + } + + /** + * Sends an "Init" message to the Hydra node to start a new head. + * @returns the tag "HeadIsInitializing" once the head is initialized. + */ + async init(): Promise { + await this.ensureConnectionReady(); + console.debug('Sending init command...'); + this.connection.send(JSON.stringify({ tag: 'Init' })); + return this.listen('HeadIsInitializing'); + } + + /** + * Sends an "Abort" message to the Hydra node to abort the initialization of a Hydra head. + * @returns the tag "HeadIsAborted" if the head was aborted successfully. + */ + async abort(): Promise { + await this.ensureConnectionReady(); + console.debug('Aborting head opening...'); + this.connection.send(JSON.stringify({ tag: 'Abort' })); + return new Promise(async (resolve) => { + const tag = await this.listen('HeadIsAborted'); + resolve(tag); + }).then(() => this.stop()); + } + + /** + * Sends a commit transaction to the Hydra node. + * @param apiUrl - The URL of the Hydra API endpoint. + * @param blueprint - The CBOR-encoded transaction blueprint. + * @param utxos - An array of the UTxOs to commit. + * @returns the transaction hash once the commit is successful. + */ + async sendCommit( + _apiUrl: string, + _utxos: UTxO[], + _blueprint?: CBORHex + ): Promise { + throw new Error('Not implemented'); + } + + /** + * Sends a raw transaction to the Hydra node. + * @param tx - The CBOR-encoded transaction to send. + * @returns the tag "TxValid" when the transaction is valid and "SnapshotConfirmed" when the snapshot is confirmed. + */ + async sendTx(tx: CBORHex): Promise { + await this.ensureConnectionReady(); + console.debug('Sending transaction...'); + this.connection.send( + JSON.stringify({ + tag: 'NewTx', + transaction: { cborHex: tx, description: '', type: 'Tx BabbageEra' }, + }) + ); + return this.listen('TxValid'); + } + + /** + * Retrieves the UTxO snapshot from the Hydra node. + * @returns an array of UTxOs from the snapshot. + */ + async getSnapshot(): Promise { + const apiURL = `${this.url.origin.replace('ws', 'http')}/snapshot/utxo`; + try { + const response = await axios.get(apiURL); + const hydraUtxos = Object.entries(response.data); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const lucidUtxos = hydraUtxos.map((utxo: any) => { + const [hash, idx] = utxo[0].split('#'); + const output = utxo[1]; + return hydraUtxoToLucidUtxo(hash, idx, output); + }); + return lucidUtxos; + } catch (error) { + console.debug(error as unknown as string); + throw error; + } + } + + /** + * Sends a decommit transaction to the Hydra node. + * @param apiUrl - The URL of the Hydra API endpoint. + * @param tx - The CBOR-encoded transaction to send for decommitment. + * @returns the response data from the Hydra node. + */ + async decommit(apiUrl: string, tx: CBORHex): Promise { + try { + const payload = { + cborHex: tx, + description: '', + type: 'Tx BabbageEra', + }; + const response = await axios.post(apiUrl, payload); + return response.data; + } catch (error) { + console.error(error as unknown as string); + throw error; + } + } + + /** + * Sends a "Close" message to the Hydra node to close the current head. + * @returns the tag "HeadIsClosed" once the head is closed successfully. + */ + async close(): Promise { + await this.ensureConnectionReady(); + console.debug('Closing head...'); + this.connection.send(JSON.stringify({ tag: 'Close' })); + const data = await this.waitForMessage('HeadIsClosed', 30_000); + return data.tag; + } + + /** + * Sends a "Fanout" message to the Hydra node to finalize the current head. + * @returns the tag "HeadIsFinalized" once the head is finalized. + */ + async fanout(): Promise { + await this.ensureConnectionReady(); + console.debug('Sending fanout command...'); + this.connection.send(JSON.stringify({ tag: 'Fanout' })); + return this.listen('HeadIsFinalized'); + } +} + +type HydraUtxo = { + address: string; + datum: string | null; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + inlineDatum: any; + inlineDatumhash: string | null; + referenceScript: { + script: { cborHex: string; description: string; type: string }; + scriptLanguage: string; + } | null; + value: Record>; +}; +function lucidUtxoToHydraUtxo(utxo: UTxO): HydraUtxo { + const address = utxo.address; + const value: Record> = {}; + // Probably needs fix for datums which are not inlined + const datum = null; + let inlineDatum = null; + let inlineDatumhash = null; + let referenceScript = null; + + for (const [unit, amount] of Object.entries(utxo.assets)) { + if (unit === 'lovelace') { + value['lovelace'] = Number(amount); + } else { + const fromU = fromUnit(unit); + const currentValue = + (value[fromU.policyId] as Record) || {}; + currentValue[fromU.assetName!] = Number(amount); + value[fromU.policyId] = currentValue; + } + } + if (utxo.datum) { + const plutusData = CML.PlutusData.from_cbor_hex(utxo.datum); + inlineDatum = JSON.parse( + CML.decode_plutus_datum_to_json_str( + plutusData, + CML.CardanoNodePlutusDatumSchema.DetailedSchema + ) + ); + inlineDatumhash = blake2b(32) + .update(Buffer.from(utxo.datum, 'hex')) + .digest('hex'); + } + if (utxo.scriptRef) { + let refinedScriptType; + /** + * Lucid ScriptType = Native | PlutusV1 | PlutusV2 | PlutusV3 + * Hydra ScriptType = PlutusScriptV3 | ... + */ + if (utxo.scriptRef.type.includes('Plutus')) { + refinedScriptType = utxo.scriptRef.type.replace('Plutus', 'PlutusScript'); + } else { + refinedScriptType = utxo.scriptRef.type; + } + referenceScript = { + script: { + cborHex: utxo.scriptRef.script, + description: '', + type: refinedScriptType, + }, + scriptLanguage: `PlutusScriptLanguage ${refinedScriptType}`, + }; + } + return { + address, + value, + datum, + inlineDatum, + inlineDatumhash, + referenceScript, + }; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function hydraUtxoToLucidUtxo(hash: string, idx: number, output: any): UTxO { + const datumBytes = output.inlineDatum ? output.inlineDatumRaw : null; + const assets: Assets = {}; + for (const [policy, value] of Object.entries(output.value)) { + if (policy === 'lovelace') { + assets[policy] = BigInt(value as number); + } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const namesAndAmounts: [string, number][] = Object.entries(value as any); + for (const [assetName, amount] of namesAndAmounts) { + const unit = `${policy}${assetName}`; + assets[unit] = BigInt(amount as number); + } + } + } + return { + txHash: hash, + outputIndex: Number(idx), + assets: assets, + address: output.address, + datum: datumBytes, + }; +} + +export { HydraHandler, lucidUtxoToHydraUtxo }; diff --git a/lazer/cardano/hermes/server/src/offchain/hydra/provider.ts b/lazer/cardano/hermes/server/src/offchain/hydra/provider.ts new file mode 100644 index 00000000..a9e6a486 --- /dev/null +++ b/lazer/cardano/hermes/server/src/offchain/hydra/provider.ts @@ -0,0 +1,123 @@ +import { Address, CML, OutRef, ProtocolParameters, Provider, Unit, UTxO, Credential, RewardAddress, Delegation, Datum, DatumHash, TxHash, Transaction, EvalRedeemer, credentialToAddress } from "@lucid-evolution/lucid"; +import { join } from 'path'; +import { HydraHandler } from './handler.js'; +import { readFileSync } from "fs"; + +// load and convert protocol parameters +const protocolParametersFromFile = JSON.parse(readFileSync(join(process.cwd(), '../infra/protocol-parameters.json'), 'utf8')); + +class HydraProvider implements Provider { + + constructor(private readonly hydra: HydraHandler) { + this.hydra = hydra; + } + + async getProtocolParameters(): Promise { + const protocolParameters: ProtocolParameters = { + minFeeA: protocolParametersFromFile.txFeeFixed, + minFeeB: protocolParametersFromFile.txFeePerByte, + maxTxSize: protocolParametersFromFile.maxTxSize, + maxValSize: protocolParametersFromFile.maxValueSize, + keyDeposit: BigInt(protocolParametersFromFile.stakeAddressDeposit), + poolDeposit: BigInt(protocolParametersFromFile.stakePoolDeposit), + drepDeposit: BigInt(protocolParametersFromFile.dRepDeposit), + govActionDeposit: BigInt(protocolParametersFromFile.govActionDeposit), + priceMem: protocolParametersFromFile.executionUnitPrices.priceMemory, + priceStep: protocolParametersFromFile.executionUnitPrices.priceSteps, + maxTxExMem: BigInt(protocolParametersFromFile.maxTxExecutionUnits.memory), + maxTxExSteps: BigInt(protocolParametersFromFile.maxTxExecutionUnits.steps), + coinsPerUtxoByte: BigInt(protocolParametersFromFile.utxoCostPerByte), + collateralPercentage: protocolParametersFromFile.collateralPercentage, + maxCollateralInputs: protocolParametersFromFile.maxCollateralInputs, + minFeeRefScriptCostPerByte: protocolParametersFromFile.minFeeRefScriptCostPerByte, + costModels: protocolParametersFromFile.costModels, + } + return protocolParameters; + } + + async getUtxos(addressOrCredential: Address | Credential): Promise { + const result: UTxO[] = []; + + const snapshotUTxOs = await this.hydra.getSnapshot(); + + if (typeof addressOrCredential === 'string') { + // Direct address string + snapshotUTxOs.forEach((utxo) => { + if (utxo.address === addressOrCredential) { + result.push(utxo); + } + }); + } else { + const credential = credentialToAddress("Custom", addressOrCredential); + console.info(`credential: ${credential}`); + console.info(snapshotUTxOs); + snapshotUTxOs.forEach((utxo) => { + if (utxo.address === credential) { + result.push(utxo); + } + }); + } + return result; + } + + async getUtxosWithUnit(addressOrCredential: Address | Credential, unit: Unit): Promise { + const result: UTxO[] = []; + const utxos = await this.getUtxos(addressOrCredential); + utxos.filter((utxo) => utxo.assets[unit] > 0n); + return result; + } + + async getUtxoByUnit(unit: Unit): Promise { + const utxos = await this.hydra.getSnapshot(); + const utxosWithUnit = utxos.filter((utxo) => utxo.assets[unit] > 0n); + if (utxosWithUnit.length !== 1) { + throw new Error(`UTxOs with unit ${unit} found: ${utxosWithUnit}`); + } + return utxosWithUnit[0]; + } + + async getUtxosByOutRef(outRefs: Array): Promise { + const utxos = await this.hydra.getSnapshot(); + return utxos.filter((utxo) => outRefs.some( + (outRef) => + outRef.txHash === utxo.txHash + && outRef.outputIndex === utxo.outputIndex + ), + ); + } + + async getDelegation(_rewardAddress: RewardAddress): Promise { + throw new Error('Not implemented'); + } + + async getDatum(_datumHash: DatumHash): Promise { + throw new Error('Not implemented'); + } + + async awaitTx(txHash: TxHash, checkInterval: number = 5000): Promise { + console.info(`Waiting for ${checkInterval} milliseconds`); + let snapshot = await this.hydra.getSnapshot(); + while (!snapshot.some((utxo) => utxo.txHash === txHash)) { + await new Promise(resolve => setTimeout(resolve, checkInterval)); + snapshot = await this.hydra.getSnapshot(); + } + return true; + } + + async submitTx(tx: Transaction): Promise { + const txValidity = await this.hydra.sendTx(tx); + if (txValidity === 'TxValid') { + // calculate tx hash + const cmlTx = CML.Transaction.from_cbor_hex(tx) + const txHash = CML.hash_transaction(cmlTx.body()); + return txHash.to_hex(); + } + throw new Error('Transaction not valid'); + } + + async evaluateTx(_tx: Transaction, _additionalUTxOs?: UTxO[]): Promise { + throw new Error('Not implemented'); + } +} + +export { HydraProvider }; diff --git a/lazer/cardano/hermes/server/src/offchain/index.ts b/lazer/cardano/hermes/server/src/offchain/index.ts new file mode 100644 index 00000000..1e9653d5 --- /dev/null +++ b/lazer/cardano/hermes/server/src/offchain/index.ts @@ -0,0 +1,3 @@ +export * from "./orders.js"; +export * from "./market.js"; +export * from "./claims.js"; diff --git a/lazer/cardano/hermes/server/src/offchain/market.ts b/lazer/cardano/hermes/server/src/offchain/market.ts new file mode 100644 index 00000000..7b79d1e9 --- /dev/null +++ b/lazer/cardano/hermes/server/src/offchain/market.ts @@ -0,0 +1,49 @@ +import BigNumber from "bignumber.js"; +import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk"; +import { createMarket as _createMarket } from "../market.js"; +import type { Market } from "../types.js"; + +const BTC_FEED_ID = 1; + +async function fetchBtcPrice(): Promise { + const token = process.env["PYTH_ACCESS_TOKEN"]; + if (!token) + throw new Error("[offchain/market] PYTH_ACCESS_TOKEN env var is required"); + + const client = await PythLazerClient.create({ + token, + webSocketPoolConfig: {}, + }); + try { + const update = await client.getLatestPrice({ + priceFeedIds: [BTC_FEED_ID], + properties: ["price", "exponent"], + formats: [], + channel: "fixed_rate@200ms", + }); + const feed = update.parsed?.priceFeeds?.[0]; + if (feed?.price === undefined || feed.exponent === undefined) { + throw new Error("[offchain/market] no price data returned from Pyth"); + } + return new BigNumber(feed.price).shiftedBy(feed.exponent).toNumber(); + } finally { + client.shutdown(); + } +} + +// ── MOCK ────────────────────────────────────────────────────────────────────── +let currentMarket: Market | undefined; + +export async function createMarket(): Promise { + const strikePrice = await fetchBtcPrice(); + currentMarket = _createMarket(strikePrice); + console.log( + `[offchain/market] created market ${currentMarket.id} strikePrice=${strikePrice}`, + ); + return currentMarket; +} + +export function getCurrentMarket(): Market | undefined { + return currentMarket; +} +// ── END MOCK ────────────────────────────────────────────────────────────────── diff --git a/lazer/cardano/hermes/server/src/offchain/orders.ts b/lazer/cardano/hermes/server/src/offchain/orders.ts new file mode 100644 index 00000000..3ce0b9fc --- /dev/null +++ b/lazer/cardano/hermes/server/src/offchain/orders.ts @@ -0,0 +1,53 @@ +import type { Action, Order, Side } from "../types.js"; + +// TODO: Replace every function body with smart contract calls, e.g.: +// +// import { ethers } from "ethers" +// const contract = new ethers.Contract(ORDERBOOK_ADDRESS, ABI, signer) +// +// export async function createOrder(...): Promise { +// const tx = await contract.placeOrder(side, action, price, quantity) +// await tx.wait() +// return fetchOrderFromChain(tx) +// } +// +// export async function getOpenOrders(): Promise { +// return contract.getOpenOrders() +// } +// +// export async function removeOrder(id: string): Promise { +// // handled on-chain when orders are matched; no separate removal needed +// } + +// ── MOCK ────────────────────────────────────────────────────────────────────── +const store = new Map(); + +export function createOrder( + side: Side, + action: Action, + price: number, + quantity: number, + ownerAddress: string, +): Order { + const order: Order = { + id: crypto.randomUUID(), + timestamp: Date.now(), + side, + action, + price, + quantity, + ownerAddress, + }; + store.set(order.id, order); + return order; +} + +export function getOpenOrders(): Order[] { + // MOCK: returns the in-memory store (empty until createOrder is called) + return [...store.values()]; +} + +export function removeOrder(id: string): void { + store.delete(id); +} +// ── END MOCK ────────────────────────────────────────────────────────────────── diff --git a/lazer/cardano/hermes/server/src/rest.ts b/lazer/cardano/hermes/server/src/rest.ts new file mode 100644 index 00000000..58009606 --- /dev/null +++ b/lazer/cardano/hermes/server/src/rest.ts @@ -0,0 +1,116 @@ +import type { IncomingMessage, ServerResponse } from "node:http"; +import type { + MarketHistoryEntry, + MarketOutcome, + Side, + UserPosition, +} from "./types.js"; + +// TODO: Replace getMockHistory() with real blockchain reads: +// +// import { ethers } from "ethers" +// +// const CONTRACT_ADDRESS = "0x..." // TODO: deployed market factory address +// const ABI = [...] // TODO: contract ABI +// const provider = new ethers.JsonRpcProvider("https://your-rpc-url") +// const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider) +// +// async function getHistory(address: string): Promise { +// const marketCount = await contract.marketCount() +// const entries: MarketHistoryEntry[] = [] +// for (let i = Number(marketCount) - 1; i >= 0; i--) { +// const market = await contract.markets(i) +// const pos = address ? await contract.positionOf(i, address) : null +// entries.push({ +// marketId: i.toString(), +// startTime: Number(market.startTime) * 1000, +// endTime: Number(market.endTime) * 1000, +// strikePrice: Number(market.strikePrice) / 1e18, +// finalBtcPrice: Number(market.finalPrice) / 1e18, +// outcome: Number(market.finalPrice) > Number(market.strikePrice) ? "UP" : "DOWN", +// userPosition: pos && Number(pos.quantity) > 0 ? { +// side: Number(pos.side) === 0 ? "UP" : "DOWN", +// quantity: Number(pos.quantity), +// avgPrice: Number(pos.avgPrice) / 1e18, +// result: /* derive from outcome vs side */, +// pnl: /* derive from result */, +// } : null, +// }) +// } +// return entries +// } + +const STRIKE = 67_500; +const MARKET_DURATION_MS = 5 * 60 * 1000; + +// Stable mock final prices — alternating above/below strike +const MOCK_FINALS = [67_820, 67_210, 68_100, 66_950, 67_640]; + +// Markets where the user has a position (by index into the 5-entry list) +const USER_POSITION_INDICES = new Set([0, 2, 3]); + +function buildUserPosition( + index: number, + outcome: MarketOutcome, + address: string, +): UserPosition | null { + if (!address || !USER_POSITION_INDICES.has(index)) return null; + + // Mock: user always bet UP in markets 0 and 2, DOWN in market 3 + const side: Side = index === 3 ? "DOWN" : "UP"; + const quantity = (index + 1) * 50; + const avgPrice = 0.48 + index * 0.02; + const won = side === outcome; + const pnl = won + ? Math.round(quantity * (1 - avgPrice) * 100) / 100 + : Math.round(-quantity * avgPrice * 100) / 100; + + return { + side, + quantity, + avgPrice, + result: won ? "WON" : "LOST", + pnl, + }; +} + +function getMockHistory(address: string): MarketHistoryEntry[] { + const now = Date.now(); + return MOCK_FINALS.map((finalBtcPrice, i) => { + const endTime = now - i * MARKET_DURATION_MS; + const startTime = endTime - MARKET_DURATION_MS; + const outcome: MarketOutcome = finalBtcPrice > STRIKE ? "UP" : "DOWN"; + return { + marketId: `mock-market-${5 - i}`, + startTime, + endTime, + strikePrice: STRIKE, + finalBtcPrice, + outcome, + userPosition: buildUserPosition(i, outcome, address), + }; + }); +} + +function setCors(res: ServerResponse): void { + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Content-Type", "application/json"); +} + +export function handleRestRequest( + req: IncomingMessage, + res: ServerResponse, +): void { + const url = new URL(req.url ?? "/", "http://localhost"); + + if (req.method === "GET" && url.pathname === "/api/markets/history") { + const address = url.searchParams.get("address") ?? ""; + setCors(res); + res.writeHead(200); + res.end(JSON.stringify(getMockHistory(address))); + return; + } + + res.writeHead(404); + res.end(JSON.stringify({ error: "not found" })); +} diff --git a/lazer/cardano/hermes/server/src/streams/btcPrice.ts b/lazer/cardano/hermes/server/src/streams/btcPrice.ts new file mode 100644 index 00000000..5a9789ac --- /dev/null +++ b/lazer/cardano/hermes/server/src/streams/btcPrice.ts @@ -0,0 +1,72 @@ +import { EventEmitter } from "node:events"; +import BigNumber from "bignumber.js"; +import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk"; +import type { PriceTick } from "../types.js"; + +const BTC_FEED_ID = 1; + +interface CurrentPrice { + raw: string; + exponent: number; + num: number; // pre-computed float, used by the mock orderbook +} + +export async function createBtcPriceStream(): Promise<{ + emitter: EventEmitter; + getPrice: () => number | undefined; +}> { + const token = process.env["PYTH_ACCESS_TOKEN"]; + if (!token) + throw new Error("[btcPrice] PYTH_ACCESS_TOKEN env var is required"); + + const emitter = new EventEmitter(); + let current: CurrentPrice | undefined; + + // TODO: Once the settlement contract is wired, switch to a verified feed: + // formats: ["evm"], deliveryFormat: "binary" + // and pass the signed payload to the contract for on-chain price validation. + const client = await PythLazerClient.create({ + token, + webSocketPoolConfig: {}, + }); + + client.subscribe({ + type: "subscribe", + subscriptionId: 1, + priceFeedIds: [BTC_FEED_ID], + properties: ["price", "exponent", "feedUpdateTimestamp"], + formats: [], + deliveryFormat: "json", + channel: "fixed_rate@200ms", + }); + + client.addMessageListener((event) => { + if (event.type !== "json") return; + if (event.value.type !== "streamUpdated") return; + const feed = event.value.parsed?.priceFeeds?.[0]; + if ( + feed?.price === undefined || + feed.exponent === undefined || + feed.feedUpdateTimestamp === undefined + ) + return; + + const bn = new BigNumber(feed.price).shiftedBy(feed.exponent); + current = { + raw: feed.price, + exponent: feed.exponent, + num: bn.toNumber(), + }; + + const tick: PriceTick = { + timestamp: feed.feedUpdateTimestamp / 1000, // µs → ms + btcPriceStr: bn.toFixed(2), + btcPriceRaw: feed.price, + exponent: feed.exponent, + }; + emitter.emit("tick", tick); + }); + + console.log("[btcPrice] Pyth Lazer connected, subscribed to BTC/USD feed"); + return { emitter, getPrice: () => current?.num }; +} diff --git a/lazer/cardano/hermes/server/src/streams/orderbook.ts b/lazer/cardano/hermes/server/src/streams/orderbook.ts new file mode 100644 index 00000000..3793eae1 --- /dev/null +++ b/lazer/cardano/hermes/server/src/streams/orderbook.ts @@ -0,0 +1,72 @@ +import { EventEmitter } from "node:events"; +import type { Action, Order, Side } from "../types.js"; + +// TODO: Replace the mock below with real smart contract events. +// +// The Orderbook contract emits an "OrderPlaced" event whenever a new limit +// order is submitted on-chain. Subscribe using ethers.js or viem: +// +// import { ethers } from "ethers" +// +// const ORDERBOOK_ADDRESS = "0x..." // TODO: fill in deployed contract address +// const ABI = [...] // TODO: fill in contract ABI (at minimum the OrderPlaced event) +// +// const provider = new ethers.WebSocketProvider("wss://your-rpc-url") +// const contract = new ethers.Contract(ORDERBOOK_ADDRESS, ABI, provider) +// +// contract.on("OrderPlaced", (id, owner, side, action, price, qty, ts) => { +// const order: Order = { +// id: id.toString(), +// timestamp: Number(ts) * 1000, // contract emits unix seconds +// side: side === 0n ? "UP" : "DOWN", +// action: action === 0n ? "BUY" : "SELL", +// price: Number(price) / 1e18, // contract stores as uint256 wei-scaled +// quantity: Number(qty), +// ownerAddress: owner, +// } +// emitter.emit("order", order) +// }) +// +// Remove the MOCK block below once the real subscription is wired in. + +const ADDRESS_POOL = Array.from({ length: 10 }, (_, i) => `addr_${i + 1}`); +const STRIKE = 67_500; +const INTERVAL_MS = 300; + +function clamp(v: number, lo: number, hi: number): number { + return Math.min(hi, Math.max(lo, v)); +} + +export function createOrderbookStream(getBtcPrice: () => number | undefined): { + emitter: EventEmitter; + getLatestOrder: () => Order | null; +} { + const emitter = new EventEmitter(); + let latestOrder: Order | null = null; + + // ── MOCK: remove once real contract events are wired in ─────────────────── + setInterval(() => { + const btcPrice = getBtcPrice(); + if (btcPrice === undefined) return; // wait for first Pyth tick + const side: Side = Math.random() > 0.5 ? "UP" : "DOWN"; + const action: Action = Math.random() > 0.5 ? "BUY" : "SELL"; + const baseUpProb = clamp(0.5 + (btcPrice - STRIKE) / 10_000, 0.05, 0.95); + const ref = side === "UP" ? baseUpProb : 1 - baseUpProb; + const price = clamp(ref + (Math.random() - 0.5) * 0.06, 0.01, 0.99); + const order: Order = { + id: crypto.randomUUID(), + timestamp: Date.now(), + side, + action, + price, + quantity: Math.floor(Math.random() * 500) + 1, + ownerAddress: + ADDRESS_POOL[Math.floor(Math.random() * ADDRESS_POOL.length)], + }; + latestOrder = order; + emitter.emit("order", order); + }, INTERVAL_MS); + // ── END MOCK ────────────────────────────────────────────────────────────── + + return { emitter, getLatestOrder: () => latestOrder }; +} diff --git a/lazer/cardano/hermes/server/src/streams/positions.ts b/lazer/cardano/hermes/server/src/streams/positions.ts new file mode 100644 index 00000000..6314090a --- /dev/null +++ b/lazer/cardano/hermes/server/src/streams/positions.ts @@ -0,0 +1,57 @@ +import { EventEmitter } from "node:events"; +import type { Fill, Order } from "../types.js"; + +// TODO: Replace the mock below with real smart contract events. +// +// The Market (settlement) contract emits an "OrderFilled" event when two +// orders are matched on-chain. Subscribe using ethers.js or viem: +// +// import { ethers } from "ethers" +// +// const MARKET_ADDRESS = "0x..." // TODO: fill in deployed contract address +// const ABI = [...] // TODO: fill in contract ABI (at minimum the OrderFilled event) +// +// const provider = new ethers.WebSocketProvider("wss://your-rpc-url") +// const contract = new ethers.Contract(MARKET_ADDRESS, ABI, provider) +// +// contract.on("OrderFilled", (id, owner, side, qty, price, ts) => { +// const fill: Fill = { +// id: id.toString(), +// timestamp: Number(ts) * 1000, // contract emits unix seconds +// side: side === 0n ? "UP" : "DOWN", +// quantity: Number(qty), +// price: Number(price) / 1e18, // uint256 wei-scaled +// ownerAddress: owner, +// } +// emitter.emit("fill", fill) +// }) +// +// Remove the MOCK block below once the real subscription is wired in. + +const ADDRESS_POOL = Array.from({ length: 10 }, (_, i) => `addr_${i + 1}`); +const INTERVAL_MS = 800; + +export function createPositionsStream( + getLatestOrder: () => Order | null, +): EventEmitter { + const emitter = new EventEmitter(); + + // ── MOCK: remove once real contract events are wired in ─────────────────── + setInterval(() => { + const latest = getLatestOrder(); + if (!latest) return; + const fill: Fill = { + id: crypto.randomUUID(), + timestamp: Date.now(), + side: latest.side, + quantity: Math.floor(latest.quantity * (0.3 + Math.random() * 0.7)), + price: latest.price, + ownerAddress: + ADDRESS_POOL[Math.floor(Math.random() * ADDRESS_POOL.length)], + }; + emitter.emit("fill", fill); + }, INTERVAL_MS); + // ── END MOCK ────────────────────────────────────────────────────────────── + + return emitter; +} diff --git a/lazer/cardano/hermes/server/src/types.ts b/lazer/cardano/hermes/server/src/types.ts new file mode 100644 index 00000000..d9b69596 --- /dev/null +++ b/lazer/cardano/hermes/server/src/types.ts @@ -0,0 +1,91 @@ +export interface Market { + id: string; // crypto.randomUUID() — future: on-chain market ID (uint256) + startTime: number; // ms timestamp — future: from block.timestamp at creation + endTime: number; // ms timestamp — future: startTime + duration from contract + strikePrice: number; // future: read from contract's stored strike at creation +} + +export type Side = "UP" | "DOWN"; +export type Action = "BUY" | "SELL"; +export type MarketOutcome = "UP" | "DOWN"; +export type UserResult = "WON" | "LOST"; + +export interface UserPosition { + side: Side; + quantity: number; + avgPrice: number; // price paid per share (0–1) + result: UserResult; + pnl: number; // quantity*(1-avgPrice) if won, -quantity*avgPrice if lost +} + +export interface MarketHistoryEntry { + marketId: string; + startTime: number; // ms + endTime: number; // ms + strikePrice: number; + finalBtcPrice: number; + outcome: MarketOutcome; // which side won + userPosition: UserPosition | null; // null if address had no shares +} + +export interface PriceTick { + timestamp: number; + btcPriceStr: string; // display-ready decimal string, e.g. "67543.21" (BigNumber-computed) + btcPriceRaw: string; // raw Pyth integer string, e.g. "6754321000000" + exponent: number; // e.g. -8; actual = btcPriceRaw * 10^exponent +} + +export interface Order { + id: string; + timestamp: number; + side: Side; + action: Action; + price: number; // 0–1 probability price of the bet position + quantity: number; + ownerAddress: string; // plain string; format determined by backend/wallet +} + +export interface Fill { + id: string; + timestamp: number; + side: Side; + quantity: number; + price: number; + ownerAddress: string; +} + +export interface PositionSummary { + upContracts: number; + upAvgPrice: number; + downContracts: number; + downAvgPrice: number; +} + +export interface RollingAverages { + upBuyAvg: number; + upSellAvg: number; + downBuyAvg: number; + downSellAvg: number; +} + +// ── Server → Client ─────────────────────────────────────────────────────────── + +export type ServerMessage = + | { type: "connected"; data: { market: Market } } + | { type: "market_started"; data: { market: Market } } + | { type: "price_tick"; data: PriceTick } + | { type: "order"; data: Order } + | { type: "fill"; data: Fill } + | { type: "position_summary"; data: PositionSummary } + | { type: "rolling_averages"; data: RollingAverages }; + +// ── Client → Server ─────────────────────────────────────────────────────────── + +export interface PlaceOrderPayload { + side: Side; + action: Action; + price: number; + quantity: number; +} + +export type ClientMessage = { type: "place_order"; data: PlaceOrderPayload }; diff --git a/lazer/cardano/hermes/server/tsconfig.json b/lazer/cardano/hermes/server/tsconfig.json new file mode 100644 index 00000000..574c1991 --- /dev/null +++ b/lazer/cardano/hermes/server/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": ["src"] +} diff --git a/lazer/cardano/hermes/ui/.gitignore b/lazer/cardano/hermes/ui/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/lazer/cardano/hermes/ui/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/lazer/cardano/hermes/ui/.prettierignore b/lazer/cardano/hermes/ui/.prettierignore new file mode 100644 index 00000000..0b4a1db4 --- /dev/null +++ b/lazer/cardano/hermes/ui/.prettierignore @@ -0,0 +1,7 @@ +node_modules/ +coverage/ +.pnpm-store/ +pnpm-lock.yaml +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/lazer/cardano/hermes/ui/.prettierrc b/lazer/cardano/hermes/ui/.prettierrc new file mode 100644 index 00000000..9000bfaa --- /dev/null +++ b/lazer/cardano/hermes/ui/.prettierrc @@ -0,0 +1,11 @@ +{ + "endOfLine": "lf", + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 80, + "plugins": ["prettier-plugin-tailwindcss"], + "tailwindStylesheet": "src/index.css", + "tailwindFunctions": ["cn", "cva"] +} diff --git a/lazer/cardano/hermes/ui/README.md b/lazer/cardano/hermes/ui/README.md new file mode 100644 index 00000000..811328a4 --- /dev/null +++ b/lazer/cardano/hermes/ui/README.md @@ -0,0 +1,21 @@ +# React + TypeScript + Vite + shadcn/ui + +This is a template for a new Vite project with React, TypeScript, and shadcn/ui. + +## Adding components + +To add components to your app, run the following command: + +```bash +npx shadcn@latest add button +``` + +This will place the ui components in the `src/components` directory. + +## Using components + +To use the components in your app, import them as follows: + +```tsx +import { Button } from "@/components/ui/button" +``` diff --git a/lazer/cardano/hermes/ui/components.json b/lazer/cardano/hermes/ui/components.json new file mode 100644 index 00000000..5c23ec49 --- /dev/null +++ b/lazer/cardano/hermes/ui/components.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "radix-nova", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/index.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "rtl": false, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "menuColor": "default", + "menuAccent": "subtle", + "registries": {} +} diff --git a/lazer/cardano/hermes/ui/eslint.config.js b/lazer/cardano/hermes/ui/eslint.config.js new file mode 100644 index 00000000..5e6b472f --- /dev/null +++ b/lazer/cardano/hermes/ui/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/lazer/cardano/hermes/ui/index.html b/lazer/cardano/hermes/ui/index.html new file mode 100644 index 00000000..1f738fe7 --- /dev/null +++ b/lazer/cardano/hermes/ui/index.html @@ -0,0 +1,13 @@ + + + + + + + vite-app + + +
+ + + diff --git a/lazer/cardano/hermes/ui/package.json b/lazer/cardano/hermes/ui/package.json new file mode 100644 index 00000000..75262eab --- /dev/null +++ b/lazer/cardano/hermes/ui/package.json @@ -0,0 +1,47 @@ +{ + "name": "hermes", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "format": "prettier --write \"**/*.{ts,tsx}\"", + "typecheck": "tsc --noEmit", + "preview": "vite preview" + }, + "dependencies": { + "@fontsource-variable/geist": "^5.2.8", + "@tailwindcss/vite": "^4.2.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "dotenv": "^17.3.1", + "lucide-react": "^0.577.0", + "radix-ui": "^1.4.3", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "react-router-dom": "^7.13.1", + "recharts": "^3.8.0", + "shadcn": "^4.1.0", + "tailwind-merge": "^3.5.0", + "tailwindcss": "^4.2.1", + "tw-animate-css": "^1.4.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.4", + "@types/node": "^24.12.0", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.2.0", + "eslint": "^9.39.4", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.5.2", + "globals": "^16.5.0", + "prettier": "^3.8.1", + "prettier-plugin-tailwindcss": "^0.7.2", + "typescript": "~5.9.3", + "typescript-eslint": "^8.57.1", + "vite": "^7.3.1" + } +} diff --git a/lazer/cardano/hermes/ui/pnpm-lock.yaml b/lazer/cardano/hermes/ui/pnpm-lock.yaml new file mode 100644 index 00000000..bb0ef69b --- /dev/null +++ b/lazer/cardano/hermes/ui/pnpm-lock.yaml @@ -0,0 +1,6723 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@fontsource-variable/geist': + specifier: ^5.2.8 + version: 5.2.8 + '@tailwindcss/vite': + specifier: ^4.2.1 + version: 4.2.2(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)) + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + dotenv: + specifier: ^17.3.1 + version: 17.3.1 + lucide-react: + specifier: ^0.577.0 + version: 0.577.0(react@19.2.4) + radix-ui: + specifier: ^1.4.3 + version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: + specifier: ^19.2.4 + version: 19.2.4 + react-dom: + specifier: ^19.2.4 + version: 19.2.4(react@19.2.4) + react-router-dom: + specifier: ^7.13.1 + version: 7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + recharts: + specifier: ^3.8.0 + version: 3.8.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.4)(react@19.2.4)(redux@5.0.1) + shadcn: + specifier: ^4.1.0 + version: 4.1.0(@types/node@24.12.0)(typescript@5.9.3) + tailwind-merge: + specifier: ^3.5.0 + version: 3.5.0 + tailwindcss: + specifier: ^4.2.1 + version: 4.2.2 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 + devDependencies: + '@eslint/js': + specifier: ^9.39.4 + version: 9.39.4 + '@types/node': + specifier: ^24.12.0 + version: 24.12.0 + '@types/react': + specifier: ^19.2.14 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: ^5.2.0 + version: 5.2.0(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)) + eslint: + specifier: ^9.39.4 + version: 9.39.4(jiti@2.6.1) + eslint-plugin-react-hooks: + specifier: ^7.0.1 + version: 7.0.1(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-react-refresh: + specifier: ^0.5.2 + version: 0.5.2(eslint@9.39.4(jiti@2.6.1)) + globals: + specifier: ^16.5.0 + version: 16.5.0 + prettier: + specifier: ^3.8.1 + version: 3.8.1 + prettier-plugin-tailwindcss: + specifier: ^0.7.2 + version: 0.7.2(prettier@3.8.1) + typescript: + specifier: ~5.9.3 + version: 5.9.3 + typescript-eslint: + specifier: ^8.57.1 + version: 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + vite: + specifier: ^7.3.1 + version: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0) + +packages: + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.28.6': + resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.28.6': + resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.28.6': + resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.6': + resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.28.5': + resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@dotenvx/dotenvx@1.57.1': + resolution: {integrity: sha512-iKXuo8Nes9Ft4zF3AZOT4FHkl6OV8bHqn61a67qHokkBzSEurnKZAlOkT0FYrRNVGvE6nCfZMtYswyjfXCR1MQ==} + hasBin: true + + '@ecies/ciphers@0.2.5': + resolution: {integrity: sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==} + engines: {bun: '>=1', deno: '>=2', node: '>=16'} + peerDependencies: + '@noble/ciphers': ^1.0.0 + + '@esbuild/aix-ppc64@0.27.4': + resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.4': + resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.4': + resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.4': + resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.4': + resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.4': + resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.4': + resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.4': + resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.4': + resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.4': + resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.4': + resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.4': + resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.4': + resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.4': + resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.4': + resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.4': + resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.4': + resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.4': + resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.4': + resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.4': + resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.4': + resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.4': + resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.4': + resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.4': + resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.4': + resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.4': + resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.7.5': + resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} + + '@floating-ui/dom@1.7.6': + resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} + + '@floating-ui/react-dom@2.1.8': + resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.11': + resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + + '@fontsource-variable/geist@5.2.8': + resolution: {integrity: sha512-cJ6m9e+8MQ5dCYJsLylfZrgBh6KkG4bOLckB35Tr9J/EqdkEM6QllH5PxqP1dhTvFup+HtMRPuz9xOjxXJggxw==} + + '@hono/node-server@1.19.11': + resolution: {integrity: sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@modelcontextprotocol/sdk@1.27.1': + resolution: {integrity: sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + + '@mswjs/interceptors@0.41.3': + resolution: {integrity: sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==} + engines: {node: '>=18'} + + '@noble/ciphers@1.3.0': + resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@open-draft/logger@0.3.0': + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + + '@open-draft/until@2.1.0': + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + + '@radix-ui/number@1.1.1': + resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} + + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + + '@radix-ui/react-accessible-icon@1.1.7': + resolution: {integrity: sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-accordion@1.2.12': + resolution: {integrity: sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-alert-dialog@1.1.15': + resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-aspect-ratio@1.1.7': + resolution: {integrity: sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-avatar@1.1.10': + resolution: {integrity: sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-checkbox@1.3.3': + resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collapsible@1.1.12': + resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context-menu@2.2.16': + resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.15': + resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-form@0.1.8': + resolution: {integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-hover-card@1.1.15': + resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-label@2.1.7': + resolution: {integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-menubar@1.1.16': + resolution: {integrity: sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-navigation-menu@1.2.14': + resolution: {integrity: sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-one-time-password-field@0.1.8': + resolution: {integrity: sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-password-toggle-field@0.1.3': + resolution: {integrity: sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popover@1.1.15': + resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-progress@1.1.7': + resolution: {integrity: sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-radio-group@1.3.8': + resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-scroll-area@1.2.10': + resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-select@2.2.6': + resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-separator@1.1.7': + resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slider@1.3.6': + resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-switch@1.2.6': + resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tabs@1.1.13': + resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toast@1.2.15': + resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toggle-group@1.1.11': + resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toggle@1.1.10': + resolution: {integrity: sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toolbar@1.1.11': + resolution: {integrity: sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tooltip@1.2.8': + resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-is-hydrated@0.1.0': + resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-previous@1.1.1': + resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-visually-hidden@1.2.3': + resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + + '@reduxjs/toolkit@2.11.2': + resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} + peerDependencies: + react: ^16.9.0 || ^17.0.0 || ^18 || ^19 + react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + + '@rollup/rollup-android-arm-eabi@4.60.0': + resolution: {integrity: sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.60.0': + resolution: {integrity: sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.60.0': + resolution: {integrity: sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.60.0': + resolution: {integrity: sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.0': + resolution: {integrity: sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.0': + resolution: {integrity: sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.0': + resolution: {integrity: sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.60.0': + resolution: {integrity: sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.60.0': + resolution: {integrity: sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.60.0': + resolution: {integrity: sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.60.0': + resolution: {integrity: sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.60.0': + resolution: {integrity: sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.60.0': + resolution: {integrity: sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.60.0': + resolution: {integrity: sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.60.0': + resolution: {integrity: sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.60.0': + resolution: {integrity: sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.60.0': + resolution: {integrity: sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.60.0': + resolution: {integrity: sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.60.0': + resolution: {integrity: sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.60.0': + resolution: {integrity: sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.0': + resolution: {integrity: sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.0': + resolution: {integrity: sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.0': + resolution: {integrity: sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.0': + resolution: {integrity: sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.0': + resolution: {integrity: sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==} + cpu: [x64] + os: [win32] + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@standard-schema/utils@0.3.0': + resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} + + '@tailwindcss/node@4.2.2': + resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} + + '@tailwindcss/oxide-android-arm64@4.2.2': + resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.2.2': + resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.2.2': + resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.2.2': + resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.2.2': + resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.2.2': + resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.2.2': + resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.2.2': + resolution: {integrity: sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + + '@ts-morph/common@0.27.0': + resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@24.12.0': + resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + + '@types/statuses@2.0.6': + resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} + + '@types/use-sync-external-store@0.0.6': + resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} + + '@types/validate-npm-package-name@4.0.2': + resolution: {integrity: sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==} + + '@typescript-eslint/eslint-plugin@8.57.1': + resolution: {integrity: sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.57.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.57.1': + resolution: {integrity: sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.57.1': + resolution: {integrity: sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.57.1': + resolution: {integrity: sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.57.1': + resolution: {integrity: sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.57.1': + resolution: {integrity: sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.57.1': + resolution: {integrity: sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.57.1': + resolution: {integrity: sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.57.1': + resolution: {integrity: sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.57.1': + resolution: {integrity: sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitejs/plugin-react@5.2.0': + resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.10.10: + resolution: {integrity: sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + body-parser@2.2.2: + resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} + engines: {node: '>=18'} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001780: + resolution: {integrity: sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + code-block-writer@13.0.3: + resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + content-disposition@1.0.1: + resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js-light@2.5.1: + resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + + dedent@1.7.2: + resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + diff@8.0.3: + resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + engines: {node: '>=0.3.1'} + + dotenv@17.3.1: + resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eciesjs@0.4.18: + resolution: {integrity: sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==} + engines: {bun: '>=1', deno: '>=2', node: '>=16'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.321: + resolution: {integrity: sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + enhanced-resolve@5.20.1: + resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} + engines: {node: '>=10.13.0'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-toolkit@1.45.1: + resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} + + esbuild@0.27.4: + resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-plugin-react-hooks@7.0.1: + resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-refresh@0.5.2: + resolution: {integrity: sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==} + peerDependencies: + eslint: ^9 || ^10 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + eventsource-parser@3.0.6: + resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@9.6.1: + resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} + engines: {node: ^18.19.0 || >=20.5.0} + + express-rate-limit@8.3.1: + resolution: {integrity: sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + fuzzysort@3.1.0: + resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + get-own-enumerable-keys@1.0.0: + resolution: {integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==} + engines: {node: '>=14.16'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphql@16.13.1: + resolution: {integrity: sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + hono@4.12.8: + resolution: {integrity: sha512-VJCEvtrezO1IAR+kqEYnxUOoStaQPGrCmX3j4wDTNOcD1uRPFpGlwQUIW8niPuvHXaTUxeOUl5MMDGrl+tmO9A==} + engines: {node: '>=16.9.0'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + immer@10.2.0: + resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} + + immer@11.1.4: + resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-in-ssh@1.0.0: + resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} + engines: {node: '>=20'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@3.0.0: + resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} + engines: {node: '>=12'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + is-regexp@3.1.0: + resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} + engines: {node: '>=12'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@3.1.5: + resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} + engines: {node: '>=18'} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + jose@6.2.2: + resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lucide-react@0.577.0: + resolution: {integrity: sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + msw@2.12.14: + resolution: {integrity: sha512-4KXa4nVBIBjbDbd7vfQNuQ25eFxug0aropCQFoI0JdOBuJWamkT1yLVIWReFI8SiTRc+H1hKzaNk+cLk2N9rtQ==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-releases@2.0.36: + resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-treeify@1.1.33: + resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} + engines: {node: '>= 10'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + open@11.0.0: + resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} + engines: {node: '>=20'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + + path-to-regexp@8.3.0: + resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + engines: {node: '>=4'} + + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + engines: {node: ^10 || ^12 || >=14} + + powershell-utils@0.1.0: + resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} + engines: {node: '>=20'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-plugin-tailwindcss@0.7.2: + resolution: {integrity: sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==} + engines: {node: '>=20.19'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-hermes': '*' + '@prettier/plugin-oxc': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-hermes': + optional: true + '@prettier/plugin-oxc': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + + pretty-ms@9.3.0: + resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + engines: {node: '>=18'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.15.0: + resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + radix-ui@1.4.3: + resolution: {integrity: sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + peerDependencies: + react: ^19.2.4 + + react-is@19.2.4: + resolution: {integrity: sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==} + + react-redux@9.2.0: + resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} + peerDependencies: + '@types/react': ^18.2.25 || ^19 + react: ^18.0 || ^19 + redux: ^5.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + redux: + optional: true + + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-router-dom@7.13.1: + resolution: {integrity: sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.13.1: + resolution: {integrity: sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@19.2.4: + resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + engines: {node: '>=0.10.0'} + + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + + recharts@3.8.0: + resolution: {integrity: sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ==} + engines: {node: '>=18'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + redux-thunk@3.1.0: + resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} + peerDependencies: + redux: ^5.0.0 + + redux@5.0.1: + resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + reselect@5.1.1: + resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + rettime@0.10.1: + resolution: {integrity: sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.60.0: + resolution: {integrity: sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shadcn@4.1.0: + resolution: {integrity: sha512-3zETJ+0Ezj69FS6RL0HOkLKKAR5yXisXx1iISJdfLQfrUqj/VIQlanQi1Ukk+9OE+XHZVj4FQNTBSfbr2CyCYg==} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + stringify-object@5.0.0: + resolution: {integrity: sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==} + engines: {node: '>=14.16'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + tailwind-merge@3.5.0: + resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} + + tailwindcss@4.2.2: + resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tldts-core@7.0.27: + resolution: {integrity: sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==} + + tldts@7.0.27: + resolution: {integrity: sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==} + hasBin: true + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-morph@26.0.0: + resolution: {integrity: sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==} + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@5.5.0: + resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} + engines: {node: '>=20'} + + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + + typescript-eslint@8.57.1: + resolution: {integrity: sha512-fLvZWf+cAGw3tqMCYzGIU6yR8K+Y9NT2z23RwOjlNFF2HwSB3KhdEFI5lSBv8tNmFkkBShSjsCjzx1vahZfISA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + until-async@3.0.2: + resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + validate-npm-package-name@7.0.2: + resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==} + engines: {node: ^20.17.0 || >=22.9.0} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + victory-vendor@37.3.6: + resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} + + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + wsl-utils@0.3.1: + resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} + engines: {node: '>=20'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + zod-to-json-schema@3.25.1: + resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} + peerDependencies: + zod: ^3.25 || ^4 + + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + +snapshots: + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.29.2': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@dotenvx/dotenvx@1.57.1': + dependencies: + commander: 11.1.0 + dotenv: 17.3.1 + eciesjs: 0.4.18 + execa: 5.1.1 + fdir: 6.5.0(picomatch@4.0.3) + ignore: 5.3.2 + object-treeify: 1.1.33 + picomatch: 4.0.3 + which: 4.0.0 + + '@ecies/ciphers@0.2.5(@noble/ciphers@1.3.0)': + dependencies: + '@noble/ciphers': 1.3.0 + + '@esbuild/aix-ppc64@0.27.4': + optional: true + + '@esbuild/android-arm64@0.27.4': + optional: true + + '@esbuild/android-arm@0.27.4': + optional: true + + '@esbuild/android-x64@0.27.4': + optional: true + + '@esbuild/darwin-arm64@0.27.4': + optional: true + + '@esbuild/darwin-x64@0.27.4': + optional: true + + '@esbuild/freebsd-arm64@0.27.4': + optional: true + + '@esbuild/freebsd-x64@0.27.4': + optional: true + + '@esbuild/linux-arm64@0.27.4': + optional: true + + '@esbuild/linux-arm@0.27.4': + optional: true + + '@esbuild/linux-ia32@0.27.4': + optional: true + + '@esbuild/linux-loong64@0.27.4': + optional: true + + '@esbuild/linux-mips64el@0.27.4': + optional: true + + '@esbuild/linux-ppc64@0.27.4': + optional: true + + '@esbuild/linux-riscv64@0.27.4': + optional: true + + '@esbuild/linux-s390x@0.27.4': + optional: true + + '@esbuild/linux-x64@0.27.4': + optional: true + + '@esbuild/netbsd-arm64@0.27.4': + optional: true + + '@esbuild/netbsd-x64@0.27.4': + optional: true + + '@esbuild/openbsd-arm64@0.27.4': + optional: true + + '@esbuild/openbsd-x64@0.27.4': + optional: true + + '@esbuild/openharmony-arm64@0.27.4': + optional: true + + '@esbuild/sunos-x64@0.27.4': + optional: true + + '@esbuild/win32-arm64@0.27.4': + optional: true + + '@esbuild/win32-ia32@0.27.4': + optional: true + + '@esbuild/win32-x64@0.27.4': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': + dependencies: + eslint: 9.39.4(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.14.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.4': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@floating-ui/core@1.7.5': + dependencies: + '@floating-ui/utils': 0.2.11 + + '@floating-ui/dom@1.7.6': + dependencies: + '@floating-ui/core': 1.7.5 + '@floating-ui/utils': 0.2.11 + + '@floating-ui/react-dom@2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@floating-ui/dom': 1.7.6 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@floating-ui/utils@0.2.11': {} + + '@fontsource-variable/geist@5.2.8': {} + + '@hono/node-server@1.19.11(hono@4.12.8)': + dependencies: + hono: 4.12.8 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@inquirer/ansi@1.0.2': {} + + '@inquirer/confirm@5.1.21(@types/node@24.12.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.12.0) + '@inquirer/type': 3.0.10(@types/node@24.12.0) + optionalDependencies: + '@types/node': 24.12.0 + + '@inquirer/core@10.3.2(@types/node@24.12.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.12.0) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.12.0 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/type@3.0.10(@types/node@24.12.0)': + optionalDependencies: + '@types/node': 24.12.0 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@modelcontextprotocol/sdk@1.27.1(zod@3.25.76)': + dependencies: + '@hono/node-server': 1.19.11(hono@4.12.8) + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.0.6 + express: 5.2.1 + express-rate-limit: 8.3.1(express@5.2.1) + hono: 4.12.8 + jose: 6.2.2 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + '@mswjs/interceptors@0.41.3': + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + + '@noble/ciphers@1.3.0': {} + + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.8.0': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@open-draft/deferred-promise@2.2.0': {} + + '@open-draft/logger@0.3.0': + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + + '@open-draft/until@2.1.0': {} + + '@radix-ui/number@1.1.1': {} + + '@radix-ui/primitive@1.1.3': {} + + '@radix-ui/react-accessible-icon@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-aspect-ratio@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + aria-hidden: 1.2.6 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + aria-hidden: 1.2.6 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-menubar@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-one-time-password-field@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-password-toggle-field@0.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + aria-hidden: 1.2.6 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/rect': 1.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-progress@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + aria-hidden: 1.2.6 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-separator@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-toolbar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/rect': 1.1.1 + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/rect@1.1.1': {} + + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4)': + dependencies: + '@standard-schema/spec': 1.1.0 + '@standard-schema/utils': 0.3.0 + immer: 11.1.4 + redux: 5.0.1 + redux-thunk: 3.1.0(redux@5.0.1) + reselect: 5.1.1 + optionalDependencies: + react: 19.2.4 + react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1) + + '@rolldown/pluginutils@1.0.0-rc.3': {} + + '@rollup/rollup-android-arm-eabi@4.60.0': + optional: true + + '@rollup/rollup-android-arm64@4.60.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.0': + optional: true + + '@rollup/rollup-darwin-x64@4.60.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.0': + optional: true + + '@sec-ant/readable-stream@0.4.1': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@standard-schema/spec@1.1.0': {} + + '@standard-schema/utils@0.3.0': {} + + '@tailwindcss/node@4.2.2': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.20.1 + jiti: 2.6.1 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.2.2 + + '@tailwindcss/oxide-android-arm64@4.2.2': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.2.2': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.2.2': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.2.2': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.2.2': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + optional: true + + '@tailwindcss/oxide@4.2.2': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.2.2 + '@tailwindcss/oxide-darwin-arm64': 4.2.2 + '@tailwindcss/oxide-darwin-x64': 4.2.2 + '@tailwindcss/oxide-freebsd-x64': 4.2.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 + '@tailwindcss/oxide-linux-x64-musl': 4.2.2 + '@tailwindcss/oxide-wasm32-wasi': 4.2.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 + + '@tailwindcss/vite@4.2.2(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0))': + dependencies: + '@tailwindcss/node': 4.2.2 + '@tailwindcss/oxide': 4.2.2 + tailwindcss: 4.2.2 + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0) + + '@ts-morph/common@0.27.0': + dependencies: + fast-glob: 3.3.3 + minimatch: 10.2.4 + path-browserify: 1.0.1 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/d3-array@3.2.2': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@24.12.0': + dependencies: + undici-types: 7.16.0 + + '@types/react-dom@19.2.3(@types/react@19.2.14)': + dependencies: + '@types/react': 19.2.14 + + '@types/react@19.2.14': + dependencies: + csstype: 3.2.3 + + '@types/statuses@2.0.6': {} + + '@types/use-sync-external-store@0.0.6': {} + + '@types/validate-npm-package-name@4.0.2': {} + + '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.57.1 + '@typescript-eslint/type-utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.57.1 + eslint: 9.39.4(jiti@2.6.1) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.57.1 + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.57.1 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.57.1(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.57.1(typescript@5.9.3) + '@typescript-eslint/types': 8.57.1 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.57.1': + dependencies: + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/visitor-keys': 8.57.1 + + '@typescript-eslint/tsconfig-utils@8.57.1(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.57.1': {} + + '@typescript-eslint/typescript-estree@8.57.1(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.57.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.57.1(typescript@5.9.3) + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/visitor-keys': 8.57.1 + debug: 4.4.3 + minimatch: 10.2.4 + semver: 7.7.4 + tinyglobby: 0.2.15 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.57.1 + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.57.1': + dependencies: + '@typescript-eslint/types': 8.57.1 + eslint-visitor-keys: 5.0.1 + + '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0) + transitivePeerDependencies: + - supports-color + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@7.1.4: {} + + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv@6.14.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.10.10: {} + + body-parser@2.2.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + on-finished: 2.4.1 + qs: 6.15.0 + raw-body: 3.0.2 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.10.10 + caniuse-lite: 1.0.30001780 + electron-to-chromium: 1.5.321 + node-releases: 2.0.36 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001780: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clsx@2.1.1: {} + + code-block-writer@13.0.3: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@11.1.0: {} + + commander@14.0.3: {} + + concat-map@0.0.1: {} + + content-disposition@1.0.1: {} + + content-type@1.0.5: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cookie@1.1.1: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cosmiconfig@9.0.1(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + csstype@3.2.3: {} + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-color@3.1.0: {} + + d3-ease@3.0.1: {} + + d3-format@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@3.1.0: {} + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.2 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + data-uri-to-buffer@4.0.1: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js-light@2.5.1: {} + + dedent@1.7.2: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + define-lazy-prop@3.0.0: {} + + depd@2.0.0: {} + + detect-libc@2.1.2: {} + + detect-node-es@1.1.0: {} + + diff@8.0.3: {} + + dotenv@17.3.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eciesjs@0.4.18: + dependencies: + '@ecies/ciphers': 0.2.5(@noble/ciphers@1.3.0) + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.321: {} + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + encodeurl@2.0.0: {} + + enhanced-resolve@5.20.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + env-paths@2.2.1: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-toolkit@1.45.1: {} + + esbuild@0.27.4: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.4 + '@esbuild/android-arm': 0.27.4 + '@esbuild/android-arm64': 0.27.4 + '@esbuild/android-x64': 0.27.4 + '@esbuild/darwin-arm64': 0.27.4 + '@esbuild/darwin-x64': 0.27.4 + '@esbuild/freebsd-arm64': 0.27.4 + '@esbuild/freebsd-x64': 0.27.4 + '@esbuild/linux-arm': 0.27.4 + '@esbuild/linux-arm64': 0.27.4 + '@esbuild/linux-ia32': 0.27.4 + '@esbuild/linux-loong64': 0.27.4 + '@esbuild/linux-mips64el': 0.27.4 + '@esbuild/linux-ppc64': 0.27.4 + '@esbuild/linux-riscv64': 0.27.4 + '@esbuild/linux-s390x': 0.27.4 + '@esbuild/linux-x64': 0.27.4 + '@esbuild/netbsd-arm64': 0.27.4 + '@esbuild/netbsd-x64': 0.27.4 + '@esbuild/openbsd-arm64': 0.27.4 + '@esbuild/openbsd-x64': 0.27.4 + '@esbuild/openharmony-arm64': 0.27.4 + '@esbuild/sunos-x64': 0.27.4 + '@esbuild/win32-arm64': 0.27.4 + '@esbuild/win32-ia32': 0.27.4 + '@esbuild/win32-x64': 0.27.4 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + eslint-plugin-react-hooks@7.0.1(eslint@9.39.4(jiti@2.6.1)): + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.2 + eslint: 9.39.4(jiti@2.6.1) + hermes-parser: 0.25.1 + zod: 4.3.6 + zod-validation-error: 4.0.2(zod@4.3.6) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-refresh@0.5.2(eslint@9.39.4(jiti@2.6.1)): + dependencies: + eslint: 9.39.4(jiti@2.6.1) + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@9.39.4(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.14.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@5.0.4: {} + + eventsource-parser@3.0.6: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.0.6 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@9.6.1: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.3.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.2 + + express-rate-limit@8.3.1(express@5.2.1): + dependencies: + express: 5.2.1 + ip-address: 10.1.0 + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.2 + content-disposition: 1.0.1 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.15.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.1.0: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flatted@3.4.2: {} + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + fuzzysort@3.1.0: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.5.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-nonce@1.0.1: {} + + get-own-enumerable-keys@1.0.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@6.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@16.5.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphql@16.13.1: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + headers-polyfill@4.0.3: {} + + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + hono@4.12.8: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + human-signals@8.0.1: {} + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + immer@10.2.0: {} + + immer@11.1.4: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + internmap@2.0.3: {} + + ip-address@10.1.0: {} + + ipaddr.js@1.9.1: {} + + is-arrayish@0.2.1: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-in-ssh@1.0.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-interactive@2.0.0: {} + + is-node-process@1.2.0: {} + + is-number@7.0.0: {} + + is-obj@3.0.0: {} + + is-plain-obj@4.1.0: {} + + is-promise@4.0.0: {} + + is-regexp@3.1.0: {} + + is-stream@2.0.1: {} + + is-stream@4.0.1: {} + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + isexe@3.1.5: {} + + jiti@2.6.1: {} + + jose@6.2.2: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.2: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kleur@3.0.3: {} + + kleur@4.1.5: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lines-and-columns@1.2.4: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + log-symbols@6.0.0: + dependencies: + chalk: 5.6.2 + is-unicode-supported: 1.3.0 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lucide-react@0.577.0(react@19.2.4): + dependencies: + react: 19.2.4 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + media-typer@1.1.0: {} + + merge-descriptors@2.0.0: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.54.0: {} + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mimic-fn@2.1.0: {} + + mimic-function@5.0.1: {} + + minimatch@10.2.4: + dependencies: + brace-expansion: 5.0.4 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.12 + + minimist@1.2.8: {} + + ms@2.1.3: {} + + msw@2.12.14(@types/node@24.12.0)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.21(@types/node@24.12.0) + '@mswjs/interceptors': 0.41.3 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.1.1 + graphql: 16.13.1 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.10.1 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.1 + type-fest: 5.5.0 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + + mute-stream@2.0.0: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + negotiator@1.0.0: {} + + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-releases@2.0.36: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-treeify@1.1.33: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + open@11.0.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-in-ssh: 1.0.0 + is-inside-container: 1.0.0 + powershell-utils: 0.1.0 + wsl-utils: 0.3.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@8.2.0: + dependencies: + chalk: 5.6.2 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + outvariant@1.4.3: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-ms@4.0.0: {} + + parseurl@1.3.3: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-to-regexp@6.3.0: {} + + path-to-regexp@8.3.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pkce-challenge@5.0.1: {} + + postcss-selector-parser@7.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.8: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + powershell-utils@0.1.0: {} + + prelude-ls@1.2.1: {} + + prettier-plugin-tailwindcss@0.7.2(prettier@3.8.1): + dependencies: + prettier: 3.8.1 + + prettier@3.8.1: {} + + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + punycode@2.3.1: {} + + qs@6.15.0: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + radix-ui@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-accessible-icon': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-alert-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-aspect-ratio': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-avatar': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-checkbox': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-context-menu': 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-hover-card': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-menubar': 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-one-time-password-field': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-password-toggle-field': 0.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-progress': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-radio-group': 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slider': 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-switch': 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-toolbar': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + range-parser@1.2.1: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + unpipe: 1.0.0 + + react-dom@19.2.4(react@19.2.4): + dependencies: + react: 19.2.4 + scheduler: 0.27.0 + + react-is@19.2.4: {} + + react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1): + dependencies: + '@types/use-sync-external-store': 0.0.6 + react: 19.2.4 + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + redux: 5.0.1 + + react-refresh@0.18.0: {} + + react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.4): + dependencies: + react: 19.2.4 + react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.4) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + react-remove-scroll@2.7.2(@types/react@19.2.14)(react@19.2.4): + dependencies: + react: 19.2.4 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.14)(react@19.2.4) + react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.4) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.4) + use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + + react-router-dom@7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-router: 7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + + react-router@7.13.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + cookie: 1.1.1 + react: 19.2.4 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.2.4(react@19.2.4) + + react-style-singleton@2.2.3(@types/react@19.2.14)(react@19.2.4): + dependencies: + get-nonce: 1.0.1 + react: 19.2.4 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + react@19.2.4: {} + + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + + recharts@3.8.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.4)(react@19.2.4)(redux@5.0.1): + dependencies: + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4) + clsx: 2.1.1 + decimal.js-light: 2.5.1 + es-toolkit: 1.45.1 + eventemitter3: 5.0.4 + immer: 10.2.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-is: 19.2.4 + react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1) + reselect: 5.1.1 + tiny-invariant: 1.3.3 + use-sync-external-store: 1.6.0(react@19.2.4) + victory-vendor: 37.3.6 + transitivePeerDependencies: + - '@types/react' + - redux + + redux-thunk@3.1.0(redux@5.0.1): + dependencies: + redux: 5.0.1 + + redux@5.0.1: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + reselect@5.1.1: {} + + resolve-from@4.0.0: {} + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + rettime@0.10.1: {} + + reusify@1.1.0: {} + + rollup@4.60.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.0 + '@rollup/rollup-android-arm64': 4.60.0 + '@rollup/rollup-darwin-arm64': 4.60.0 + '@rollup/rollup-darwin-x64': 4.60.0 + '@rollup/rollup-freebsd-arm64': 4.60.0 + '@rollup/rollup-freebsd-x64': 4.60.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.0 + '@rollup/rollup-linux-arm-musleabihf': 4.60.0 + '@rollup/rollup-linux-arm64-gnu': 4.60.0 + '@rollup/rollup-linux-arm64-musl': 4.60.0 + '@rollup/rollup-linux-loong64-gnu': 4.60.0 + '@rollup/rollup-linux-loong64-musl': 4.60.0 + '@rollup/rollup-linux-ppc64-gnu': 4.60.0 + '@rollup/rollup-linux-ppc64-musl': 4.60.0 + '@rollup/rollup-linux-riscv64-gnu': 4.60.0 + '@rollup/rollup-linux-riscv64-musl': 4.60.0 + '@rollup/rollup-linux-s390x-gnu': 4.60.0 + '@rollup/rollup-linux-x64-gnu': 4.60.0 + '@rollup/rollup-linux-x64-musl': 4.60.0 + '@rollup/rollup-openbsd-x64': 4.60.0 + '@rollup/rollup-openharmony-arm64': 4.60.0 + '@rollup/rollup-win32-arm64-msvc': 4.60.0 + '@rollup/rollup-win32-ia32-msvc': 4.60.0 + '@rollup/rollup-win32-x64-gnu': 4.60.0 + '@rollup/rollup-win32-x64-msvc': 4.60.0 + fsevents: 2.3.3 + + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.3.0 + transitivePeerDependencies: + - supports-color + + run-applescript@7.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safer-buffer@2.1.2: {} + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + semver@7.7.4: {} + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + set-cookie-parser@2.7.2: {} + + setprototypeof@1.2.0: {} + + shadcn@4.1.0(@types/node@24.12.0)(typescript@5.9.3): + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + '@dotenvx/dotenvx': 1.57.1 + '@modelcontextprotocol/sdk': 1.27.1(zod@3.25.76) + '@types/validate-npm-package-name': 4.0.2 + browserslist: 4.28.1 + commander: 14.0.3 + cosmiconfig: 9.0.1(typescript@5.9.3) + dedent: 1.7.2 + deepmerge: 4.3.1 + diff: 8.0.3 + execa: 9.6.1 + fast-glob: 3.3.3 + fs-extra: 11.3.4 + fuzzysort: 3.1.0 + https-proxy-agent: 7.0.6 + kleur: 4.1.5 + msw: 2.12.14(@types/node@24.12.0)(typescript@5.9.3) + node-fetch: 3.3.2 + open: 11.0.0 + ora: 8.2.0 + postcss: 8.5.8 + postcss-selector-parser: 7.1.1 + prompts: 2.4.2 + recast: 0.23.11 + stringify-object: 5.0.0 + tailwind-merge: 3.5.0 + ts-morph: 26.0.0 + tsconfig-paths: 4.2.0 + validate-npm-package-name: 7.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - '@cfworker/json-schema' + - '@types/node' + - babel-plugin-macros + - supports-color + - typescript + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sisteransi@1.0.5: {} + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + statuses@2.0.2: {} + + stdin-discarder@0.2.2: {} + + strict-event-emitter@0.5.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + + stringify-object@5.0.0: + dependencies: + get-own-enumerable-keys: 1.0.0 + is-obj: 3.0.0 + is-regexp: 3.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-bom@3.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-final-newline@4.0.0: {} + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tagged-tag@1.0.0: {} + + tailwind-merge@3.5.0: {} + + tailwindcss@4.2.2: {} + + tapable@2.3.0: {} + + tiny-invariant@1.3.3: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tldts-core@7.0.27: {} + + tldts@7.0.27: + dependencies: + tldts-core: 7.0.27 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + tough-cookie@6.0.1: + dependencies: + tldts: 7.0.27 + + ts-api-utils@2.5.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + ts-morph@26.0.0: + dependencies: + '@ts-morph/common': 0.27.0 + code-block-writer: 13.0.3 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + tw-animate-css@1.4.0: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@5.5.0: + dependencies: + tagged-tag: 1.0.0 + + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.2 + + typescript-eslint@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + typescript@5.9.3: {} + + undici-types@7.16.0: {} + + unicorn-magic@0.3.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + until-async@3.0.2: {} + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.4): + dependencies: + react: 19.2.4 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.4): + dependencies: + detect-node-es: 1.1.0 + react: 19.2.4 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + use-sync-external-store@1.6.0(react@19.2.4): + dependencies: + react: 19.2.4 + + util-deprecate@1.0.2: {} + + validate-npm-package-name@7.0.2: {} + + vary@1.1.2: {} + + victory-vendor@37.3.6: + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-ease': 3.0.2 + '@types/d3-interpolate': 3.0.4 + '@types/d3-scale': 4.0.9 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-timer': 3.0.2 + d3-array: 3.2.4 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-scale: 4.0.2 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-timer: 3.0.1 + + vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0): + dependencies: + esbuild: 0.27.4 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.8 + rollup: 4.60.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.12.0 + fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.32.0 + + web-streams-polyfill@3.3.3: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@4.0.0: + dependencies: + isexe: 3.1.5 + + word-wrap@1.2.5: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + wsl-utils@0.3.1: + dependencies: + is-wsl: 3.1.1 + powershell-utils: 0.1.0 + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yoctocolors-cjs@2.1.3: {} + + yoctocolors@2.1.2: {} + + zod-to-json-schema@3.25.1(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod-validation-error@4.0.2(zod@4.3.6): + dependencies: + zod: 4.3.6 + + zod@3.25.76: {} + + zod@4.3.6: {} diff --git a/lazer/cardano/hermes/ui/public/vite.svg b/lazer/cardano/hermes/ui/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/lazer/cardano/hermes/ui/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lazer/cardano/hermes/ui/src/App.tsx b/lazer/cardano/hermes/ui/src/App.tsx new file mode 100644 index 00000000..2e0f41a2 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/App.tsx @@ -0,0 +1,16 @@ +import { BrowserRouter, Route, Routes } from "react-router-dom" +import { MarketDashboard } from "@/components/MarketDashboard" +import { HistoryPage } from "@/pages/HistoryPage" + +export function App() { + return ( + + + } /> + } /> + + + ) +} + +export default App diff --git a/lazer/cardano/hermes/ui/src/assets/react.svg b/lazer/cardano/hermes/ui/src/assets/react.svg new file mode 100644 index 00000000..6c87de9b --- /dev/null +++ b/lazer/cardano/hermes/ui/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lazer/cardano/hermes/ui/src/components/FillRow.tsx b/lazer/cardano/hermes/ui/src/components/FillRow.tsx new file mode 100644 index 00000000..fc51286c --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/FillRow.tsx @@ -0,0 +1,28 @@ +import { memo } from "react" +import type { Fill } from "@/types/market" + +interface FillRowProps { + fill: Fill +} + +function formatTime(ts: number): string { + return new Date(ts).toLocaleTimeString("en-GB") +} + +export const FillRow = memo(function FillRow({ fill }: FillRowProps) { + const isUp = fill.side === "UP" + + return ( +
+ + {formatTime(fill.timestamp)} + + + {fill.side} + + {fill.quantity} + {fill.price.toFixed(4)} + {fill.ownerAddress} +
+ ) +}) diff --git a/lazer/cardano/hermes/ui/src/components/MarketDashboard.tsx b/lazer/cardano/hermes/ui/src/components/MarketDashboard.tsx new file mode 100644 index 00000000..15400270 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/MarketDashboard.tsx @@ -0,0 +1,122 @@ +import { Link } from "react-router-dom" +import { useMarketStream } from "@/hooks/useMarketStream" +import { PriceChart } from "./PriceChart" +import { OrderBook } from "./OrderBook" +import { Positions } from "./Positions" +import { TradeForm } from "./TradeForm" + +const STATUS_LABEL = { + connecting: "○ CONNECTING", + live: "● LIVE", + disconnected: "○ DISCONNECTED", +} as const + +const STATUS_CLASS = { + connecting: "text-yellow-400", + live: "text-green-400", + disconnected: "text-muted-foreground", +} as const + +function formatTime(ts: number): string { + return new Date(ts).toLocaleTimeString("en-GB") +} + +function formatCountdown(secs: number): string { + const m = Math.floor(secs / 60) + .toString() + .padStart(2, "0") + const s = (secs % 60).toString().padStart(2, "0") + return `${m}:${s}` +} + +function countdownClass(secs: number): string { + if (secs > 60) return "text-green-400" + if (secs > 10) return "text-yellow-400" + return "text-red-400" +} + +export function MarketDashboard() { + const { + market, + secondsRemaining, + priceTicks, + currentBtcPriceStr, + orders, + fills, + positionSummary, + rollingAverages, + status, + placeOrder, + } = useMarketStream() + + const strikePrice = market?.strikePrice + + return ( +
+
+ + BTC/USD PREDICTION MARKET + + + + {STATUS_LABEL[status]} + + + + HISTORY → + + + + {market && ( + <> + + + START{" "} + + {formatTime(market.startTime)} + + + + + + END{" "} + + {formatTime(market.endTime)} + + + + + + ENDS IN{" "} + + {formatCountdown(secondsRemaining)} + + + + )} +
+ +
+
+ + + +
+
+ +
+
+
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/components/OrderBook.tsx b/lazer/cardano/hermes/ui/src/components/OrderBook.tsx new file mode 100644 index 00000000..995acb2a --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/OrderBook.tsx @@ -0,0 +1,30 @@ +import type { Order } from "@/types/market" +import { TuiPanel } from "./TuiPanel" +import { OrderRow } from "./OrderRow" + +interface OrderBookProps { + orders: Order[] + strikePrice: number | undefined +} + +export function OrderBook({ orders, strikePrice }: OrderBookProps) { + return ( + ${strikePrice !== undefined ? `$${strikePrice.toLocaleString()}` : "—"}`} + > +
+ TIME + SIDE + TYPE + PRICE + QTY + OWNER +
+
+ {orders.map((order) => ( + + ))} +
+
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/components/OrderRow.tsx b/lazer/cardano/hermes/ui/src/components/OrderRow.tsx new file mode 100644 index 00000000..ea2ecd39 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/OrderRow.tsx @@ -0,0 +1,34 @@ +import { memo } from "react" +import type { Order } from "@/types/market" + +interface OrderRowProps { + order: Order +} + +function formatTime(ts: number): string { + return new Date(ts).toLocaleTimeString("en-GB") +} + +export const OrderRow = memo(function OrderRow({ order }: OrderRowProps) { + const isBuy = order.action === "BUY" + const isUp = order.side === "UP" + + return ( +
+ + {formatTime(order.timestamp)} + + + {order.side} + + {order.action} + {order.price.toFixed(4)} + {order.quantity} + {order.ownerAddress} +
+ ) +}) diff --git a/lazer/cardano/hermes/ui/src/components/Positions.tsx b/lazer/cardano/hermes/ui/src/components/Positions.tsx new file mode 100644 index 00000000..c9daa999 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/Positions.tsx @@ -0,0 +1,44 @@ +import type { Fill, PositionSummary } from "@/types/market" +import { TuiPanel } from "./TuiPanel" +import { FillRow } from "./FillRow" + +interface PositionsProps { + fills: Fill[] + summary: PositionSummary +} + +export function Positions({ fills, summary }: PositionsProps) { + return ( + +
+ + UP + {": "} + {summary.upContracts} + {" @ "} + {summary.upAvgPrice.toFixed(4)} + + + + DOWN + {": "} + {summary.downContracts} + {" @ "} + {summary.downAvgPrice.toFixed(4)} + +
+
+ TIME + SIDE + QTY + PRICE + OWNER +
+
+ {fills.map((fill) => ( + + ))} +
+
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/components/PriceChart.tsx b/lazer/cardano/hermes/ui/src/components/PriceChart.tsx new file mode 100644 index 00000000..7ce63964 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/PriceChart.tsx @@ -0,0 +1,103 @@ +import { + CartesianGrid, + Line, + LineChart, + ReferenceLine, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from "recharts" +import type { PriceTick } from "@/types/market" +import { TuiPanel } from "./TuiPanel" + +interface PriceChartProps { + ticks: PriceTick[] + strikePrice: number | undefined + currentPrice: string +} + +function formatTime(ts: number): string { + return new Date(ts).toLocaleTimeString("en-GB") +} + +function formatUsd(v: number): string { + return `$${Math.round(v).toLocaleString()}` +} + +export function PriceChart({ + ticks, + strikePrice, + currentPrice, +}: PriceChartProps) { + return ( + +
+ + + + + + formatTime(v as number)} + formatter={(v) => [formatUsd(Number(v)), "BTC/USD"]} + /> + {strikePrice !== undefined && ( + + )} + + parseFloat((tick as PriceTick).btcPriceStr) + } + stroke="#facc15" + strokeWidth={1.5} + dot={false} + isAnimationActive={false} + /> + + +
+
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/components/TradeForm.tsx b/lazer/cardano/hermes/ui/src/components/TradeForm.tsx new file mode 100644 index 00000000..9e88580d --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/TradeForm.tsx @@ -0,0 +1,241 @@ +import { useEffect, useState } from "react" +import type { PlaceOrderPayload, RollingAverages } from "@/types/market" +import { TuiPanel } from "./TuiPanel" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" + +interface TradeFormProps { + averages: RollingAverages + strikePrice: number | undefined + onPlaceOrder: (payload: PlaceOrderPayload) => void +} + +interface LastAction { + verb: string + qty: number + side: string + price: string +} + +export function TradeForm({ + averages, + strikePrice, + onPlaceOrder, +}: TradeFormProps) { + const [buyQty, setBuyQty] = useState("100") + const [buyUpPrice, setBuyUpPrice] = useState("") + const [buyDownPrice, setBuyDownPrice] = useState("") + + const [sellQty, setSellQty] = useState("100") + const [sellUpPrice, setSellUpPrice] = useState("") + const [sellDownPrice, setSellDownPrice] = useState("") + + const [lastAction, setLastAction] = useState(null) + + // Pre-fill price fields from rolling averages only when the field is empty + // (i.e., the user hasn't typed a custom value yet) + useEffect(() => { + if (!buyUpPrice) setBuyUpPrice(averages.upBuyAvg.toFixed(4)) + }, [averages.upBuyAvg, buyUpPrice]) + + useEffect(() => { + if (!buyDownPrice) setBuyDownPrice(averages.downBuyAvg.toFixed(4)) + }, [averages.downBuyAvg, buyDownPrice]) + + useEffect(() => { + if (!sellUpPrice) setSellUpPrice(averages.upSellAvg.toFixed(4)) + }, [averages.upSellAvg, sellUpPrice]) + + useEffect(() => { + if (!sellDownPrice) setSellDownPrice(averages.downSellAvg.toFixed(4)) + }, [averages.downSellAvg, sellDownPrice]) + + function validate(qty: string, price: string): boolean { + const q = parseInt(qty, 10) + const p = parseFloat(price) + return !isNaN(q) && q > 0 && !isNaN(p) && p > 0 && p <= 1 + } + + function handleBuy(side: "UP" | "DOWN") { + const price = side === "UP" ? buyUpPrice : buyDownPrice + if (!validate(buyQty, price)) return + const qty = parseInt(buyQty, 10) + onPlaceOrder({ + side, + action: "BUY", + price: parseFloat(price), + quantity: qty, + }) + setLastAction({ verb: "BUY", qty, side, price }) + } + + function handleSell(side: "UP" | "DOWN") { + const price = side === "UP" ? sellUpPrice : sellDownPrice + if (!validate(sellQty, price)) return + const qty = parseInt(sellQty, 10) + onPlaceOrder({ + side, + action: "SELL", + price: parseFloat(price), + quantity: qty, + }) + setLastAction({ verb: "SELL", qty, side, price }) + } + + return ( + ${strikePrice !== undefined ? `$${strikePrice.toLocaleString()}` : "—"}`} + className="h-full" + > + + + + BUY + + + SELL + + + + +
+ + setBuyQty(e.target.value)} + className="h-7 rounded-none border-border font-mono text-xs" + /> +
+ +
+
+ + setBuyUpPrice(e.target.value)} + className="h-7 rounded-none border-border font-mono text-xs" + /> + +
+ +
+ + setBuyDownPrice(e.target.value)} + className="h-7 rounded-none border-border font-mono text-xs" + /> + +
+
+
+ + +
+ + setSellQty(e.target.value)} + className="h-7 rounded-none border-border font-mono text-xs" + /> +
+ +
+
+ + setSellUpPrice(e.target.value)} + className="h-7 rounded-none border-border font-mono text-xs" + /> + +
+ +
+ + setSellDownPrice(e.target.value)} + className="h-7 rounded-none border-border font-mono text-xs" + /> + +
+
+
+
+ + {lastAction && ( +
+ {">"}{" "} + + {lastAction.verb} + {" "} + {lastAction.qty}{" "} + + {lastAction.side} + {" "} + @ {lastAction.price} +
+ )} +
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/components/TuiPanel.tsx b/lazer/cardano/hermes/ui/src/components/TuiPanel.tsx new file mode 100644 index 00000000..43d21577 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/TuiPanel.tsx @@ -0,0 +1,23 @@ +import { cn } from "@/lib/utils" + +interface TuiPanelProps { + title: string + children: React.ReactNode + className?: string +} + +export function TuiPanel({ title, children, className }: TuiPanelProps) { + return ( +
+
+ ┌─ + [ {title} ] + + {"─".repeat(200)} + + ─┐ +
+
{children}
+
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/components/theme-provider.tsx b/lazer/cardano/hermes/ui/src/components/theme-provider.tsx new file mode 100644 index 00000000..1349a0ca --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/theme-provider.tsx @@ -0,0 +1,230 @@ +/* eslint-disable react-refresh/only-export-components */ +import * as React from "react" + +type Theme = "dark" | "light" | "system" +type ResolvedTheme = "dark" | "light" + +type ThemeProviderProps = { + children: React.ReactNode + defaultTheme?: Theme + storageKey?: string + disableTransitionOnChange?: boolean +} + +type ThemeProviderState = { + theme: Theme + setTheme: (theme: Theme) => void +} + +const COLOR_SCHEME_QUERY = "(prefers-color-scheme: dark)" +const THEME_VALUES: Theme[] = ["dark", "light", "system"] + +const ThemeProviderContext = React.createContext< + ThemeProviderState | undefined +>(undefined) + +function isTheme(value: string | null): value is Theme { + if (value === null) { + return false + } + + return THEME_VALUES.includes(value as Theme) +} + +function getSystemTheme(): ResolvedTheme { + if (window.matchMedia(COLOR_SCHEME_QUERY).matches) { + return "dark" + } + + return "light" +} + +function disableTransitionsTemporarily() { + const style = document.createElement("style") + style.appendChild( + document.createTextNode( + "*,*::before,*::after{-webkit-transition:none!important;transition:none!important}" + ) + ) + document.head.appendChild(style) + + return () => { + window.getComputedStyle(document.body) + requestAnimationFrame(() => { + requestAnimationFrame(() => { + style.remove() + }) + }) + } +} + +function isEditableTarget(target: EventTarget | null) { + if (!(target instanceof HTMLElement)) { + return false + } + + if (target.isContentEditable) { + return true + } + + const editableParent = target.closest( + "input, textarea, select, [contenteditable='true']" + ) + if (editableParent) { + return true + } + + return false +} + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "theme", + disableTransitionOnChange = true, + ...props +}: ThemeProviderProps) { + const [theme, setThemeState] = React.useState(() => { + const storedTheme = localStorage.getItem(storageKey) + if (isTheme(storedTheme)) { + return storedTheme + } + + return defaultTheme + }) + + const setTheme = React.useCallback( + (nextTheme: Theme) => { + localStorage.setItem(storageKey, nextTheme) + setThemeState(nextTheme) + }, + [storageKey] + ) + + const applyTheme = React.useCallback( + (nextTheme: Theme) => { + const root = document.documentElement + const resolvedTheme = + nextTheme === "system" ? getSystemTheme() : nextTheme + const restoreTransitions = disableTransitionOnChange + ? disableTransitionsTemporarily() + : null + + root.classList.remove("light", "dark") + root.classList.add(resolvedTheme) + + if (restoreTransitions) { + restoreTransitions() + } + }, + [disableTransitionOnChange] + ) + + React.useEffect(() => { + applyTheme(theme) + + if (theme !== "system") { + return undefined + } + + const mediaQuery = window.matchMedia(COLOR_SCHEME_QUERY) + const handleChange = () => { + applyTheme("system") + } + + mediaQuery.addEventListener("change", handleChange) + + return () => { + mediaQuery.removeEventListener("change", handleChange) + } + }, [theme, applyTheme]) + + React.useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.repeat) { + return + } + + if (event.metaKey || event.ctrlKey || event.altKey) { + return + } + + if (isEditableTarget(event.target)) { + return + } + + if (event.key.toLowerCase() !== "d") { + return + } + + setThemeState((currentTheme) => { + const nextTheme = + currentTheme === "dark" + ? "light" + : currentTheme === "light" + ? "dark" + : getSystemTheme() === "dark" + ? "light" + : "dark" + + localStorage.setItem(storageKey, nextTheme) + return nextTheme + }) + } + + window.addEventListener("keydown", handleKeyDown) + + return () => { + window.removeEventListener("keydown", handleKeyDown) + } + }, [storageKey]) + + React.useEffect(() => { + const handleStorageChange = (event: StorageEvent) => { + if (event.storageArea !== localStorage) { + return + } + + if (event.key !== storageKey) { + return + } + + if (isTheme(event.newValue)) { + setThemeState(event.newValue) + return + } + + setThemeState(defaultTheme) + } + + window.addEventListener("storage", handleStorageChange) + + return () => { + window.removeEventListener("storage", handleStorageChange) + } + }, [defaultTheme, storageKey]) + + const value = React.useMemo( + () => ({ + theme, + setTheme, + }), + [theme, setTheme] + ) + + return ( + + {children} + + ) +} + +export const useTheme = () => { + const context = React.useContext(ThemeProviderContext) + + if (context === undefined) { + throw new Error("useTheme must be used within a ThemeProvider") + } + + return context +} diff --git a/lazer/cardano/hermes/ui/src/components/ui/badge.tsx b/lazer/cardano/hermes/ui/src/components/ui/badge.tsx new file mode 100644 index 00000000..cacff11d --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/ui/badge.tsx @@ -0,0 +1,49 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from "radix-ui" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", + secondary: + "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", + destructive: + "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20", + outline: + "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", + ghost: + "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", + link: "text-primary underline-offset-4 hover:underline", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Badge({ + className, + variant = "default", + asChild = false, + ...props +}: React.ComponentProps<"span"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot.Root : "span" + + return ( + + ) +} + +export { Badge, badgeVariants } diff --git a/lazer/cardano/hermes/ui/src/components/ui/button.tsx b/lazer/cardano/hermes/ui/src/components/ui/button.tsx new file mode 100644 index 00000000..c88ffd6f --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/ui/button.tsx @@ -0,0 +1,67 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from "radix-ui" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", + outline: + "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", + ghost: + "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50", + destructive: + "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: + "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", + xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", + sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", + lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3", + icon: "size-8", + "icon-xs": + "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3", + "icon-sm": + "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg", + "icon-lg": "size-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Button({ + className, + variant = "default", + size = "default", + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean + }) { + const Comp = asChild ? Slot.Root : "button" + + return ( + + ) +} + +export { Button, buttonVariants } diff --git a/lazer/cardano/hermes/ui/src/components/ui/input.tsx b/lazer/cardano/hermes/ui/src/components/ui/input.tsx new file mode 100644 index 00000000..d763cd9a --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/ui/input.tsx @@ -0,0 +1,19 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Input({ className, type, ...props }: React.ComponentProps<"input">) { + return ( + + ) +} + +export { Input } diff --git a/lazer/cardano/hermes/ui/src/components/ui/tabs.tsx b/lazer/cardano/hermes/ui/src/components/ui/tabs.tsx new file mode 100644 index 00000000..2cb6924e --- /dev/null +++ b/lazer/cardano/hermes/ui/src/components/ui/tabs.tsx @@ -0,0 +1,88 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Tabs as TabsPrimitive } from "radix-ui" + +import { cn } from "@/lib/utils" + +function Tabs({ + className, + orientation = "horizontal", + ...props +}: React.ComponentProps) { + return ( + + ) +} + +const tabsListVariants = cva( + "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none", + { + variants: { + variant: { + default: "bg-muted", + line: "gap-1 bg-transparent", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function TabsList({ + className, + variant = "default", + ...props +}: React.ComponentProps & + VariantProps) { + return ( + + ) +} + +function TabsTrigger({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function TabsContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants } diff --git a/lazer/cardano/hermes/ui/src/hooks/useMarketStream.ts b/lazer/cardano/hermes/ui/src/hooks/useMarketStream.ts new file mode 100644 index 00000000..04dbc4ee --- /dev/null +++ b/lazer/cardano/hermes/ui/src/hooks/useMarketStream.ts @@ -0,0 +1,160 @@ +import { useCallback, useEffect, useRef, useState } from "react" +import type { + ClientMessage, + Fill, + Market, + Order, + PlaceOrderPayload, + PositionSummary, + PriceTick, + RollingAverages, + ServerMessage, +} from "@/types/market" + +// The WS URL can be overridden via environment variable for production deploys. +// In development the Vite proxy forwards /ws → ws://localhost:8080 (see vite.config.ts). +const WS_URL = + (import.meta.env.VITE_WS_URL as string | undefined) ?? + "ws://localhost:8080/ws" + +const MAX_TICKS = 120 +const MAX_ORDERS = 50 +const MAX_FILLS = 30 + +export type ConnectionStatus = "connecting" | "live" | "disconnected" + +const DEFAULT_AVG: RollingAverages = { + upBuyAvg: 0.5, + upSellAvg: 0.5, + downBuyAvg: 0.5, + downSellAvg: 0.5, +} + +const DEFAULT_SUMMARY: PositionSummary = { + upContracts: 0, + upAvgPrice: 0, + downContracts: 0, + downAvgPrice: 0, +} + +export interface MarketStreamData { + market: Market | null + secondsRemaining: number + priceTicks: PriceTick[] + currentBtcPriceStr: string + orders: Order[] + fills: Fill[] + positionSummary: PositionSummary + rollingAverages: RollingAverages + status: ConnectionStatus + placeOrder: (payload: PlaceOrderPayload) => void +} + +export function useMarketStream(): MarketStreamData { + const [market, setMarket] = useState(null) + const [secondsRemaining, setSecondsRemaining] = useState(0) + const [priceTicks, setPriceTicks] = useState([]) + const [orders, setOrders] = useState([]) + const [fills, setFills] = useState([]) + const [positionSummary, setPositionSummary] = + useState(DEFAULT_SUMMARY) + const [rollingAverages, setRollingAverages] = + useState(DEFAULT_AVG) + const [status, setStatus] = useState("connecting") + + const wsRef = useRef(null) + + // ── WebSocket connection ──────────────────────────────────────────────────── + + useEffect(() => { + const ws = new WebSocket(WS_URL) + wsRef.current = ws + + ws.onopen = () => setStatus("live") + ws.onclose = () => setStatus("disconnected") + ws.onerror = () => setStatus("disconnected") + + ws.onmessage = (event: MessageEvent) => { + const msg = JSON.parse(event.data) as ServerMessage + + switch (msg.type) { + case "connected": + setMarket(msg.data.market) + break + + case "market_started": + setMarket(msg.data.market) + // Reset all market-scoped state for the new market + setPriceTicks([]) + setOrders([]) + setFills([]) + setPositionSummary(DEFAULT_SUMMARY) + setRollingAverages(DEFAULT_AVG) + break + + case "price_tick": + setPriceTicks((prev) => [...prev.slice(-(MAX_TICKS - 1)), msg.data]) + break + + case "order": + setOrders((prev) => [msg.data, ...prev].slice(0, MAX_ORDERS)) + break + + case "fill": + setFills((prev) => [msg.data, ...prev].slice(0, MAX_FILLS)) + break + + case "position_summary": + setPositionSummary(msg.data) + break + + case "rolling_averages": + setRollingAverages(msg.data) + break + } + } + + return () => ws.close() + }, []) + + // ── Countdown timer ───────────────────────────────────────────────────────── + + useEffect(() => { + if (!market) return + // Tick immediately, then every second + setSecondsRemaining( + Math.max(0, Math.round((market.endTime - Date.now()) / 1000)) + ) + const id = setInterval(() => { + setSecondsRemaining( + Math.max(0, Math.round((market.endTime - Date.now()) / 1000)) + ) + }, 1_000) + return () => clearInterval(id) + }, [market]) + + // ── placeOrder ────────────────────────────────────────────────────────────── + + const placeOrder = useCallback((payload: PlaceOrderPayload) => { + const ws = wsRef.current + if (!ws || ws.readyState !== WebSocket.OPEN) return + const msg: ClientMessage = { type: "place_order", data: payload } + ws.send(JSON.stringify(msg)) + }, []) + + const currentBtcPriceStr = + priceTicks.length > 0 ? priceTicks[priceTicks.length - 1].btcPriceStr : "" + + return { + market, + secondsRemaining, + priceTicks, + currentBtcPriceStr, + orders, + fills, + positionSummary, + rollingAverages, + status, + placeOrder, + } +} diff --git a/lazer/cardano/hermes/ui/src/index.css b/lazer/cardano/hermes/ui/src/index.css new file mode 100644 index 00000000..024a264b --- /dev/null +++ b/lazer/cardano/hermes/ui/src/index.css @@ -0,0 +1,133 @@ +@import "tailwindcss"; +@import "tw-animate-css"; +@import "shadcn/tailwind.css"; +@import "@fontsource-variable/geist"; + +@custom-variant dark (&:is(.dark *)); + +@theme inline { + --font-heading: var(--font-sans); + --font-sans: 'Geist Variable', sans-serif; + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --color-foreground: var(--foreground); + --color-background: var(--background); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); +} + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } + html { + @apply font-sans; + } +} +.tui-scroll::-webkit-scrollbar { width: 4px; } +.tui-scroll::-webkit-scrollbar-track { background: transparent; } +.tui-scroll::-webkit-scrollbar-thumb { background: oklch(1 0 0 / 15%); border-radius: 0; } diff --git a/lazer/cardano/hermes/ui/src/lib/utils.ts b/lazer/cardano/hermes/ui/src/lib/utils.ts new file mode 100644 index 00000000..bd0c391d --- /dev/null +++ b/lazer/cardano/hermes/ui/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/lazer/cardano/hermes/ui/src/main.tsx b/lazer/cardano/hermes/ui/src/main.tsx new file mode 100644 index 00000000..2c36773b --- /dev/null +++ b/lazer/cardano/hermes/ui/src/main.tsx @@ -0,0 +1,14 @@ +import { StrictMode } from "react" +import { createRoot } from "react-dom/client" + +import "./index.css" +import App from "./App.tsx" +import { ThemeProvider } from "@/components/theme-provider.tsx" + +createRoot(document.getElementById("root")!).render( + + + + + +) diff --git a/lazer/cardano/hermes/ui/src/pages/HistoryPage.tsx b/lazer/cardano/hermes/ui/src/pages/HistoryPage.tsx new file mode 100644 index 00000000..b19240a6 --- /dev/null +++ b/lazer/cardano/hermes/ui/src/pages/HistoryPage.tsx @@ -0,0 +1,152 @@ +import { useState } from "react" +import { Link } from "react-router-dom" +import type { MarketHistoryEntry } from "@/types/market" +import { TuiPanel } from "@/components/TuiPanel" +import { Input } from "@/components/ui/input" +import { Button } from "@/components/ui/button" + +// In development, Vite proxies /api → http://localhost:8080 (see vite.config.ts). +// Override with VITE_API_URL for production. +const API_BASE = (import.meta.env.VITE_API_URL as string | undefined) ?? "" + +function formatTime(ts: number): string { + return new Date(ts).toLocaleTimeString("en-GB") +} + +function formatUsd(v: number): string { + return `$${Math.round(v).toLocaleString()}` +} + +function shortId(id: string): string { + return id.length > 8 ? id.slice(0, 8) + "…" : id +} + +export function HistoryPage() { + const [address, setAddress] = useState("") + const [entries, setEntries] = useState([]) + const [loading, setLoading] = useState(false) + const [error, setError] = useState(null) + const [loaded, setLoaded] = useState(false) + + async function load() { + setLoading(true) + setError(null) + try { + const params = address ? `?address=${encodeURIComponent(address)}` : "" + const res = await fetch(`${API_BASE}/api/markets/history${params}`) + if (!res.ok) throw new Error(`HTTP ${res.status}`) + const data = (await res.json()) as MarketHistoryEntry[] + setEntries(data) + setLoaded(true) + } catch (err) { + setError(err instanceof Error ? err.message : "fetch failed") + } finally { + setLoading(false) + } + } + + function handleKeyDown(e: React.KeyboardEvent) { + if (e.key === "Enter") void load() + } + + return ( +
+
+ + ← LIVE MARKET + + + + PAST MARKETS + +
+ +
+ +
+ address: + setAddress(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="addr_1 … or leave empty" + className="h-7 w-64 rounded-none border-border font-mono text-xs" + /> + +
+ + {error &&
! {error}
} + + {loaded && ( + <> + {/* Header row */} +
+ MARKET + START + END + STRIKE + FINAL + OUTCOME + YOU +
+ + {entries.length === 0 && ( +
+ no markets found +
+ )} + + {entries.map((entry) => { + const pos = entry.userPosition + const isUp = entry.outcome === "UP" + + return ( +
+ + {shortId(entry.marketId)} + + + {formatTime(entry.startTime)} + + + {formatTime(entry.endTime)} + + {formatUsd(entry.strikePrice)} + {formatUsd(entry.finalBtcPrice)} + + {entry.outcome} {isUp ? "▲" : "▼"} + + {pos ? ( + + {pos.result} {pos.pnl >= 0 ? "+" : ""} + {pos.pnl.toFixed(2)} + + ) : ( + + )} +
+ ) + })} + + )} +
+
+
+ ) +} diff --git a/lazer/cardano/hermes/ui/src/types/market.ts b/lazer/cardano/hermes/ui/src/types/market.ts new file mode 100644 index 00000000..f17bf89f --- /dev/null +++ b/lazer/cardano/hermes/ui/src/types/market.ts @@ -0,0 +1,93 @@ +// Keep in sync with server/src/types.ts + +export interface Market { + id: string // future: on-chain market ID (uint256) + startTime: number // ms timestamp — future: from block.timestamp at creation + endTime: number // ms timestamp — future: startTime + duration from contract + strikePrice: number // future: read from contract's stored strike at creation +} + +export type Side = "UP" | "DOWN" +export type Action = "BUY" | "SELL" +export type MarketOutcome = "UP" | "DOWN" +export type UserResult = "WON" | "LOST" + +export interface UserPosition { + side: Side + quantity: number + avgPrice: number // price paid per share (0–1) + result: UserResult + pnl: number +} + +export interface MarketHistoryEntry { + marketId: string + startTime: number // ms + endTime: number // ms + strikePrice: number + finalBtcPrice: number + outcome: MarketOutcome + userPosition: UserPosition | null +} + +export interface PriceTick { + timestamp: number + btcPriceStr: string // display-ready decimal string, e.g. "67543.21" (BigNumber-computed) + btcPriceRaw: string // raw Pyth integer string, e.g. "6754321000000" + exponent: number // e.g. -8; actual = btcPriceRaw * 10^exponent +} + +export interface Order { + id: string + timestamp: number + side: Side + action: Action + price: number // 0–1 probability price of the bet position + quantity: number + ownerAddress: string // plain string; format determined by backend/wallet +} + +export interface Fill { + id: string + timestamp: number + side: Side + quantity: number + price: number + ownerAddress: string +} + +export interface PositionSummary { + upContracts: number + upAvgPrice: number + downContracts: number + downAvgPrice: number +} + +export interface RollingAverages { + upBuyAvg: number + upSellAvg: number + downBuyAvg: number + downSellAvg: number +} + +// ── Server → Client ─────────────────────────────────────────────────────────── + +export type ServerMessage = + | { type: "connected"; data: { market: Market } } + | { type: "market_started"; data: { market: Market } } + | { type: "price_tick"; data: PriceTick } + | { type: "order"; data: Order } + | { type: "fill"; data: Fill } + | { type: "position_summary"; data: PositionSummary } + | { type: "rolling_averages"; data: RollingAverages } + +// ── Client → Server ─────────────────────────────────────────────────────────── + +export interface PlaceOrderPayload { + side: Side + action: Action + price: number + quantity: number +} + +export type ClientMessage = { type: "place_order"; data: PlaceOrderPayload } diff --git a/lazer/cardano/hermes/ui/tsconfig.app.json b/lazer/cardano/hermes/ui/tsconfig.app.json new file mode 100644 index 00000000..a1323130 --- /dev/null +++ b/lazer/cardano/hermes/ui/tsconfig.app.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} diff --git a/lazer/cardano/hermes/ui/tsconfig.json b/lazer/cardano/hermes/ui/tsconfig.json new file mode 100644 index 00000000..fec8c8e5 --- /dev/null +++ b/lazer/cardano/hermes/ui/tsconfig.json @@ -0,0 +1,13 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/lazer/cardano/hermes/ui/tsconfig.node.json b/lazer/cardano/hermes/ui/tsconfig.node.json new file mode 100644 index 00000000..8a67f62f --- /dev/null +++ b/lazer/cardano/hermes/ui/tsconfig.node.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/lazer/cardano/hermes/ui/vite.config.ts b/lazer/cardano/hermes/ui/vite.config.ts new file mode 100644 index 00000000..c8c5e7ef --- /dev/null +++ b/lazer/cardano/hermes/ui/vite.config.ts @@ -0,0 +1,27 @@ +import path from "path" +import tailwindcss from "@tailwindcss/vite" +import react from "@vitejs/plugin-react" +import { defineConfig } from "vite" + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), tailwindcss()], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, + server: { + proxy: { + // Forwards /ws → ws://localhost:8080 so the UI avoids CORS issues in dev. + // VITE_WS_URL defaults to "ws://localhost:8080/ws" which uses this proxy. + "/ws": { + target: "ws://localhost:8080", + ws: true, + }, + "/api": { + target: "http://localhost:8080", + }, + }, + }, +})