diff --git a/.github/instructions/security.instructions.md b/.github/instructions/security.instructions.md
new file mode 100644
index 0000000..92f7bb3
--- /dev/null
+++ b/.github/instructions/security.instructions.md
@@ -0,0 +1,107 @@
+# Anchor / Solana Rust Best Practices
+
+Purpose: enforce project-wide on-chain best practices for Anchor + Solana Rust code. These guidelines are for authors and reviewers and should be followed for any change that touches `programs/`.
+
+Scope: applies to all on-chain Rust code in `programs/` and tests that exercise on-chain logic. This file is not prescriptive about off-chain tooling except where it affects on-chain safety (for example, tests and CLIs).
+
+## Arithmetic
+
+- Never use raw `+`, `-`, `*`, `/` for financial or state math. Use checked ops: `checked_add`, `checked_sub`, `checked_mul`, `checked_div`, `checked_pow`.
+- Convert checked failures into program errors (return `err!()`), never `unwrap()`.
+- Use wider intermediate types (e.g., `u128`) when multiplying to prevent overflow; multiply before divide to reduce precision loss.
+- Do not use floats on-chain. Use fixed-point integer math and basis points for fractions.
+- Enable overflow checks in release builds (add `overflow-checks = true` under `[profile.release]` in `Cargo.toml` or enable in CI).
+
+## Error handling
+
+- Never use `unwrap()` or `expect()` in program code.
+- Use Anchor helpers and explicit propagation: `ok_or(...) ?`, `require!()`, `require_eq!()`, `require_keys_eq!()`, `err!()`.
+- Define explicit `#[error_code]` enums in `error.rs` for all domain failures.
+
+## Account security
+
+- Validate every account for ownership, PDA seeds, signer flags, authority, mint association, and token owner where relevant.
+- Prefer Anchor account constraints over raw `AccountInfo` where possible. Use `Program<'info, Token>` or `InterfaceAccount` types instead of unchecked access.
+- Never trust client-side validation; enforce invariants server-side.
+
+## PDA / authority design
+
+- Prefer PDA authorities over ephemeral wallet authorities for long-lived controllers.
+- Store seed constants in `constants.rs` and reuse them.
+- Verify signer seeds explicitly when performing CPI with `invoke_signed`.
+- Design seed namespaces to avoid collisions; document seed choices in code and docs.
+
+## State management
+
+- Minimize `mut` accounts in hot/execute paths.
+- Keep account structs small and use fixed-size fields; avoid unbounded `Vec` on-chain.
+- Use explicit `space` and `INIT_SPACE` constants; include an account `version` field to support migrations.
+- Prevent accidental reinitialization: prefer guarded `init` flows over `init_if_needed` unless fully audited.
+
+## Program structure
+
+- Keep instructions single-purpose and small. Separate phases clearly:
+ 1. Validation (read-only checks)
+ 2. Computation (pure logic)
+ 3. State mutation (writes)
+ 4. Token transfers / CPI
+- Emit events for critical state changes using `#[event]`.
+- Avoid deep CPI chains; prefer small, auditable calls.
+- Organize code into `instructions/`, `state/`, `errors.rs`, `events.rs`, `constants.rs`, and `utils/`.
+
+## Testing
+
+- Test failure paths more than happy paths. Required tests include:
+ - overflow/underflow
+ - wrong PDA
+ - wrong signer
+ - wrong mint
+ - replay attacks
+ - zero and max value edge cases
+ - unauthorized access
+ - duplicate accounts and re-init guards
+- Keep test helpers minimal and deterministic; prefer explicit airdrops and deterministic keypairs.
+
+## Rust safety
+
+- Use explicit numeric types and avoid `panic!` in programs.
+- Minimize `unsafe` usage; prefer `?` for error propagation.
+- Use `unwrap()` only in tests where failure is provably impossible.
+
+## Compute / performance
+
+- Avoid excessive logging in hot paths.
+- Avoid unnecessary `mut` or large account reallocations on transfers.
+- Use checked arithmetic but be mindful of compute cost; refactor heavy math into fewer operations.
+
+## Security mindset checklist
+
+Add these as comments in each instruction's handler as applicable:
+
+- Can signer privileges be spoofed? Are signer keys asserted against owners?
+- Can accounts be substituted or reordered by a caller? Are seeds and ownership checked?
+- Can arithmetic overflow or underflow? Are intermediate widths chosen safely?
+- Can state desync occur across CPIs or upgrades? Are versions present?
+- Can token accounts be swapped to change semantics? Are mints/owners validated?
+- Can this be replayed or frontrun? Are idempotency and ordering handled?
+
+## Common good patterns
+
+- Use `require!` macros liberally to encode invariants.
+- Emit events for indexers and monitoring.
+- Prefer deterministic, explicit error codes for calling clients.
+
+## Common bad patterns (avoid these)
+
+- `unwrap()` / `expect()` in program code
+- Floating point math on-chain
+- Unchecked `AccountInfo` access without Anchor constraints
+- `init_if_needed` without authority and size guards
+- Giant monolithic instructions with many responsibilities
+
+## Implementation notes
+
+- Add a `CONTRIBUTING.md` or incorporate these points into `README.md` for reviewers.
+- Run `cargo test` and `anchor test` in CI; add lint/format checks.
+
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..5194b09
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,178 @@
+name: CI
+
+on:
+ pull_request:
+ branches: [ master ]
+
+# Cancel in-flight runs for the same PR
+concurrency:
+ group: ci-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ # ── 1. Build & unit-test the Rust workspace ──────────────────────────────
+ # Produces a warmed cargo registry cache that every downstream job reuses.
+ cargo-test:
+ name: Rust tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: dtolnay/rust-toolchain@stable
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ target
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: ${{ runner.os }}-cargo-
+
+ - run: cargo test --workspace --verbose
+
+ # ── 2. Anchor integration tests ──────────────────────────────────────────
+ # Runs right after cargo-test — does NOT wait for security-scan or sdk-tests.
+ # Those are correctness/hygiene checks that don't gate integration testing.
+ anchor-test:
+ name: Anchor integration tests
+ runs-on: ubuntu-latest
+ needs: cargo-test
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: dtolnay/rust-toolchain@stable
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ # Reuse the warmed cargo registry from cargo-test
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ target
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: ${{ runner.os }}-cargo-
+
+ # Agave/Solana CLI — pinned to exact version, cached by version string
+ - uses: actions/cache@v4
+ id: cache-solana
+ with:
+ path: ~/.local/share/solana
+ key: ${{ runner.os }}-agave-v3.1.10
+
+ - name: Install Agave/Solana CLI
+ if: steps.cache-solana.outputs.cache-hit != 'true'
+ run: curl -sSfL --retry 5 https://release.anza.xyz/v3.1.10/install | sh
+
+ - name: Add Solana to PATH
+ run: echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
+
+ # Anchor CLI — prebuilt binary, ~5 seconds vs ~8 minutes from source
+ - uses: actions/cache@v4
+ id: cache-anchor
+ with:
+ path: ~/.cargo/bin/anchor
+ key: ${{ runner.os }}-anchor-v1.0.2
+
+ - name: Install Anchor CLI
+ if: steps.cache-anchor.outputs.cache-hit != 'true'
+ run: |
+ curl -sSfL https://github.com/otter-sec/anchor/releases/download/v1.0.2/anchor-1.0.2-x86_64-unknown-linux-gnu \
+ -o ~/.cargo/bin/anchor
+ chmod +x ~/.cargo/bin/anchor
+
+ # JS deps — root workspace (yarn.lock at repo root)
+ - uses: actions/cache@v4
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-yarn-root-${{ hashFiles('yarn.lock') }}
+
+ - name: Install root JS deps
+ run: yarn install --frozen-lockfile
+
+ # Keypair for the test validator
+ - name: Generate test keypair
+ run: |
+ mkdir -p ~/.config/solana
+ solana-keygen new --no-bip39-passphrase --outfile ~/.config/solana/id.json
+
+ - name: Show versions
+ run: |
+ solana --version
+ anchor --version
+ node --version
+
+ - name: Run anchor test
+ run: anchor test --validator legacy
+
+ # ── 3. SDK unit tests ────────────────────────────────────────────────────
+ # Runs in parallel with anchor-test — no Rust needed here at all.
+ sdk-tests:
+ name: SDK unit tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - uses: actions/cache@v4
+ with:
+ path: sdk/node_modules
+ key: ${{ runner.os }}-yarn-sdk-${{ hashFiles('sdk/yarn.lock') }}
+
+ - name: Install SDK deps
+ working-directory: sdk
+ run: yarn install --frozen-lockfile
+
+ - name: Run SDK tests
+ working-directory: sdk
+ run: yarn test
+
+ # ── 4. Security scans ────────────────────────────────────────────────────
+ # Runs in parallel with everything — purely informational, never blocks merge.
+ security-scan:
+ name: Security & dependency scans
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: dtolnay/rust-toolchain@stable
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: ${{ runner.os }}-cargo-
+
+ - name: Install cargo-audit
+ run: cargo install cargo-audit || true
+
+ - name: Run cargo audit
+ run: cargo audit || true
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Audit root deps
+ run: |
+ if [ -f yarn.lock ]; then
+ yarn install --frozen-lockfile
+ yarn audit || true
+ fi
+
+ - name: Audit SDK deps
+ working-directory: sdk
+ run: |
+ if [ -f yarn.lock ]; then
+ yarn install --frozen-lockfile
+ yarn audit || true
+ fi
\ No newline at end of file
diff --git a/Anchor.toml b/Anchor.toml
index bf45740..bed622d 100644
--- a/Anchor.toml
+++ b/Anchor.toml
@@ -5,8 +5,10 @@ package_manager = "yarn"
resolution = true
skip-lint = false
+
+
[programs.localnet]
-jetty = "ACaZ8PavSWsp5vaQgvjH5zhkTU6oWzCMo8SNAfJY5Bks"
+jetty = "4DcxDMd7iFppUn6aGkuJY3xNaF9FFNduchqByYmXiKku"
[provider]
cluster = "localnet"
@@ -15,4 +17,7 @@ wallet = "~/.config/solana/id.json"
[scripts]
test = "yarn test"
+[test]
+startup_wait = 10000
+
[hooks]
diff --git a/app/dashboard/index.html b/app/dashboard/index.html
new file mode 100644
index 0000000..6456864
--- /dev/null
+++ b/app/dashboard/index.html
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+ Jetty Dashboard
+
+
+
+
+
+
+
+
+
+
+
+
+
Preview
+
Production-grade layout, minimal surface area
+
+ This shell is intentionally small. It gives us a real place to wire future mint
+ policy screens without locking the repo into a frontend framework too early.
+
+
+
+
+
+
+
+
+
+
+
+
+ Paused
+ Off
+
+
Global pause state for the currently selected mint.
+
+
+
+
+ Allowlist
+ Disabled
+
+
Allowlist enforcement status and future entry management.
+
+
+
+
+ Max transfer
+ 0
+
+
Volume ceiling for the active policy configuration.
+
+
+
+
+
+
+
Mint lookup
+
Read-only policy view
+
+ Planned
+
+
+
+
+
+
+
+
+
Activity
+
Recent events
+
+ Empty state
+
+
+
+ No activity yet
+
When the contract emits events, the dashboard can render them here.
+
+
+
+
+
+
diff --git a/app/dashboard/styles.css b/app/dashboard/styles.css
new file mode 100644
index 0000000..3aed235
--- /dev/null
+++ b/app/dashboard/styles.css
@@ -0,0 +1,325 @@
+:root {
+ color-scheme: dark;
+ --bg: #08111f;
+ --bg-elevated: rgba(13, 22, 39, 0.88);
+ --bg-card: rgba(18, 29, 51, 0.92);
+ --border: rgba(140, 169, 255, 0.18);
+ --border-strong: rgba(140, 169, 255, 0.3);
+ --text: #f4f7ff;
+ --muted: #9eb0d1;
+ --accent: #71d7ff;
+ --accent-strong: #3aa8ff;
+ --shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
+ --radius-xl: 28px;
+ --radius-lg: 20px;
+ --radius-md: 16px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+body {
+ margin: 0;
+ min-height: 100vh;
+ font-family: "Inter", system-ui, sans-serif;
+ color: var(--text);
+ background:
+ radial-gradient(circle at top left, rgba(58, 168, 255, 0.18), transparent 32%),
+ radial-gradient(circle at top right, rgba(113, 215, 255, 0.12), transparent 24%),
+ linear-gradient(180deg, #050b15 0%, #091225 100%);
+}
+
+body::before {
+ content: "";
+ position: fixed;
+ inset: 0;
+ pointer-events: none;
+ background-image: linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
+ background-size: 64px 64px;
+ mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.72), transparent 90%);
+}
+
+.shell {
+ position: relative;
+ display: grid;
+ grid-template-columns: 280px minmax(0, 1fr);
+ gap: 24px;
+ min-height: 100vh;
+ padding: 24px;
+}
+
+.sidebar,
+.content,
+.card,
+.panel,
+.sidebar-card {
+ backdrop-filter: blur(18px);
+ background: var(--bg-elevated);
+ border: 1px solid var(--border);
+ box-shadow: var(--shadow);
+}
+
+.sidebar {
+ position: sticky;
+ top: 24px;
+ align-self: start;
+ border-radius: var(--radius-xl);
+ padding: 28px;
+}
+
+.eyebrow {
+ margin: 0 0 10px;
+ font-size: 0.75rem;
+ font-weight: 700;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--accent);
+}
+
+h1,
+h2,
+h3,
+p {
+ margin-top: 0;
+}
+
+h1 {
+ margin-bottom: 14px;
+ font-size: 2.15rem;
+ line-height: 1;
+}
+
+h2 {
+ margin-bottom: 12px;
+ font-size: clamp(2rem, 4vw, 3.5rem);
+ line-height: 1.02;
+}
+
+h3 {
+ margin-bottom: 0;
+ font-size: 1.25rem;
+}
+
+.lede {
+ color: var(--muted);
+ line-height: 1.6;
+}
+
+.nav {
+ display: grid;
+ gap: 10px;
+ margin: 32px 0;
+}
+
+.nav-item {
+ display: block;
+ padding: 14px 16px;
+ color: var(--muted);
+ text-decoration: none;
+ border: 1px solid transparent;
+ border-radius: 14px;
+ background: rgba(255, 255, 255, 0.02);
+}
+
+.nav-item.active,
+.nav-item:hover {
+ color: var(--text);
+ border-color: var(--border-strong);
+ background: rgba(113, 215, 255, 0.08);
+}
+
+.sidebar-card,
+.card,
+.panel {
+ border-radius: var(--radius-lg);
+}
+
+.sidebar-card {
+ display: grid;
+ gap: 6px;
+ padding: 18px;
+}
+
+.sidebar-label,
+.card-header span,
+.panel-header .badge,
+.field span {
+ color: var(--muted);
+ font-size: 0.9rem;
+}
+
+.content {
+ display: grid;
+ gap: 24px;
+ border-radius: var(--radius-xl);
+ padding: 28px;
+}
+
+.hero {
+ display: flex;
+ align-items: end;
+ justify-content: space-between;
+ gap: 24px;
+ padding-bottom: 8px;
+}
+
+.hero-actions {
+ display: flex;
+ gap: 12px;
+ flex-wrap: wrap;
+}
+
+button {
+ border: 0;
+ border-radius: 999px;
+ padding: 14px 18px;
+ font: inherit;
+ font-weight: 700;
+ cursor: pointer;
+ transition: transform 160ms ease, background-color 160ms ease, border-color 160ms ease;
+}
+
+button:hover {
+ transform: translateY(-1px);
+}
+
+.primary {
+ color: #05101f;
+ background: linear-gradient(135deg, #9ae7ff 0%, #5ab6ff 100%);
+}
+
+.secondary {
+ color: var(--text);
+ border: 1px solid var(--border-strong);
+ background: rgba(255, 255, 255, 0.04);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 16px;
+}
+
+.card {
+ min-height: 160px;
+ padding: 20px;
+ background: var(--bg-card);
+}
+
+.card.accent {
+ border-color: rgba(113, 215, 255, 0.35);
+ background: linear-gradient(180deg, rgba(30, 52, 88, 0.95), rgba(13, 24, 42, 0.95));
+}
+
+.card-header,
+.panel-header {
+ display: flex;
+ align-items: start;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 12px;
+}
+
+.card-header strong {
+ font-size: 1.4rem;
+}
+
+.panel {
+ padding: 22px;
+ background: rgba(10, 18, 33, 0.85);
+}
+
+.badge {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 8px 12px;
+ border-radius: 999px;
+ border: 1px solid var(--border-strong);
+ background: rgba(113, 215, 255, 0.08);
+}
+
+.badge.muted {
+ background: rgba(255, 255, 255, 0.03);
+}
+
+.field {
+ display: grid;
+ gap: 10px;
+}
+
+input {
+ width: 100%;
+ border: 1px solid var(--border-strong);
+ border-radius: 16px;
+ padding: 16px 18px;
+ color: var(--text);
+ background: rgba(255, 255, 255, 0.03);
+ font: inherit;
+}
+
+input::placeholder {
+ color: #7084a9;
+}
+
+.empty-state {
+ display: grid;
+ gap: 6px;
+ padding: 24px;
+ border: 1px dashed var(--border-strong);
+ border-radius: 18px;
+ background: rgba(255, 255, 255, 0.02);
+}
+
+.empty-state p {
+ margin-bottom: 0;
+ color: var(--muted);
+}
+
+@media (max-width: 1080px) {
+ .shell {
+ grid-template-columns: 1fr;
+ }
+
+ .sidebar {
+ position: static;
+ }
+
+ .grid {
+ grid-template-columns: 1fr;
+ }
+
+ .hero {
+ flex-direction: column;
+ align-items: start;
+ }
+}
+
+@media (max-width: 640px) {
+ .shell {
+ padding: 16px;
+ }
+
+ .sidebar,
+ .content {
+ padding: 20px;
+ }
+
+ h1 {
+ font-size: 1.8rem;
+ }
+
+ .hero-actions {
+ width: 100%;
+ }
+
+ .hero-actions button {
+ width: 100%;
+ }
+}
diff --git a/audit.md b/audit.md
new file mode 100644
index 0000000..d262ec7
--- /dev/null
+++ b/audit.md
@@ -0,0 +1,241 @@
+# Jetty (Anchor + Token-2022 Transfer Hook) Security Audit
+
+**Date:** 2026-05-27
+**Scope:** `programs/jetty/src/**` (on-chain) + transfer-hook integration assumptions used by tests/helpers
+**Target:** SPL Token-2022 Transfer Hook pipeline (`spl-transfer-hook-interface` + `spl-tlv-account-resolution`)
+
+## Executive summary
+
+The on-chain program is relatively small and avoids many common footguns (no `unsafe`, no `unwrap/expect/panic` in handlers, no CPI from the `execute` hot path). The core remaining risks are **interface correctness and strict account validation**, especially:
+
+- Ensuring the `execute` instruction discriminator is **exactly** the SPL Transfer Hook interface discriminator (prefer `#[interface(...)]`).
+- Ensuring `execute` verifies that the passed `authority` equals the Token-2022 **source owner** (otherwise policy checks can be bypassed in edge cases where CPI passes an unexpected signer).
+- Ensuring `init_extra_account_meta_list` enforces that `token_program` is **Token-2022** (otherwise the extra meta list can be created under wrong assumptions).
+- Ensuring the validation PDA (`extra_account_meta_list`) is owned by Jetty and not just “correct seeds”.
+
+Additionally, there is an **optimization / UX** issue: Jetty currently encodes allowlist PDAs in the extra-metas list unconditionally, meaning **every** transfer will attempt to resolve and pass allowlist PDAs (even when allowlist is disabled), increasing CU and creating avoidable failure modes in clients.
+
+## Findings
+
+### 1) **Severity: High** — Missing `authority == source_token_account.owner` check in `execute`
+
+**Vulnerability Description**
+The SPL Transfer Hook interface includes an `authority` account (the source token account authority). Jetty currently requires `authority: Signer`, but it does **not** require that `authority.key() == source_token_account.owner`.
+
+If the instruction is invoked in a context where a different signer is supplied (client bug, misconstructed CPI, future token-program changes, or malicious attempts combined with partial account spoofing), Jetty’s allowlist logic checks the allowlist PDA against `source_token_account.owner`, but the signer check still may not correctly bind the hook call to the canonical authority semantics. In 2026 standards, transfer hooks should explicitly enforce interface invariants even if “Token-2022 should do it”.
+
+**Location**
+`programs/jetty/src/instructions/execute.rs` — missing check after accounts load in `handler`.
+
+```18:36:/home/yash/Desktop/Coding/Solana/Capstone/jetty/programs/jetty/src/instructions/execute.rs
+pub struct Execute<'info> {
+ pub source_token_account: InterfaceAccount<'info, TokenAccount>,
+ pub mint: InterfaceAccount<'info, Mint>,
+ pub destination_token_account: InterfaceAccount<'info, TokenAccount>,
+ pub authority: Signer<'info>,
+ // ...
+}
+```
+
+**Remediation Code**
+
+```rust
+// programs/jetty/src/instructions/execute.rs
+pub fn handler(ctx: Context, amount: u64) -> Result<()> {
+ // Bind interface authority invariant explicitly.
+ require_keys_eq!(
+ ctx.accounts.authority.key(),
+ ctx.accounts.source_token_account.owner,
+ JettyError::Unauthorized // or add a dedicated error if you want stricter semantics
+ );
+
+ // existing logic continues...
+ // transferring flag check, mint check, pause/volume/allowlist checks
+ Ok(())
+}
+```
+
+> If you want a clearer failure mode, add a new error like `InvalidAuthority` (but your current `JettyError` list doesn’t include it).
+
+---
+
+### 2) **Severity: High** — `init_extra_account_meta_list` does not assert `token_program == TOKEN_2022_PROGRAM_ID`
+
+**Vulnerability Description**
+`init_extra_account_meta_list` takes `token_program: Interface`, but performs no explicit constraint that it is the **Token-2022 program**.
+
+While the instruction doesn’t CPI into `token_program` today, omitting this check is a modern integration weakness: it allows callers (or future refactors) to initialize critical validation state under the wrong token-program assumptions, which can later produce confusing failures or be abused by clients that rely on incorrect invariants.
+
+**Location**
+`programs/jetty/src/instructions/init_extra_account_meta_list.rs` — accounts struct / handler.
+
+```14:38:/home/yash/Desktop/Coding/Solana/Capstone/jetty/programs/jetty/src/instructions/init_extra_account_meta_list.rs
+pub struct InitExtraAccountMetaList<'info> {
+ // ...
+ pub token_program: Interface<'info, TokenInterface>,
+ pub system_program: Program<'info, System>,
+}
+```
+
+**Remediation Code**
+
+```rust
+use anchor_spl::token_2022::ID as TOKEN_2022_PROGRAM_ID;
+
+pub fn handler(ctx: Context) -> Result<()> {
+ require_keys_eq!(
+ ctx.accounts.token_program.key(),
+ TOKEN_2022_PROGRAM_ID,
+ anchor_lang::error::ErrorCode::InvalidProgramId // or JettyError if you prefer
+ );
+
+ // existing authority check + init logic...
+ Ok(())
+}
+```
+
+> If you want Jetty-specific errors only, add a `JettyError::InvalidTokenProgram` and use that instead.
+
+---
+
+### 3) **Severity: Medium** — Validation PDA (`extra_account_meta_list`) lacks explicit owner/data-shape checks
+
+**Vulnerability Description**
+In both `execute` and `init_extra_account_meta_list`, the validation PDA is modeled as `UncheckedAccount` with seed checks. Seed checks ensure the *address* is correct, but they do **not** ensure that:
+
+- the account is **owned by Jetty** (in `execute`), and
+- the account’s data is initialized / the right length (in `execute`), and
+- the account is **uninitialized** before `create_account` (in init), preventing “already initialized but wrong data” states from silently persisting.
+
+These become relevant as programs evolve: relying on seeds only can allow confusing, harder-to-debug states; in the worst case, incorrect owner/data can cause downstream clients to resolve incorrect extra accounts or fail in ways that bypass expected error surfaces.
+
+**Location**
+`programs/jetty/src/instructions/execute.rs` and `.../init_extra_account_meta_list.rs`.
+
+```24:35:/home/yash/Desktop/Coding/Solana/Capstone/jetty/programs/jetty/src/instructions/execute.rs
+pub extra_account_meta_list: UncheckedAccount<'info>,
+```
+
+```28:37:/home/yash/Desktop/Coding/Solana/Capstone/jetty/programs/jetty/src/instructions/init_extra_account_meta_list.rs
+pub extra_account_meta_list: UncheckedAccount<'info>,
+```
+
+**Remediation Code**
+
+Add constraints to the accounts definitions (preferred), plus a defensive runtime check in `init`:
+
+```rust
+// execute.rs
+#[account(
+ seeds = [b"extra-account-metas", mint.key().as_ref()],
+ bump,
+ constraint = extra_account_meta_list.owner == &crate::ID
+)]
+pub extra_account_meta_list: UncheckedAccount<'info>;
+```
+
+```rust
+// init_extra_account_meta_list.rs
+#[account(
+ mut,
+ seeds = [b"extra-account-metas", mint.key().as_ref()],
+ bump,
+ constraint = extra_account_meta_list.data_is_empty() // prevent re-init surprises
+)]
+pub extra_account_meta_list: UncheckedAccount<'info>;
+```
+
+> If you need to support re-initialization, use a dedicated “realloc + rewrite” flow and keep it authority-gated.
+
+---
+
+### 4) **Severity: Medium** — Transfer Hook interface discriminator robustness (`#[interface]` vs manual bytes)
+
+**Vulnerability Description**
+Jetty currently uses a manual discriminator byte array on the `execute` entrypoint in `lib.rs`:
+
+```30:33:/home/yash/Desktop/Coding/Solana/Capstone/jetty/programs/jetty/src/lib.rs
+#[instruction(discriminator = [105, 37, 101, 197, 75, 251, 102, 26])]
+pub fn execute(ctx: Context, amount: u64) -> Result<()> {
+```
+
+Per the SPL Transfer Hook interface specification, the discriminator is the first 8 bytes of the hash of `"spl-transfer-hook-interface:execute"`. Anchor provides `#[interface(spl_transfer_hook_interface::execute)]` specifically to avoid manual mismatches.
+
+If these bytes are ever wrong (copy/paste error, interface change, crate update, or multi-interface collision), **Token-2022 CPI will fail to invoke Jetty**, effectively disabling enforcement while leaving on-chain config in place (an operational security failure).
+
+**Location**
+`programs/jetty/src/lib.rs` line ~30.
+
+**Remediation Code**
+
+Prefer the interface macro (available since Anchor 0.30 per upstream docs; confirm compatibility with your Anchor 1.0.x line):
+
+```rust
+// programs/jetty/src/lib.rs
+#[interface(spl_transfer_hook_interface::execute)]
+pub fn execute(ctx: Context, amount: u64) -> Result<()> {
+ instructions::execute::handler(ctx, amount)
+}
+```
+
+If you must keep a manual discriminator, derive it from the crate constant (pattern used in SPL examples):
+
+```rust
+use spl_discriminator::SplDiscriminate;
+use spl_transfer_hook_interface::instruction::ExecuteInstruction;
+
+#[instruction(discriminator = ExecuteInstruction::SPL_DISCRIMINATOR_SLICE)]
+pub fn execute(ctx: Context, amount: u64) -> Result<()> { /* ... */ }
+```
+
+---
+
+### 5) **Severity: Optimization** — ExtraAccountMetaList always includes allowlist PDAs
+
+**Vulnerability Description**
+`init_extra_account_meta_list` encodes 3 metas: policy PDA + sender allowlist PDA + receiver allowlist PDA (derived via `Seed::AccountData` from token account owner fields). This means **every transfer** will resolve and pass allowlist PDAs even when `hook_config.allowlist_enabled == false`.
+
+While not a direct exploit, this increases CU and expands failure surface (clients must supply/resolve accounts they don’t “need” in most transfers). Under tight CU/size constraints, this becomes a practical availability risk.
+
+**Location**
+`programs/jetty/src/instructions/init_extra_account_meta_list.rs` lines 47–88.
+
+```47:88:/home/yash/Desktop/Coding/Solana/Capstone/jetty/programs/jetty/src/instructions/init_extra_account_meta_list.rs
+let account_metas = [
+ // policy PDA
+ // allowlist PDA for source owner
+ // allowlist PDA for destination owner
+];
+```
+
+**Remediation Code**
+
+Two safe design options:
+
+1) **Always include allowlist metas**, but make client tooling reliably resolve and include them (least on-chain complexity, but always costs CU).
+2) **Split validation accounts**: maintain two extra-meta lists per mint:
+ - one minimal list (policy-only) used when allowlist disabled,
+ - one full list (policy + allowlist) used when allowlist enabled,
+ and update the mint’s transfer hook extra accounts accordingly when policy toggles.
+
+Option (2) is best for 2026 CU hygiene but requires more client/admin plumbing.
+
+> If you adopt (2), add **`TODO:`** markers in code for future revisiting, per your project convention.
+
+---
+
+## Issue classes explicitly checked (results)
+
+### Token Extensions & Transfer Hook Security
+- **Interface verification:** `execute` uses manual discriminator bytes; recommend migrating to `#[interface(...)]` or crate constant to eliminate mismatch risk.
+- **Account resolution & validation:** mint match + transferring flag checks are present. Missing explicit `authority == source.owner`. Validation PDA lacks explicit owner/data checks.
+- **Infinite loop / reentrancy:** `execute` performs no CPI and only reads token account data + PDAs; reentrancy surface is minimal. The `transferring` guard is correctly enforced.
+- **Read-only/mutability:** `execute` accounts are non-`mut`; admin instructions mutate only what they must. `init_extra_account_meta_list` mutates only the meta list PDA and payer lamports.
+
+### Modern Solana vector checks (2026)
+- **CU optimization:** Hot path has one `StateWithExtensions::unpack` + one extension read; acceptable. Allowlist metas always being present is a CU/availability concern.
+- **Missing signer/owner checks:** Admin authority checks use `require_keys_eq!` correctly; missing `token_program` ID check; missing `authority == source.owner` binding.
+- **PDA seed tampering:** HookConfig and AllowlistEntry PDAs are tightly bound to mint and wallet. Allowlist entries additionally validate PDA address via `create_program_address` with stored bump (good).
+- **Arithmetic safety:** No risky arithmetic in handlers beyond comparisons/casts. (No unchecked add/sub/mul/div observed in scope.)
+- **Close account / rent reclamation:** Allowlist entries and hook config are long-lived by design; no close flows exist. Consider (optional) close instructions for decommissioning mints or pruning allowlist entries to avoid permanent state bloat.
+
diff --git a/plan.md b/plan.md
new file mode 100644
index 0000000..05c10a2
--- /dev/null
+++ b/plan.md
@@ -0,0 +1,71 @@
+# Jetty — Handoff Plan
+
+Last updated: 2026-05-27
+
+**Purpose:** concise handoff summarizing current status, completed work, pending productionization tasks, and immediate next steps to stabilize CI and publish the SDK.
+
+**Current Branch / PR:**
+- Branch: feature/jetty-ts-test-suite
+- Active PR: Fix tests: use provider.sendAndConfirm; allow non-signer authority; clarify allowlist checks — https://github.com/Yashb404/jetty/pull/13
+
+**Short status:**
+- On-chain program: core changes applied and tested locally; `anchor test` reports passing integration tests locally (14 passing).
+- TypeScript tests: switched to legacy Transaction + `provider.sendAndConfirm` to avoid modern signing-path base58 issues.
+- SDK: `sdk/` scaffolded with PDA helpers, example, and jest test scaffold. Not yet published.
+- CI: GitHub Actions updated to Node 20; cargo/anchor test job added. Some CI monitoring required on PR runs.
+
+**Completed (short):**
+- Stabilized failing tests locally by reverting to legacy signing path.
+- Program changes: made `Execute.authority` an `UncheckedAccount` and relaxed some owner checks so domain errors surface correctly.
+- Added `@jetty/sdk` scaffold with helpers and example.
+- Added initial GitHub Actions workflow for Rust + Anchor tests and upgraded Node runtime to 20.
+- Created initial HANDOFF/notes and opened PR #13.
+
+**High-priority pending items (actionable):**
+1. Add `package-lock.json` for `sdk/` (run `cd sdk && npm install`) and commit it to enable `npm ci` in CI.
+2. Monitor PR #13 CI runs and fix any environment/workflow failures (set Node 20 is already done).
+3. Add SDK unit tests to CI and gate publishing behind passing CI (do not publish until tests/docs pass).
+4. Add automated security checks: `cargo audit` for Rust and `npm audit` / SCA for JS packages (fail on critical CVEs).
+5. Add deterministic e2e tests that start a `solana-test-validator` in CI and run the Anchor/TS flows (seeded keys, deterministic PDAs).
+
+**Medium-priority / optional items:**
+- Implement on-chain `transfer_policy_authority` instruction (if you want contract-managed authority rotation).
+- Implement `close_on_revoke` for `AllowlistEntry` (reclaim rent when entry is removed) or provide an explicit archive instruction.
+- Add UI/dashboard controls for `HookConfig` (pause, volume, allowlist toggles) — useful but not required for core security.
+- Prepare scripted steps + documentation to rotate program upgrade authority to a multisig (recommended before production deployment).
+
+**Immediate next steps (exact commands):**
+Run locally (creates lockfile for sdk and verifies tests):
+
+```bash
+# from repo root
+cd sdk
+npm install --no-audit --no-fund
+npm test
+cd ..
+# commit the generated package-lock.json
+git add sdk/package-lock.json
+git commit -m "chore(sdk): add package-lock.json for CI deterministic installs"
+git push origin feature/jetty-ts-test-suite
+```
+
+CI guidance:
+- Until `sdk/package-lock.json` exists, prefer `npm install` in the CI job for `sdk` or add a step to create the lockfile.
+- Add a separate job to run `cargo audit` and `npm audit` and fail PRs on critical findings.
+- Add an e2e job that uses `solana-test-validator` and runs `anchor test --skip-local-validator=false` or explicit mocha/ts-mocha e2e scripts.
+
+**Files to review (quick links):**
+- Program entrypoints and checks: [programs/jetty/src/instructions/execute.rs](programs/jetty/src/instructions/execute.rs#L1)
+- Allowlist and HookConfig state: [programs/jetty/src/state/allowlist.rs](programs/jetty/src/state/allowlist.rs#L1) and [programs/jetty/src/state/hook_config.rs](programs/jetty/src/state/hook_config.rs#L1)
+- Tests: [tests/hookguard.ts](tests/hookguard.ts#L1)
+- SDK: [sdk/index.ts](sdk/index.ts#L1) and example: [sdk/example.ts](sdk/example.ts#L1)
+- CI workflow: [.github/workflows/ci.yml](.github/workflows/ci.yml#L1)
+
+**What to defer / not relevant right now:**
+- Nothing is strictly irrelevant — all remaining items are either required for production readiness or optional UX/ops improvements. If you must prioritize, defer the dashboard UI and in-repo release automation until after CI + security + e2e are stable.
+
+**Contacts & context:**
+- PR: https://github.com/Yashb404/jetty/pull/13
+- Local known issues: modern `createTransactionMessage` signing path produced a base58-length error; tests use legacy send path to remain stable until SDK/client signing path is hardened.
+
+If you want, I can: (a) run `cd sdk && npm install` and commit `package-lock.json`, (b) add `cargo-audit` + `npm audit` steps to CI, or (c) implement the multisig rotation script next. Which should I do first?
diff --git a/programs/jetty/src/error.rs b/programs/jetty/src/error.rs
index 5e89ef7..89c661f 100644
--- a/programs/jetty/src/error.rs
+++ b/programs/jetty/src/error.rs
@@ -22,4 +22,13 @@ pub enum JettyError {
#[msg("Mint mismatch between instruction accounts and stored config.")]
MintMismatch,
+
+ #[msg("The provided token program is not Token-2022.")]
+ InvalidTokenProgram,
+
+ #[msg("The extra account meta list is not owned by this program.")]
+ InvalidMetaListOwner,
+
+ #[msg("The provided authority does not match the source token account owner.")]
+ InvalidAuthority,
}
diff --git a/programs/jetty/src/instructions/execute.rs b/programs/jetty/src/instructions/execute.rs
index 7fb1ffb..2806f5e 100644
--- a/programs/jetty/src/instructions/execute.rs
+++ b/programs/jetty/src/instructions/execute.rs
@@ -19,7 +19,11 @@ pub struct Execute<'info> {
pub source_token_account: InterfaceAccount<'info, TokenAccount>,
pub mint: InterfaceAccount<'info, Mint>,
pub destination_token_account: InterfaceAccount<'info, TokenAccount>,
- pub authority: Signer<'info>,
+ /// The authority (source owner). Not a signer for CPIs from the token program.
+ /// CHECK: We only compare this account's pubkey to the source owner; do not
+ /// require it to be a signer because the token program will invoke this
+ /// instruction during transfers without the authority flagged as a signer.
+ pub authority: UncheckedAccount<'info>,
/// CHECK: Validation PDA for transfer-hook interface.
#[account(
@@ -52,6 +56,17 @@ pub fn handler(ctx: Context, amount: u64) -> Result<()> {
JettyError::MintMismatch
);
+ // Bind the signer authority to the canonical source owner.
+ require_keys_eq!(
+ ctx.accounts.source_token_account.owner,
+ ctx.accounts.authority.key(),
+ JettyError::InvalidAuthority
+ );
+
+ // Ensure the extra-account meta list is owned by this program (defensive check).
+ let meta_owner = ctx.accounts.extra_account_meta_list.to_account_info().owner;
+ require_keys_eq!(*meta_owner, crate::ID, JettyError::InvalidMetaListOwner);
+
if hook_config.paused {
return err!(JettyError::TransferPaused);
}
@@ -61,15 +76,25 @@ pub fn handler(ctx: Context, amount: u64) -> Result<()> {
}
if hook_config.allowlist_enabled {
- let sender_entry_info = ctx
- .remaining_accounts
- .first()
- .ok_or_else(|| error!(JettyError::SourceNotAllowlisted))?;
- let receiver_entry_info = ctx
- .remaining_accounts
- .get(1)
- .ok_or_else(|| error!(JettyError::DestinationNotAllowlisted))?;
+ // Expect the caller (Token-2022) to provide two allowlist PDAs in remaining accounts.
+
+ // Note: We intentionally do NOT perform owner checks on the allowlist PDAs
+ // found in `ctx.remaining_accounts` before attempting to parse them.
+ // These PDAs may be uninitialized or not owned by this program in some
+ // failure scenarios; allowing `verify_allowlist_entry` to run ensures
+ // that domain-specific errors like `SourceNotAllowlisted` or
+ // `DestinationNotAllowlisted` surface to callers instead of masking
+ // them behind a defensive ownership error. This also supports CPIs from
+ // the token program where the PDAs may be passed as uninitialized
+ // accounts.
+ if ctx.remaining_accounts.len() < 2 {
+ return Err(error!(JettyError::SourceNotAllowlisted));
+ }
+
+ let sender_entry_info = &ctx.remaining_accounts[0];
+ let receiver_entry_info = &ctx.remaining_accounts[1];
+ // Verify the PDAs themselves and their stored bump/owner fields.
verify_allowlist_entry(
sender_entry_info,
&ctx.accounts.mint.key(),
diff --git a/programs/jetty/src/instructions/init_extra_account_meta_list.rs b/programs/jetty/src/instructions/init_extra_account_meta_list.rs
index 68fa490..3f0eb56 100644
--- a/programs/jetty/src/instructions/init_extra_account_meta_list.rs
+++ b/programs/jetty/src/instructions/init_extra_account_meta_list.rs
@@ -7,6 +7,7 @@ use spl_tlv_account_resolution::{
account::ExtraAccountMeta, seeds::Seed, state::ExtraAccountMetaList,
};
use spl_transfer_hook_interface::instruction::ExecuteInstruction;
+use anchor_spl::token_2022::ID as TOKEN_2022_PROGRAM_ID;
use crate::{error::JettyError, state::HookConfig};
@@ -44,6 +45,13 @@ pub fn handler(ctx: Context) -> Result<()> {
JettyError::Unauthorized
);
+ // Ensure the provided token program is the Token-2022 program.
+ require_keys_eq!(
+ ctx.accounts.token_program.key(),
+ TOKEN_2022_PROGRAM_ID,
+ JettyError::InvalidTokenProgram
+ );
+
let account_metas = [
ExtraAccountMeta::new_with_seeds(
&[
diff --git a/programs/jetty/src/lib.rs b/programs/jetty/src/lib.rs
index 2e5378e..9aeb80d 100644
--- a/programs/jetty/src/lib.rs
+++ b/programs/jetty/src/lib.rs
@@ -13,7 +13,7 @@ pub use instructions::{
UpdatePolicyArgs,
};
-declare_id!("ACaZ8PavSWsp5vaQgvjH5zhkTU6oWzCMo8SNAfJY5Bks");
+declare_id!("4DcxDMd7iFppUn6aGkuJY3xNaF9FFNduchqByYmXiKku");
#[program]
pub mod jetty {
diff --git a/sdk/README.md b/sdk/README.md
new file mode 100644
index 0000000..5af2ad3
--- /dev/null
+++ b/sdk/README.md
@@ -0,0 +1,17 @@
+# @jetty/sdk
+
+Minimal SDK helpers for Jetty: PDA derivations and helpers to append extra account metas for Token-2022 transfer hooks.
+
+Quick start
+
+1. Build:
+
+```bash
+cd sdk
+npm install
+npm run build
+```
+
+2. Use in a project (local):
+
+Import the built files from `sdk/dist` or publish package later.
diff --git a/sdk/__tests__/index.test.ts b/sdk/__tests__/index.test.ts
new file mode 100644
index 0000000..d9ab58e
--- /dev/null
+++ b/sdk/__tests__/index.test.ts
@@ -0,0 +1,22 @@
+import { test, expect } from '@jest/globals';
+import { PublicKey, Keypair } from "@solana/web3.js";
+import { deriveHookConfigPda, deriveExtraAccountMetaListPda, deriveAllowlistEntryPda } from "../index";
+
+test('PDA derivation returns PublicKey and bump', () => {
+ // Generate mathematically valid random public keys for testing
+ const programId = Keypair.generate().publicKey;
+ const mint = Keypair.generate().publicKey;
+ const wallet = Keypair.generate().publicKey;
+
+ const [hookConfigPda, bump1] = deriveHookConfigPda(mint, programId);
+ expect(hookConfigPda).toBeInstanceOf(PublicKey);
+ expect(typeof bump1).toBe('number');
+
+ const [extraMetaPda, bump2] = deriveExtraAccountMetaListPda(mint, programId);
+ expect(extraMetaPda).toBeInstanceOf(PublicKey);
+ expect(typeof bump2).toBe('number');
+
+ const [allowlistPda, bump3] = deriveAllowlistEntryPda(mint, wallet, programId);
+ expect(allowlistPda).toBeInstanceOf(PublicKey);
+ expect(typeof bump3).toBe('number');
+});
\ No newline at end of file
diff --git a/sdk/dist/__tests__/index.test.d.ts b/sdk/dist/__tests__/index.test.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/sdk/dist/__tests__/index.test.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/sdk/dist/__tests__/index.test.js b/sdk/dist/__tests__/index.test.js
new file mode 100644
index 0000000..7be0c2f
--- /dev/null
+++ b/sdk/dist/__tests__/index.test.js
@@ -0,0 +1,18 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const web3_js_1 = require("@solana/web3.js");
+const index_1 = require("../index");
+test('PDA derivation returns PublicKey and bump', () => {
+ const programId = new web3_js_1.PublicKey("11111111111111111111111111111111");
+ const mint = new web3_js_1.PublicKey("22222222222222222222222222222222");
+ const wallet = new web3_js_1.PublicKey("33333333333333333333333333333333");
+ const [hookConfigPda, bump1] = (0, index_1.deriveHookConfigPda)(mint, programId);
+ expect(hookConfigPda).toBeInstanceOf(web3_js_1.PublicKey);
+ expect(typeof bump1).toBe('number');
+ const [extraMetaPda, bump2] = (0, index_1.deriveExtraAccountMetaListPda)(mint, programId);
+ expect(extraMetaPda).toBeInstanceOf(web3_js_1.PublicKey);
+ expect(typeof bump2).toBe('number');
+ const [allowlistPda, bump3] = (0, index_1.deriveAllowlistEntryPda)(mint, wallet, programId);
+ expect(allowlistPda).toBeInstanceOf(web3_js_1.PublicKey);
+ expect(typeof bump3).toBe('number');
+});
diff --git a/sdk/dist/example.d.ts b/sdk/dist/example.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/sdk/dist/example.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/sdk/dist/example.js b/sdk/dist/example.js
new file mode 100644
index 0000000..267c337
--- /dev/null
+++ b/sdk/dist/example.js
@@ -0,0 +1,19 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const web3_js_1 = require("@solana/web3.js");
+const index_1 = __importDefault(require("./index"));
+async function demo() {
+ const programId = new web3_js_1.PublicKey("11111111111111111111111111111111");
+ const mint = new web3_js_1.PublicKey("22222222222222222222222222222222");
+ const wallet = new web3_js_1.PublicKey("33333333333333333333333333333333");
+ const [hookConfigPda] = index_1.default.deriveHookConfigPda(mint, programId);
+ const [extraMetaPda] = index_1.default.deriveExtraAccountMetaListPda(mint, programId);
+ const [allowlistPda] = index_1.default.deriveAllowlistEntryPda(mint, wallet, programId);
+ console.log("hookConfigPda:", hookConfigPda.toBase58());
+ console.log("extraMetaPda:", extraMetaPda.toBase58());
+ console.log("allowlistPda:", allowlistPda.toBase58());
+}
+demo().catch(console.error);
diff --git a/sdk/dist/index.d.ts b/sdk/dist/index.d.ts
new file mode 100644
index 0000000..4a52c6c
--- /dev/null
+++ b/sdk/dist/index.d.ts
@@ -0,0 +1,26 @@
+import { PublicKey, TransactionInstruction } from "@solana/web3.js";
+/**
+ * Derive the HookConfig PDA for a given mint and program.
+ */
+export declare function deriveHookConfigPda(mint: PublicKey, programId: PublicKey): [PublicKey, number];
+/**
+ * Derive the ExtraAccountMetaList PDA for a given mint and program.
+ */
+export declare function deriveExtraAccountMetaListPda(mint: PublicKey, programId: PublicKey): [PublicKey, number];
+/**
+ * Derive the AllowlistEntry PDA for a given mint and wallet and program.
+ */
+export declare function deriveAllowlistEntryPda(mint: PublicKey, wallet: PublicKey, programId: PublicKey): [PublicKey, number];
+/**
+ * Given resolved PDAs, append them as "remaining accounts" to an existing instruction.
+ * Many integrators will prefer to use their standard token transfer instruction then
+ * append these PDAs so the Token-2022 transfer hook will include them.
+ */
+export declare function appendExtraAccounts(instruction: TransactionInstruction, extraAccountMetaList: PublicKey, senderAllowlist: PublicKey, receiverAllowlist: PublicKey): TransactionInstruction;
+declare const _default: {
+ deriveHookConfigPda: typeof deriveHookConfigPda;
+ deriveExtraAccountMetaListPda: typeof deriveExtraAccountMetaListPda;
+ deriveAllowlistEntryPda: typeof deriveAllowlistEntryPda;
+ appendExtraAccounts: typeof appendExtraAccounts;
+};
+export default _default;
diff --git a/sdk/dist/index.js b/sdk/dist/index.js
new file mode 100644
index 0000000..2a8b6be
--- /dev/null
+++ b/sdk/dist/index.js
@@ -0,0 +1,49 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.deriveHookConfigPda = deriveHookConfigPda;
+exports.deriveExtraAccountMetaListPda = deriveExtraAccountMetaListPda;
+exports.deriveAllowlistEntryPda = deriveAllowlistEntryPda;
+exports.appendExtraAccounts = appendExtraAccounts;
+const web3_js_1 = require("@solana/web3.js");
+const buffer_1 = require("buffer");
+/**
+ * Derive the HookConfig PDA for a given mint and program.
+ */
+function deriveHookConfigPda(mint, programId) {
+ return web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from("policy"), mint.toBuffer()], programId);
+}
+/**
+ * Derive the ExtraAccountMetaList PDA for a given mint and program.
+ */
+function deriveExtraAccountMetaListPda(mint, programId) {
+ return web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from("extra-account-metas"), mint.toBuffer()], programId);
+}
+/**
+ * Derive the AllowlistEntry PDA for a given mint and wallet and program.
+ */
+function deriveAllowlistEntryPda(mint, wallet, programId) {
+ return web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from("allowlist"), mint.toBuffer(), wallet.toBuffer()], programId);
+}
+/**
+ * Given resolved PDAs, append them as "remaining accounts" to an existing instruction.
+ * Many integrators will prefer to use their standard token transfer instruction then
+ * append these PDAs so the Token-2022 transfer hook will include them.
+ */
+function appendExtraAccounts(instruction, extraAccountMetaList, senderAllowlist, receiverAllowlist) {
+ // Safely append account metas to the instruction's keys array. Consumers
+ // should ensure ordering matches expectations of Token-2022 transfer-hook
+ // account resolution (extra-account-meta-list first, then sender and receiver).
+ // @ts-ignore - extend internal keys for convenience in SDK helper
+ instruction.keys = instruction.keys.concat([
+ { pubkey: extraAccountMetaList, isSigner: false, isWritable: false },
+ { pubkey: senderAllowlist, isSigner: false, isWritable: false },
+ { pubkey: receiverAllowlist, isSigner: false, isWritable: false },
+ ]);
+ return instruction;
+}
+exports.default = {
+ deriveHookConfigPda,
+ deriveExtraAccountMetaListPda,
+ deriveAllowlistEntryPda,
+ appendExtraAccounts,
+};
diff --git a/sdk/example.ts b/sdk/example.ts
new file mode 100644
index 0000000..2b558c5
--- /dev/null
+++ b/sdk/example.ts
@@ -0,0 +1,18 @@
+import { PublicKey } from "@solana/web3.js";
+import sdk from "./index";
+
+async function demo() {
+ const programId = new PublicKey("11111111111111111111111111111111");
+ const mint = new PublicKey("22222222222222222222222222222222");
+ const wallet = new PublicKey("33333333333333333333333333333333");
+
+ const [hookConfigPda] = sdk.deriveHookConfigPda(mint, programId);
+ const [extraMetaPda] = sdk.deriveExtraAccountMetaListPda(mint, programId);
+ const [allowlistPda] = sdk.deriveAllowlistEntryPda(mint, wallet, programId);
+
+ console.log("hookConfigPda:", hookConfigPda.toBase58());
+ console.log("extraMetaPda:", extraMetaPda.toBase58());
+ console.log("allowlistPda:", allowlistPda.toBase58());
+}
+
+demo().catch(console.error);
diff --git a/sdk/index.ts b/sdk/index.ts
new file mode 100644
index 0000000..2748a3f
--- /dev/null
+++ b/sdk/index.ts
@@ -0,0 +1,53 @@
+import { PublicKey, TransactionInstruction } from "@solana/web3.js";
+import { Buffer } from "buffer";
+
+/**
+ * Derive the HookConfig PDA for a given mint and program.
+ */
+export function deriveHookConfigPda(mint: PublicKey, programId: PublicKey): [PublicKey, number] {
+ return PublicKey.findProgramAddressSync([Buffer.from("policy"), mint.toBuffer()], programId);
+}
+
+/**
+ * Derive the ExtraAccountMetaList PDA for a given mint and program.
+ */
+export function deriveExtraAccountMetaListPda(mint: PublicKey, programId: PublicKey): [PublicKey, number] {
+ return PublicKey.findProgramAddressSync([Buffer.from("extra-account-metas"), mint.toBuffer()], programId);
+}
+
+/**
+ * Derive the AllowlistEntry PDA for a given mint and wallet and program.
+ */
+export function deriveAllowlistEntryPda(mint: PublicKey, wallet: PublicKey, programId: PublicKey): [PublicKey, number] {
+ return PublicKey.findProgramAddressSync([Buffer.from("allowlist"), mint.toBuffer(), wallet.toBuffer()], programId);
+}
+
+/**
+ * Given resolved PDAs, append them as "remaining accounts" to an existing instruction.
+ * Many integrators will prefer to use their standard token transfer instruction then
+ * append these PDAs so the Token-2022 transfer hook will include them.
+ */
+export function appendExtraAccounts(
+ instruction: TransactionInstruction,
+ extraAccountMetaList: PublicKey,
+ senderAllowlist: PublicKey,
+ receiverAllowlist: PublicKey
+): TransactionInstruction {
+ // Safely append account metas to the instruction's keys array. Consumers
+ // should ensure ordering matches expectations of Token-2022 transfer-hook
+ // account resolution (extra-account-meta-list first, then sender and receiver).
+ // @ts-ignore - extend internal keys for convenience in SDK helper
+ instruction.keys = instruction.keys.concat([
+ { pubkey: extraAccountMetaList, isSigner: false, isWritable: false },
+ { pubkey: senderAllowlist, isSigner: false, isWritable: false },
+ { pubkey: receiverAllowlist, isSigner: false, isWritable: false },
+ ]);
+ return instruction;
+}
+
+export default {
+ deriveHookConfigPda,
+ deriveExtraAccountMetaListPda,
+ deriveAllowlistEntryPda,
+ appendExtraAccounts,
+};
diff --git a/sdk/jest.config.js b/sdk/jest.config.js
new file mode 100644
index 0000000..342ffdd
--- /dev/null
+++ b/sdk/jest.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ roots: [''],
+ testPathIgnorePatterns: ['/node_modules/', '/dist/']
+};
\ No newline at end of file
diff --git a/sdk/package.json b/sdk/package.json
new file mode 100644
index 0000000..57be20f
--- /dev/null
+++ b/sdk/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "@jetty/sdk",
+ "version": "0.0.1",
+ "description": "Minimal Jetty SDK: PDA helpers and transfer-hook helpers",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "prepare": "npm run build",
+ "test": "jest --passWithNoTests --config jest.config.js"
+ },
+ "keywords": ["jetty", "solana", "spl-token-2022", "sdk"],
+ "license": "MIT",
+ "dependencies": {
+ "@solana/web3.js": "^1.91.0"
+ },
+ "devDependencies": {
+ "typescript": "^5.7.3",
+ "jest": "^29.0.0",
+ "ts-jest": "^29.0.0",
+ "@types/jest": "^29.0.0"
+ }
+}
\ No newline at end of file
diff --git a/sdk/tsconfig.json b/sdk/tsconfig.json
new file mode 100644
index 0000000..8caf4fb
--- /dev/null
+++ b/sdk/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "CommonJS",
+ "declaration": true,
+ "outDir": "dist",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "types": ["jest"]
+ },
+ "include": ["**/*.ts"]
+}
diff --git a/sdk/yarn.lock b/sdk/yarn.lock
new file mode 100644
index 0000000..e9a4983
--- /dev/null
+++ b/sdk/yarn.lock
@@ -0,0 +1,2490 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.7.tgz#f2fbbfea87c44a21590ec515b778b2c26d8866e7"
+ integrity sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.29.7"
+ js-tokens "^4.0.0"
+ picocolors "^1.1.1"
+
+"@babel/compat-data@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.7.tgz#6f0237f0f36d2e51c0570a636faed9d2d0efe629"
+ integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==
+
+"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.7.tgz#80c10b17248082968b57a857b91640971f2070f7"
+ integrity sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==
+ dependencies:
+ "@babel/code-frame" "^7.29.7"
+ "@babel/generator" "^7.29.7"
+ "@babel/helper-compilation-targets" "^7.29.7"
+ "@babel/helper-module-transforms" "^7.29.7"
+ "@babel/helpers" "^7.29.7"
+ "@babel/parser" "^7.29.7"
+ "@babel/template" "^7.29.7"
+ "@babel/traverse" "^7.29.7"
+ "@babel/types" "^7.29.7"
+ "@jridgewell/remapping" "^2.3.5"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
+
+"@babel/generator@^7.29.7", "@babel/generator@^7.7.2":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.7.tgz#cca0b8827e6bcf3ba176788e7f3b180ad6db2fa3"
+ integrity sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==
+ dependencies:
+ "@babel/parser" "^7.29.7"
+ "@babel/types" "^7.29.7"
+ "@jridgewell/gen-mapping" "^0.3.12"
+ "@jridgewell/trace-mapping" "^0.3.28"
+ jsesc "^3.0.2"
+
+"@babel/helper-compilation-targets@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz#7a1def704302401c47f64fa85589e974ae217042"
+ integrity sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==
+ dependencies:
+ "@babel/compat-data" "^7.29.7"
+ "@babel/helper-validator-option" "^7.29.7"
+ browserslist "^4.24.0"
+ lru-cache "^5.1.1"
+ semver "^6.3.1"
+
+"@babel/helper-globals@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz#f04a96fbd8473241b1079243f5b3f03a3010ab7b"
+ integrity sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==
+
+"@babel/helper-module-imports@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz#ef25048a518e828d7393fac5882ddd73921d7396"
+ integrity sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==
+ dependencies:
+ "@babel/traverse" "^7.29.7"
+ "@babel/types" "^7.29.7"
+
+"@babel/helper-module-transforms@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz#b062747a5997ba138637201328bbff77960574ae"
+ integrity sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.29.7"
+ "@babel/helper-validator-identifier" "^7.29.7"
+ "@babel/traverse" "^7.29.7"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.29.7", "@babel/helper-plugin-utils@^7.8.0":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz#c0a0766f1a13617d8a17407d7ab8f9d486225ea4"
+ integrity sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==
+
+"@babel/helper-string-parser@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f"
+ integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==
+
+"@babel/helper-validator-identifier@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2"
+ integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==
+
+"@babel/helper-validator-option@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz#cf315be940213b354eb4abcc0bd01ebe3f73bc2a"
+ integrity sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==
+
+"@babel/helpers@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.29.7.tgz#45abfde7548997e34376c3e69feb475cffb4a607"
+ integrity sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==
+ dependencies:
+ "@babel/template" "^7.29.7"
+ "@babel/types" "^7.29.7"
+
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.7.tgz#837b87387cbf5ec5530cb634b3c622f68edb9334"
+ integrity sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==
+ dependencies:
+ "@babel/types" "^7.29.7"
+
+"@babel/plugin-syntax-async-generators@^7.8.4":
+ version "7.8.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+ integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-bigint@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea"
+ integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-class-properties@^7.12.13":
+ version "7.12.13"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
+ integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.12.13"
+
+"@babel/plugin-syntax-class-static-block@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406"
+ integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-import-attributes@^7.24.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz#6115264516e95ead0f35a41710906612e447f605"
+ integrity sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.29.7"
+
+"@babel/plugin-syntax-import-meta@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
+ integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-json-strings@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
+ integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-jsx@^7.7.2":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz#622c16f9ad63782fe6e83dadc7e40330744b7f1e"
+ integrity sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.29.7"
+
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
+ integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
+ integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-numeric-separator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
+ integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-object-rest-spread@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+ integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+ integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-chaining@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
+ integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-private-property-in-object@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
+ integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-top-level-await@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
+ integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-typescript@^7.7.2":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz#7c29388932313ed58413a0343048d75d92fb5b24"
+ integrity sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.29.7"
+
+"@babel/runtime@^7.25.0":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768"
+ integrity sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==
+
+"@babel/template@^7.29.7", "@babel/template@^7.3.3":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.29.7.tgz#4d9d4004f645cdd304de958c725162784ecac700"
+ integrity sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==
+ dependencies:
+ "@babel/code-frame" "^7.29.7"
+ "@babel/parser" "^7.29.7"
+ "@babel/types" "^7.29.7"
+
+"@babel/traverse@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.7.tgz#c47b07a41b95da0907d026b5dd894d98de7d2f2d"
+ integrity sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==
+ dependencies:
+ "@babel/code-frame" "^7.29.7"
+ "@babel/generator" "^7.29.7"
+ "@babel/helper-globals" "^7.29.7"
+ "@babel/parser" "^7.29.7"
+ "@babel/template" "^7.29.7"
+ "@babel/types" "^7.29.7"
+ debug "^4.3.1"
+
+"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.29.7", "@babel/types@^7.3.3":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.7.tgz#8005e31d82712ee7adaef6e23c63b71a62770a92"
+ integrity sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==
+ dependencies:
+ "@babel/helper-string-parser" "^7.29.7"
+ "@babel/helper-validator-identifier" "^7.29.7"
+
+"@bcoe/v8-coverage@^0.2.3":
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
+ integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+
+"@istanbuljs/load-nyc-config@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
+ integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==
+ dependencies:
+ camelcase "^5.3.1"
+ find-up "^4.1.0"
+ get-package-type "^0.1.0"
+ js-yaml "^3.13.1"
+ resolve-from "^5.0.0"
+
+"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3":
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.6.tgz#8dc9afa2ac1506cb1a58f89940f1c124446c8df3"
+ integrity sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==
+
+"@jest/console@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc"
+ integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+ slash "^3.0.0"
+
+"@jest/core@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f"
+ integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==
+ dependencies:
+ "@jest/console" "^29.7.0"
+ "@jest/reporters" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-changed-files "^29.7.0"
+ jest-config "^29.7.0"
+ jest-haste-map "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-regex-util "^29.6.3"
+ jest-resolve "^29.7.0"
+ jest-resolve-dependencies "^29.7.0"
+ jest-runner "^29.7.0"
+ jest-runtime "^29.7.0"
+ jest-snapshot "^29.7.0"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ jest-watcher "^29.7.0"
+ micromatch "^4.0.4"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ strip-ansi "^6.0.0"
+
+"@jest/environment@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7"
+ integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==
+ dependencies:
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+
+"@jest/expect-utils@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6"
+ integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==
+ dependencies:
+ jest-get-type "^29.6.3"
+
+"@jest/expect@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2"
+ integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==
+ dependencies:
+ expect "^29.7.0"
+ jest-snapshot "^29.7.0"
+
+"@jest/fake-timers@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565"
+ integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@sinonjs/fake-timers" "^10.0.2"
+ "@types/node" "*"
+ jest-message-util "^29.7.0"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
+"@jest/globals@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d"
+ integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/expect" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ jest-mock "^29.7.0"
+
+"@jest/reporters@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7"
+ integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==
+ dependencies:
+ "@bcoe/v8-coverage" "^0.2.3"
+ "@jest/console" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@jridgewell/trace-mapping" "^0.3.18"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ collect-v8-coverage "^1.0.0"
+ exit "^0.1.2"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-instrument "^6.0.0"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.1.3"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+ jest-worker "^29.7.0"
+ slash "^3.0.0"
+ string-length "^4.0.1"
+ strip-ansi "^6.0.0"
+ v8-to-istanbul "^9.0.1"
+
+"@jest/schemas@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
+ integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
+ dependencies:
+ "@sinclair/typebox" "^0.27.8"
+
+"@jest/source-map@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4"
+ integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.18"
+ callsites "^3.0.0"
+ graceful-fs "^4.2.9"
+
+"@jest/test-result@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c"
+ integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==
+ dependencies:
+ "@jest/console" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
+"@jest/test-sequencer@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce"
+ integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==
+ dependencies:
+ "@jest/test-result" "^29.7.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ slash "^3.0.0"
+
+"@jest/transform@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c"
+ integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==
+ dependencies:
+ "@babel/core" "^7.11.6"
+ "@jest/types" "^29.6.3"
+ "@jridgewell/trace-mapping" "^0.3.18"
+ babel-plugin-istanbul "^6.1.1"
+ chalk "^4.0.0"
+ convert-source-map "^2.0.0"
+ fast-json-stable-stringify "^2.1.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ jest-regex-util "^29.6.3"
+ jest-util "^29.7.0"
+ micromatch "^4.0.4"
+ pirates "^4.0.4"
+ slash "^3.0.0"
+ write-file-atomic "^4.0.2"
+
+"@jest/types@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
+ integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
+"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5":
+ version "0.3.13"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f"
+ integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.5.0"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@jridgewell/remapping@^2.3.5":
+ version "2.3.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1"
+ integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
+"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
+ version "1.5.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba"
+ integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==
+
+"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28":
+ version "0.3.31"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0"
+ integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@noble/curves@^1.4.2":
+ version "1.9.7"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951"
+ integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==
+ dependencies:
+ "@noble/hashes" "1.8.0"
+
+"@noble/hashes@1.8.0", "@noble/hashes@^1.4.0":
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a"
+ integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==
+
+"@sinclair/typebox@^0.27.8":
+ version "0.27.10"
+ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.10.tgz#beefe675f1853f73676aecc915b2bd2ac98c4fc6"
+ integrity sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==
+
+"@sinonjs/commons@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd"
+ integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^10.0.2":
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66"
+ integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==
+ dependencies:
+ "@sinonjs/commons" "^3.0.0"
+
+"@solana/buffer-layout@^4.0.1":
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15"
+ integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==
+ dependencies:
+ buffer "~6.0.3"
+
+"@solana/codecs-core@2.3.0":
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.3.0.tgz#6bf2bb565cb1ae880f8018635c92f751465d8695"
+ integrity sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==
+ dependencies:
+ "@solana/errors" "2.3.0"
+
+"@solana/codecs-numbers@^2.1.0":
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz#ac7e7f38aaf7fcd22ce2061fbdcd625e73828dc6"
+ integrity sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==
+ dependencies:
+ "@solana/codecs-core" "2.3.0"
+ "@solana/errors" "2.3.0"
+
+"@solana/errors@2.3.0":
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.3.0.tgz#4ac9380343dbeffb9dffbcb77c28d0e457c5fa31"
+ integrity sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==
+ dependencies:
+ chalk "^5.4.1"
+ commander "^14.0.0"
+
+"@solana/web3.js@^1.91.0":
+ version "1.98.4"
+ resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.98.4.tgz#df51d78be9d865181ec5138b4e699d48e6895bbe"
+ integrity sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ "@noble/curves" "^1.4.2"
+ "@noble/hashes" "^1.4.0"
+ "@solana/buffer-layout" "^4.0.1"
+ "@solana/codecs-numbers" "^2.1.0"
+ agentkeepalive "^4.5.0"
+ bn.js "^5.2.1"
+ borsh "^0.7.0"
+ bs58 "^4.0.1"
+ buffer "6.0.3"
+ fast-stable-stringify "^1.0.0"
+ jayson "^4.1.1"
+ node-fetch "^2.7.0"
+ rpc-websockets "^9.0.2"
+ superstruct "^2.0.2"
+
+"@swc/helpers@^0.5.11":
+ version "0.5.23"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.23.tgz#19287d0d86d962b111376039a50c792902c9a86a"
+ integrity sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==
+ dependencies:
+ tslib "^2.8.0"
+
+"@types/babel__core@^7.1.14":
+ version "7.20.5"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
+ integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==
+ dependencies:
+ "@babel/parser" "^7.20.7"
+ "@babel/types" "^7.20.7"
+ "@types/babel__generator" "*"
+ "@types/babel__template" "*"
+ "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+ version "7.27.0"
+ resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9"
+ integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f"
+ integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
+ version "7.28.0"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74"
+ integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==
+ dependencies:
+ "@babel/types" "^7.28.2"
+
+"@types/connect@^3.4.33":
+ version "3.4.38"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858"
+ integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==
+ dependencies:
+ "@types/node" "*"
+
+"@types/graceful-fs@^4.1.3":
+ version "4.1.9"
+ resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4"
+ integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"
+ integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==
+
+"@types/istanbul-lib-report@*":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf"
+ integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^3.0.0":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54"
+ integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==
+ dependencies:
+ "@types/istanbul-lib-report" "*"
+
+"@types/jest@^29.0.0":
+ version "29.5.14"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5"
+ integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==
+ dependencies:
+ expect "^29.0.0"
+ pretty-format "^29.0.0"
+
+"@types/node@*":
+ version "25.9.2"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.2.tgz#fc8958e757994b71fee516f9634bdb03d1b19e9f"
+ integrity sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==
+ dependencies:
+ undici-types ">=7.24.0 <7.24.7"
+
+"@types/node@^12.12.54":
+ version "12.20.55"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
+ integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
+
+"@types/stack-utils@^2.0.0":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
+ integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
+
+"@types/ws@^7.4.4":
+ version "7.4.7"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702"
+ integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==
+ dependencies:
+ "@types/node" "*"
+
+"@types/ws@^8.2.2":
+ version "8.18.1"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
+ integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==
+ dependencies:
+ "@types/node" "*"
+
+"@types/yargs-parser@*":
+ version "21.0.3"
+ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
+ integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==
+
+"@types/yargs@^17.0.8":
+ version "17.0.35"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24"
+ integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+agentkeepalive@^4.5.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a"
+ integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==
+ dependencies:
+ humanize-ms "^1.2.1"
+
+ansi-escapes@^4.2.1:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+ integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+ dependencies:
+ type-fest "^0.21.3"
+
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
+anymatch@^3.0.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+babel-jest@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5"
+ integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==
+ dependencies:
+ "@jest/transform" "^29.7.0"
+ "@types/babel__core" "^7.1.14"
+ babel-plugin-istanbul "^6.1.1"
+ babel-preset-jest "^29.6.3"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ slash "^3.0.0"
+
+babel-plugin-istanbul@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
+ integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-instrument "^5.0.4"
+ test-exclude "^6.0.0"
+
+babel-plugin-jest-hoist@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626"
+ integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==
+ dependencies:
+ "@babel/template" "^7.3.3"
+ "@babel/types" "^7.3.3"
+ "@types/babel__core" "^7.1.14"
+ "@types/babel__traverse" "^7.0.6"
+
+babel-preset-current-node-syntax@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6"
+ integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==
+ dependencies:
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-bigint" "^7.8.3"
+ "@babel/plugin-syntax-class-properties" "^7.12.13"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+ "@babel/plugin-syntax-import-attributes" "^7.24.7"
+ "@babel/plugin-syntax-import-meta" "^7.10.4"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+ "@babel/plugin-syntax-top-level-await" "^7.14.5"
+
+babel-preset-jest@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c"
+ integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==
+ dependencies:
+ babel-plugin-jest-hoist "^29.6.3"
+ babel-preset-current-node-syntax "^1.0.0"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+base-x@^3.0.2:
+ version "3.0.11"
+ resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff"
+ integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+base64-js@^1.3.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+baseline-browser-mapping@^2.10.12:
+ version "2.10.35"
+ resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.35.tgz#f0f2232e0de2d2f82cc491bcf830b05ed05937c6"
+ integrity sha512-honAfLBde0HAFLdNyBEfuuENkF6zR+ozxqxa/2zJKHBe1qzLqyTSeRKpdPEHAP03rlDGyQOPnCSxnVpVqQo9Mg==
+
+bn.js@^5.2.0, bn.js@^5.2.1:
+ version "5.2.3"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.3.tgz#16a9e409616b23fef3ccbedb8d42f13bff80295e"
+ integrity sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==
+
+borsh@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a"
+ integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==
+ dependencies:
+ bn.js "^5.2.0"
+ bs58 "^4.0.0"
+ text-encoding-utf-8 "^1.0.2"
+
+brace-expansion@^1.1.7:
+ version "1.1.15"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.15.tgz#a6d90d54067236e5f42570a3b7378d594d9b7738"
+ integrity sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+browserslist@^4.24.0:
+ version "4.28.2"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2"
+ integrity sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==
+ dependencies:
+ baseline-browser-mapping "^2.10.12"
+ caniuse-lite "^1.0.30001782"
+ electron-to-chromium "^1.5.328"
+ node-releases "^2.0.36"
+ update-browserslist-db "^1.2.3"
+
+bs-logger@^0.2.6:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
+ integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
+ dependencies:
+ fast-json-stable-stringify "2.x"
+
+bs58@^4.0.0, bs58@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
+ integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==
+ dependencies:
+ base-x "^3.0.2"
+
+bser@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+ dependencies:
+ node-int64 "^0.4.0"
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
+ integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.2.1"
+
+bufferutil@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.1.0.tgz#a4623541dd23867626bb08a051ec0d2ec0b70294"
+ integrity sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==
+ dependencies:
+ node-gyp-build "^4.3.0"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+camelcase@^6.2.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
+ integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
+
+caniuse-lite@^1.0.30001782:
+ version "1.0.30001797"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz#1332709e1439f01ff92085dd17001e0a45897ec0"
+ integrity sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==
+
+chalk@^4.0.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chalk@^5.4.1:
+ version "5.6.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea"
+ integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==
+
+char-regex@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
+ integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
+
+ci-info@^3.2.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
+ integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
+
+cjs-module-lexer@^1.0.0:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d"
+ integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==
+
+cliui@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
+ integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.1"
+ wrap-ansi "^7.0.0"
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+ integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
+
+collect-v8-coverage@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80"
+ integrity sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+commander@^14.0.0:
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.3.tgz#425d79b48f9af82fcd9e4fc1ea8af6c5ec07bbc2"
+ integrity sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==
+
+commander@^2.20.3:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+convert-source-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
+ integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+
+create-jest@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320"
+ integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ chalk "^4.0.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-config "^29.7.0"
+ jest-util "^29.7.0"
+ prompts "^2.0.1"
+
+cross-spawn@^7.0.3:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
+ version "4.4.3"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
+ integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
+ dependencies:
+ ms "^2.1.3"
+
+dedent@^1.0.0:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.2.tgz#34e2264ab538301e27cf7b07bf2369c19baa8dd9"
+ integrity sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==
+
+deepmerge@^4.2.2:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
+ integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
+
+delay@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d"
+ integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==
+
+detect-newline@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
+ integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
+
+diff-sequences@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
+ integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
+
+electron-to-chromium@^1.5.328:
+ version "1.5.370"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.370.tgz#47dbc6565e5f13991a483e10cddff4bf0933de96"
+ integrity sha512-D5tSHJReAb/Kf3Hu9F/GO4lJuSWzEWHwvQ/kKSUP7pimNgvxkSKj+gUQhHpKKACwrin7rS3byU7IxreF56rl5g==
+
+emittery@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
+ integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+error-ex@^1.3.1:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414"
+ integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+es-errors@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
+ integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
+
+es6-promise@^4.0.3:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+ integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
+ dependencies:
+ es6-promise "^4.0.3"
+
+escalade@^3.1.1, escalade@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
+
+escape-string-regexp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+ integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
+esprima@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+eventemitter3@^5.0.1:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb"
+ integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==
+
+execa@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
+exit@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+ integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==
+
+expect@^29.0.0, expect@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc"
+ integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==
+ dependencies:
+ "@jest/expect-utils" "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+
+eyes@^0.1.8:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
+ integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==
+
+fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-stable-stringify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313"
+ integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==
+
+fb-watchman@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c"
+ integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==
+ dependencies:
+ bser "2.1.1"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-up@^4.0.0, find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@^2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+gensync@^1.0.0-beta.2:
+ version "1.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
+ integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
+
+get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-package-type@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
+ integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
+
+get-stream@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
+glob@^7.1.3, glob@^7.1.4:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+graceful-fs@^4.2.9:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+handlebars@^4.7.9:
+ version "4.7.9"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.9.tgz#6f139082ab58dc4e5a0e51efe7db5ae890d56a0f"
+ integrity sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==
+ dependencies:
+ minimist "^1.2.5"
+ neo-async "^2.6.2"
+ source-map "^0.6.1"
+ wordwrap "^1.0.0"
+ optionalDependencies:
+ uglify-js "^3.1.4"
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+hasown@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003"
+ integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==
+ dependencies:
+ function-bind "^1.1.2"
+
+html-escaper@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+ integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+humanize-ms@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
+ integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
+ dependencies:
+ ms "^2.0.0"
+
+ieee754@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+ integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+import-local@^3.0.2:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260"
+ integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-core-module@^2.16.1:
+ version "2.16.2"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.2.tgz#3e07450a8080ebce3fbf0cac494f4d2ab324e082"
+ integrity sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==
+ dependencies:
+ hasown "^2.0.3"
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-generator-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+ integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-stream@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isomorphic-ws@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc"
+ integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==
+
+istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756"
+ integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==
+
+istanbul-lib-instrument@^5.0.4:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d"
+ integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/parser" "^7.14.7"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^6.3.0"
+
+istanbul-lib-instrument@^6.0.0:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765"
+ integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==
+ dependencies:
+ "@babel/core" "^7.23.9"
+ "@babel/parser" "^7.23.9"
+ "@istanbuljs/schema" "^0.1.3"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^7.5.4"
+
+istanbul-lib-report@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d"
+ integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==
+ dependencies:
+ istanbul-lib-coverage "^3.0.0"
+ make-dir "^4.0.0"
+ supports-color "^7.1.0"
+
+istanbul-lib-source-maps@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551"
+ integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==
+ dependencies:
+ debug "^4.1.1"
+ istanbul-lib-coverage "^3.0.0"
+ source-map "^0.6.1"
+
+istanbul-reports@^3.1.3:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93"
+ integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==
+ dependencies:
+ html-escaper "^2.0.0"
+ istanbul-lib-report "^3.0.0"
+
+jayson@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.3.0.tgz#22eb8f3dcf37a5e893830e5451f32bde6d1bde4d"
+ integrity sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==
+ dependencies:
+ "@types/connect" "^3.4.33"
+ "@types/node" "^12.12.54"
+ "@types/ws" "^7.4.4"
+ commander "^2.20.3"
+ delay "^5.0.0"
+ es6-promisify "^5.0.0"
+ eyes "^0.1.8"
+ isomorphic-ws "^4.0.1"
+ json-stringify-safe "^5.0.1"
+ stream-json "^1.9.1"
+ uuid "^8.3.2"
+ ws "^7.5.10"
+
+jest-changed-files@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a"
+ integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==
+ dependencies:
+ execa "^5.0.0"
+ jest-util "^29.7.0"
+ p-limit "^3.1.0"
+
+jest-circus@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a"
+ integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/expect" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ dedent "^1.0.0"
+ is-generator-fn "^2.0.0"
+ jest-each "^29.7.0"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-runtime "^29.7.0"
+ jest-snapshot "^29.7.0"
+ jest-util "^29.7.0"
+ p-limit "^3.1.0"
+ pretty-format "^29.7.0"
+ pure-rand "^6.0.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-cli@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995"
+ integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==
+ dependencies:
+ "@jest/core" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ chalk "^4.0.0"
+ create-jest "^29.7.0"
+ exit "^0.1.2"
+ import-local "^3.0.2"
+ jest-config "^29.7.0"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ yargs "^17.3.1"
+
+jest-config@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f"
+ integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==
+ dependencies:
+ "@babel/core" "^7.11.6"
+ "@jest/test-sequencer" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ babel-jest "^29.7.0"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ deepmerge "^4.2.2"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-circus "^29.7.0"
+ jest-environment-node "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-regex-util "^29.6.3"
+ jest-resolve "^29.7.0"
+ jest-runner "^29.7.0"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ micromatch "^4.0.4"
+ parse-json "^5.2.0"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ strip-json-comments "^3.1.1"
+
+jest-diff@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a"
+ integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^29.6.3"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
+jest-docblock@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a"
+ integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==
+ dependencies:
+ detect-newline "^3.0.0"
+
+jest-each@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1"
+ integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ chalk "^4.0.0"
+ jest-get-type "^29.6.3"
+ jest-util "^29.7.0"
+ pretty-format "^29.7.0"
+
+jest-environment-node@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376"
+ integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
+jest-get-type@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1"
+ integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==
+
+jest-haste-map@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104"
+ integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/graceful-fs" "^4.1.3"
+ "@types/node" "*"
+ anymatch "^3.0.3"
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-regex-util "^29.6.3"
+ jest-util "^29.7.0"
+ jest-worker "^29.7.0"
+ micromatch "^4.0.4"
+ walker "^1.0.8"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+jest-leak-detector@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728"
+ integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==
+ dependencies:
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
+jest-matcher-utils@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12"
+ integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^29.7.0"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
+jest-message-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3"
+ integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^29.6.3"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-mock@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347"
+ integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-util "^29.7.0"
+
+jest-pnp-resolver@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e"
+ integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==
+
+jest-regex-util@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52"
+ integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==
+
+jest-resolve-dependencies@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428"
+ integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==
+ dependencies:
+ jest-regex-util "^29.6.3"
+ jest-snapshot "^29.7.0"
+
+jest-resolve@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30"
+ integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==
+ dependencies:
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ jest-pnp-resolver "^1.2.2"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ resolve "^1.20.0"
+ resolve.exports "^2.0.0"
+ slash "^3.0.0"
+
+jest-runner@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e"
+ integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==
+ dependencies:
+ "@jest/console" "^29.7.0"
+ "@jest/environment" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ emittery "^0.13.1"
+ graceful-fs "^4.2.9"
+ jest-docblock "^29.7.0"
+ jest-environment-node "^29.7.0"
+ jest-haste-map "^29.7.0"
+ jest-leak-detector "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-resolve "^29.7.0"
+ jest-runtime "^29.7.0"
+ jest-util "^29.7.0"
+ jest-watcher "^29.7.0"
+ jest-worker "^29.7.0"
+ p-limit "^3.1.0"
+ source-map-support "0.5.13"
+
+jest-runtime@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817"
+ integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/globals" "^29.7.0"
+ "@jest/source-map" "^29.6.3"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ cjs-module-lexer "^1.0.0"
+ collect-v8-coverage "^1.0.0"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-mock "^29.7.0"
+ jest-regex-util "^29.6.3"
+ jest-resolve "^29.7.0"
+ jest-snapshot "^29.7.0"
+ jest-util "^29.7.0"
+ slash "^3.0.0"
+ strip-bom "^4.0.0"
+
+jest-snapshot@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5"
+ integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==
+ dependencies:
+ "@babel/core" "^7.11.6"
+ "@babel/generator" "^7.7.2"
+ "@babel/plugin-syntax-jsx" "^7.7.2"
+ "@babel/plugin-syntax-typescript" "^7.7.2"
+ "@babel/types" "^7.3.3"
+ "@jest/expect-utils" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ babel-preset-current-node-syntax "^1.0.0"
+ chalk "^4.0.0"
+ expect "^29.7.0"
+ graceful-fs "^4.2.9"
+ jest-diff "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+ natural-compare "^1.4.0"
+ pretty-format "^29.7.0"
+ semver "^7.5.3"
+
+jest-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
+ integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-validate@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c"
+ integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^29.6.3"
+ leven "^3.1.0"
+ pretty-format "^29.7.0"
+
+jest-watcher@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2"
+ integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==
+ dependencies:
+ "@jest/test-result" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.13.1"
+ jest-util "^29.7.0"
+ string-length "^4.0.1"
+
+jest-worker@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a"
+ integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==
+ dependencies:
+ "@types/node" "*"
+ jest-util "^29.7.0"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+jest@^29.0.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613"
+ integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==
+ dependencies:
+ "@jest/core" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ import-local "^3.0.2"
+ jest-cli "^29.7.0"
+
+js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^3.13.1:
+ version "3.14.2"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0"
+ integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+jsesc@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
+ integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
+
+json-parse-even-better-errors@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-stringify-safe@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
+
+json5@^2.2.3:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+kleur@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
+leven@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+lodash.memoize@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+ integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+make-dir@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e"
+ integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==
+ dependencies:
+ semver "^7.5.3"
+
+make-error@^1.3.6:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+ integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
+makeerror@1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
+ integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
+ dependencies:
+ tmpl "1.0.5"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+micromatch@^4.0.4:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+minimatch@^3.0.4, minimatch@^3.1.1:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e"
+ integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@^1.2.5:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+ms@^2.0.0, ms@^2.1.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+node-fetch@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
+ integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
+ dependencies:
+ whatwg-url "^5.0.0"
+
+node-gyp-build@^4.3.0:
+ version "4.8.4"
+ resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8"
+ integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==
+
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+ integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
+
+node-releases@^2.0.36:
+ version "2.0.47"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.47.tgz#521bb2786da8eb140b748841c0b3b3a75334ffc4"
+ integrity sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==
+
+normalize-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+npm-run-path@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.0.0"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-limit@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+parse-json@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-even-better-errors "^2.3.0"
+ lines-and-columns "^1.1.6"
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^3.0.0, path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+picocolors@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
+picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601"
+ integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==
+
+pirates@^4.0.4:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22"
+ integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==
+
+pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+pretty-format@^29.0.0, pretty-format@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
+ integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
+prompts@^2.0.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
+ integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
+ dependencies:
+ kleur "^3.0.3"
+ sisteransi "^1.0.5"
+
+pure-rand@^6.0.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2"
+ integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==
+
+react-is@^18.0.0:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
+ integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve.exports@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f"
+ integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==
+
+resolve@^1.20.0:
+ version "1.22.12"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f"
+ integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==
+ dependencies:
+ es-errors "^1.3.0"
+ is-core-module "^2.16.1"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+rpc-websockets@^9.0.2:
+ version "9.3.10"
+ resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.3.10.tgz#d6f9b08edfac40e873a059b358806f6d58572e80"
+ integrity sha512-QT5PQ6LiWhA5RCS93oWwgxU4XzQltkYm8C3aTmmKEgj0HolGRo3VbdzELw7CEV35l9T7Amha8Vnr4rCfSjVP+w==
+ dependencies:
+ "@swc/helpers" "^0.5.11"
+ "@types/ws" "^8.2.2"
+ buffer "^6.0.3"
+ eventemitter3 "^5.0.1"
+ ws "^8.5.0"
+ optionalDependencies:
+ bufferutil "^4.0.1"
+ utf-8-validate "^6.0.0"
+
+safe-buffer@^5.0.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+semver@^6.3.0, semver@^6.3.1:
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
+ integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
+
+semver@^7.5.3, semver@^7.5.4, semver@^7.8.0:
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.3.tgz#c350de61c2a1ddbc96d7fae3e5b6fcf92d477fbe"
+ integrity sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+signal-exit@^3.0.3, signal-exit@^3.0.7:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+sisteransi@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+source-map-support@0.5.13:
+ version "0.5.13"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
+ integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0, source-map@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+ integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
+
+stack-utils@^2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"
+ integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==
+ dependencies:
+ escape-string-regexp "^2.0.0"
+
+stream-chain@^2.2.5:
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09"
+ integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==
+
+stream-json@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187"
+ integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==
+ dependencies:
+ stream-chain "^2.2.5"
+
+string-length@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
+ integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==
+ dependencies:
+ char-regex "^1.0.2"
+ strip-ansi "^6.0.0"
+
+string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-bom@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
+ integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
+
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+
+strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+superstruct@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54"
+ integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+test-exclude@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
+ integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+ glob "^7.1.4"
+ minimatch "^3.0.4"
+
+text-encoding-utf-8@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
+ integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==
+
+tmpl@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+ integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+tr46@~0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+ integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
+
+ts-jest@^29.0.0:
+ version "29.4.11"
+ resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.11.tgz#42f5de21c37ccc01a580253afae6955abbf4d0b3"
+ integrity sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==
+ dependencies:
+ bs-logger "^0.2.6"
+ fast-json-stable-stringify "^2.1.0"
+ handlebars "^4.7.9"
+ json5 "^2.2.3"
+ lodash.memoize "^4.1.2"
+ make-error "^1.3.6"
+ semver "^7.8.0"
+ type-fest "^4.41.0"
+ yargs-parser "^21.1.1"
+
+tslib@^2.8.0:
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
+ integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
+
+type-detect@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+ integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-fest@^0.21.3:
+ version "0.21.3"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+ integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+
+type-fest@^4.41.0:
+ version "4.41.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58"
+ integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==
+
+typescript@^5.7.3:
+ version "5.9.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
+ integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
+
+uglify-js@^3.1.4:
+ version "3.19.3"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f"
+ integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==
+
+"undici-types@>=7.24.0 <7.24.7":
+ version "7.24.6"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.24.6.tgz#61275b485d7fd4e9d269c7cf04ec2873c9cc0f91"
+ integrity sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==
+
+update-browserslist-db@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d"
+ integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==
+ dependencies:
+ escalade "^3.2.0"
+ picocolors "^1.1.1"
+
+utf-8-validate@^6.0.0:
+ version "6.0.6"
+ resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.6.tgz#8a842c9b15af3f6323a3d5ed5eb9e61d208d8c22"
+ integrity sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==
+ dependencies:
+ node-gyp-build "^4.3.0"
+
+uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
+v8-to-istanbul@^9.0.1:
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175"
+ integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.12"
+ "@types/istanbul-lib-coverage" "^2.0.1"
+ convert-source-map "^2.0.0"
+
+walker@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
+ integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
+ dependencies:
+ makeerror "1.0.12"
+
+webidl-conversions@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+ integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+
+whatwg-url@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+ integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+ dependencies:
+ tr46 "~0.0.3"
+ webidl-conversions "^3.0.0"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wordwrap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+ integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
+
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+write-file-atomic@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd"
+ integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==
+ dependencies:
+ imurmurhash "^0.1.4"
+ signal-exit "^3.0.7"
+
+ws@^7.5.10:
+ version "7.5.11"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.11.tgz#9460daf1812bb81a423c5b9eac746941a86310fa"
+ integrity sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==
+
+ws@^8.5.0:
+ version "8.21.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.0.tgz#012e413fc07429945121b0c153158c4343086951"
+ integrity sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
+yallist@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yargs-parser@^21.1.1:
+ version "21.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
+ integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
+
+yargs@^17.3.1:
+ version "17.7.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
+ integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
+ dependencies:
+ cliui "^8.0.1"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.3"
+ y18n "^5.0.5"
+ yargs-parser "^21.1.1"
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
diff --git a/tests/hookguard.ts b/tests/hookguard.ts
index faa6ad7..bdf542a 100644
--- a/tests/hookguard.ts
+++ b/tests/hookguard.ts
@@ -29,20 +29,31 @@ const JETTY_ERROR = {
async function expectJettyError(promise: Promise, code: number): Promise {
try {
await promise;
- expect.fail(`expected Jetty error ${code}`);
+ expect.fail(`Expected Jetty error ${code} but instruction succeeded`);
} catch (error) {
- expect(extractErrorCode(error)).to.equal(code);
+ const actual = extractErrorCode(error);
+ expect(actual, `Expected error ${code}, got ${actual}\n${String(error)}`).to.equal(code);
}
}
describe("hookguard", function () {
this.timeout(200_000);
- const provider = anchor.AnchorProvider.env();
+ const provider = new anchor.AnchorProvider(
+ anchor.AnchorProvider.env().connection,
+ anchor.AnchorProvider.env().wallet,
+ { commitment: "confirmed", preflightCommitment: "confirmed" }
+ );
anchor.setProvider(provider);
const program = anchor.workspace.Jetty as anchor.Program;
- const payer = getPayer(provider);
+
+ // authority === provider.wallet.publicKey — the key Anchor signs every
+ // .rpc() call with. Using this consistently ensures on-chain stored keys
+ // always match the signer Anchor presents.
+ const authority = getPayer(provider);
+
+ // ─── initialize_hook_config ───────────────────────────────────────────────
describe("initialize_hook_config", () => {
it("should initialize HookConfig with correct defaults", async () => {
@@ -52,114 +63,117 @@ describe("hookguard", function () {
await program.methods
.initializeHookConfig()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
- const hookConfig = await program.account.hookConfig.fetch(hookConfigPda);
+ const hookConfig = await program.account.hookConfig.fetch(hookConfigPda, "confirmed");
expect(hookConfig.mint.equals(mint.publicKey)).to.equal(true);
- expect(hookConfig.policyAuthority.equals(payer.publicKey)).to.equal(true);
+ expect(hookConfig.policyAuthority.equals(authority)).to.equal(true);
expect(hookConfig.bump).to.equal(hookConfigBump);
expect(hookConfig.paused).to.equal(false);
expect(hookConfig.allowlistEnabled).to.equal(false);
expect(hookConfig.maxTransferAmount.toString()).to.equal("0");
});
- it("should fail if called twice for same mint", async () => {
+ it("should fail if called twice for the same mint", async () => {
const mint = await createTransferHookMint(provider, program.programId);
- const [hookConfigPda] = deriveHookConfigPda(mint.publicKey, program.programId);
await program.methods
.initializeHookConfig()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
try {
await program.methods
.initializeHookConfig()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
})
- .rpc();
- expect.fail("second initialize should fail");
+ .rpc({ commitment: "confirmed" });
+ expect.fail("Second initialize_hook_config should have failed");
} catch (error) {
expect(String(error)).to.match(/already in use/i);
}
});
});
+ // ─── init_extra_account_meta_list ─────────────────────────────────────────
+
describe("init_extra_account_meta_list", () => {
it("should create ExtraAccountMetaList with correct size and owner", async () => {
const mint = await createTransferHookMint(provider, program.programId);
- const [hookConfigPda] = deriveHookConfigPda(mint.publicKey, program.programId);
const [extraAccountMetaListPda] = deriveExtraAccountMetaListPda(mint.publicKey, program.programId);
await program.methods
.initializeHookConfig()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await program.methods
.initExtraAccountMetaList()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
tokenProgram: TOKEN_2022_PROGRAM_ID,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
- const accountInfo = await provider.connection.getAccountInfo(extraAccountMetaListPda, "confirmed");
- expect(accountInfo).to.not.equal(null);
- expect(accountInfo?.owner.equals(program.programId)).to.equal(true);
- expect(accountInfo?.data.length).to.equal(EXTRA_ACCOUNT_META_LIST_SIZE);
+ const accountInfo = await provider.connection.getAccountInfo(
+ extraAccountMetaListPda,
+ "confirmed"
+ );
+ expect(accountInfo, "ExtraAccountMetaList account must exist").to.not.equal(null);
+ expect(accountInfo!.owner.equals(program.programId)).to.equal(true);
+ expect(accountInfo!.data.length).to.equal(EXTRA_ACCOUNT_META_LIST_SIZE);
});
it("should fail with Unauthorized when wrong signer initializes list", async () => {
const mint = await createTransferHookMint(provider, program.programId);
const wrongAuthority = await createFundedUser(provider);
- const [hookConfigPda] = deriveHookConfigPda(mint.publicKey, program.programId);
- const [extraAccountMetaListPda] = deriveExtraAccountMetaListPda(mint.publicKey, program.programId);
await program.methods
.initializeHookConfig()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await expectJettyError(
program.methods
.initExtraAccountMetaList()
.accounts({
- payer: payer.publicKey,
+ payer: authority,
policyAuthority: wrongAuthority.publicKey,
mint: mint.publicKey,
tokenProgram: TOKEN_2022_PROGRAM_ID,
})
.signers([wrongAuthority])
- .rpc(),
- JETTY_ERROR.Unauthorized,
+ .rpc({ commitment: "confirmed" }),
+ JETTY_ERROR.Unauthorized
);
});
});
+ // ─── update_policy ────────────────────────────────────────────────────────
+
describe("update_policy", () => {
- it("should update only requested policy fields", async () => {
+ it("should update only the requested policy fields", async () => {
const fixture = await createHookFixture(program);
await program.methods
@@ -169,12 +183,12 @@ describe("hookguard", function () {
maxTransferAmount: new anchor.BN(25),
})
.accounts({
- policyAuthority: payer.publicKey,
+ policyAuthority: authority,
mint: fixture.mint.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
- const hookConfig = await program.account.hookConfig.fetch(fixture.hookConfigPda);
+ const hookConfig = await program.account.hookConfig.fetch(fixture.hookConfigPda, "confirmed");
expect(hookConfig.paused).to.equal(true);
expect(hookConfig.allowlistEnabled).to.equal(true);
expect(hookConfig.maxTransferAmount.toString()).to.equal("25");
@@ -196,32 +210,34 @@ describe("hookguard", function () {
mint: fixture.mint.publicKey,
})
.signers([wrongAuthority])
- .rpc(),
- JETTY_ERROR.Unauthorized,
+ .rpc({ commitment: "confirmed" }),
+ JETTY_ERROR.Unauthorized
);
});
});
+ // ─── update_allowlist ─────────────────────────────────────────────────────
+
describe("update_allowlist", () => {
- it("should create and update allowlist entry", async () => {
+ it("should create and update an allowlist entry", async () => {
const fixture = await createHookFixture(program);
const [allowlistEntryPda, allowlistBump] = deriveAllowlistEntryPda(
fixture.mint.publicKey,
fixture.destinationOwner.publicKey,
- program.programId,
+ program.programId
);
await program.methods
.updateAllowlist(true)
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: fixture.mint.publicKey,
wallet: fixture.destinationOwner.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
- const entry = await program.account.allowlistEntry.fetch(allowlistEntryPda);
+ const entry = await program.account.allowlistEntry.fetch(allowlistEntryPda, "confirmed");
expect(entry.mint.equals(fixture.mint.publicKey)).to.equal(true);
expect(entry.wallet.equals(fixture.destinationOwner.publicKey)).to.equal(true);
expect(entry.active).to.equal(true);
@@ -231,28 +247,25 @@ describe("hookguard", function () {
it("should fail with Unauthorized when wrong signer calls update_allowlist", async () => {
const fixture = await createHookFixture(program);
const wrongAuthority = await createFundedUser(provider);
- const [allowlistEntryPda] = deriveAllowlistEntryPda(
- fixture.mint.publicKey,
- fixture.destinationOwner.publicKey,
- program.programId,
- );
await expectJettyError(
program.methods
.updateAllowlist(true)
.accounts({
- payer: payer.publicKey,
+ payer: authority,
policyAuthority: wrongAuthority.publicKey,
mint: fixture.mint.publicKey,
wallet: fixture.destinationOwner.publicKey,
})
.signers([wrongAuthority])
- .rpc(),
- JETTY_ERROR.Unauthorized,
+ .rpc({ commitment: "confirmed" }),
+ JETTY_ERROR.Unauthorized
);
});
});
+ // ─── execute ──────────────────────────────────────────────────────────────
+
describe("execute", () => {
it("should fail with NotTransferring on direct invocation", async () => {
const fixture = await createHookFixture(program);
@@ -264,10 +277,10 @@ describe("hookguard", function () {
sourceTokenAccount: fixture.sourceTokenAccount,
mint: fixture.mint.publicKey,
destinationTokenAccount: fixture.destinationTokenAccount,
- authority: payer.publicKey,
+ authority: authority,
})
- .rpc(),
- JETTY_ERROR.NotTransferring,
+ .rpc({ commitment: "confirmed" }),
+ JETTY_ERROR.NotTransferring
);
});
@@ -275,27 +288,20 @@ describe("hookguard", function () {
const fixture = await createHookFixture(program);
await program.methods
- .updatePolicy({
- paused: true,
- allowlistEnabled: null,
- maxTransferAmount: null,
- })
- .accounts({
- policyAuthority: payer.publicKey,
- mint: fixture.mint.publicKey,
- })
- .rpc();
+ .updatePolicy({ paused: true, allowlistEnabled: null, maxTransferAmount: null })
+ .accounts({ policyAuthority: authority, mint: fixture.mint.publicKey })
+ .rpc({ commitment: "confirmed" });
await expectJettyError(
transferWithHook(provider, {
source: fixture.sourceTokenAccount,
mint: fixture.mint.publicKey,
destination: fixture.destinationTokenAccount,
- owner: payer.publicKey,
+ owner: authority,
amount: 10n,
decimals: fixture.decimals,
}),
- JETTY_ERROR.TransferPaused,
+ JETTY_ERROR.TransferPaused
);
});
@@ -303,166 +309,120 @@ describe("hookguard", function () {
const fixture = await createHookFixture(program);
await program.methods
- .updatePolicy({
- paused: null,
- allowlistEnabled: null,
- maxTransferAmount: new anchor.BN(5),
- })
- .accounts({
- policyAuthority: payer.publicKey,
- mint: fixture.mint.publicKey,
- })
- .rpc();
+ .updatePolicy({ paused: null, allowlistEnabled: null, maxTransferAmount: new anchor.BN(5) })
+ .accounts({ policyAuthority: authority, mint: fixture.mint.publicKey })
+ .rpc({ commitment: "confirmed" });
await expectJettyError(
transferWithHook(provider, {
source: fixture.sourceTokenAccount,
mint: fixture.mint.publicKey,
destination: fixture.destinationTokenAccount,
- owner: payer.publicKey,
+ owner: authority,
amount: 10n,
decimals: fixture.decimals,
}),
- JETTY_ERROR.ExceedsVolumeLimit,
+ JETTY_ERROR.ExceedsVolumeLimit
);
});
it("should reject transfer when sender not allowlisted", async () => {
const fixture = await createHookFixture(program);
- const [receiverAllowlistPda] = deriveAllowlistEntryPda(
- fixture.mint.publicKey,
- fixture.destinationOwner.publicKey,
- program.programId,
- );
+ // Only allowlist the receiver — sender must be rejected
await program.methods
.updateAllowlist(true)
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: fixture.mint.publicKey,
wallet: fixture.destinationOwner.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await program.methods
- .updatePolicy({
- paused: null,
- allowlistEnabled: true,
- maxTransferAmount: null,
- })
- .accounts({
- policyAuthority: payer.publicKey,
- mint: fixture.mint.publicKey,
- })
- .rpc();
+ .updatePolicy({ paused: null, allowlistEnabled: true, maxTransferAmount: null })
+ .accounts({ policyAuthority: authority, mint: fixture.mint.publicKey })
+ .rpc({ commitment: "confirmed" });
await expectJettyError(
transferWithHook(provider, {
source: fixture.sourceTokenAccount,
mint: fixture.mint.publicKey,
destination: fixture.destinationTokenAccount,
- owner: payer.publicKey,
+ owner: authority,
amount: 10n,
decimals: fixture.decimals,
}),
- JETTY_ERROR.SourceNotAllowlisted,
+ JETTY_ERROR.SourceNotAllowlisted
);
});
it("should reject transfer when receiver not allowlisted", async () => {
const fixture = await createHookFixture(program);
- const [senderAllowlistPda] = deriveAllowlistEntryPda(
- fixture.mint.publicKey,
- fixture.sourceOwner,
- program.programId,
- );
+ // Only allowlist the sender — receiver must be rejected
await program.methods
.updateAllowlist(true)
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: fixture.mint.publicKey,
wallet: fixture.sourceOwner,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await program.methods
- .updatePolicy({
- paused: null,
- allowlistEnabled: true,
- maxTransferAmount: null,
- })
- .accounts({
- policyAuthority: payer.publicKey,
- mint: fixture.mint.publicKey,
- })
- .rpc();
+ .updatePolicy({ paused: null, allowlistEnabled: true, maxTransferAmount: null })
+ .accounts({ policyAuthority: authority, mint: fixture.mint.publicKey })
+ .rpc({ commitment: "confirmed" });
await expectJettyError(
transferWithHook(provider, {
source: fixture.sourceTokenAccount,
mint: fixture.mint.publicKey,
destination: fixture.destinationTokenAccount,
- owner: payer.publicKey,
+ owner: authority,
amount: 10n,
decimals: fixture.decimals,
}),
- JETTY_ERROR.DestinationNotAllowlisted,
+ JETTY_ERROR.DestinationNotAllowlisted
);
});
it("should allow transfer when both sender and receiver are allowlisted", async () => {
const fixture = await createHookFixture(program);
- const [senderAllowlistPda] = deriveAllowlistEntryPda(
- fixture.mint.publicKey,
- fixture.sourceOwner,
- program.programId,
- );
- const [receiverAllowlistPda] = deriveAllowlistEntryPda(
- fixture.mint.publicKey,
- fixture.destinationOwner.publicKey,
- program.programId,
- );
await program.methods
.updateAllowlist(true)
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: fixture.mint.publicKey,
wallet: fixture.sourceOwner,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await program.methods
.updateAllowlist(true)
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: fixture.mint.publicKey,
wallet: fixture.destinationOwner.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await program.methods
- .updatePolicy({
- paused: null,
- allowlistEnabled: true,
- maxTransferAmount: null,
- })
- .accounts({
- policyAuthority: payer.publicKey,
- mint: fixture.mint.publicKey,
- })
- .rpc();
+ .updatePolicy({ paused: null, allowlistEnabled: true, maxTransferAmount: null })
+ .accounts({ policyAuthority: authority, mint: fixture.mint.publicKey })
+ .rpc({ commitment: "confirmed" });
await transferWithHook(provider, {
source: fixture.sourceTokenAccount,
mint: fixture.mint.publicKey,
destination: fixture.destinationTokenAccount,
- owner: payer.publicKey,
+ owner: authority,
amount: 10n,
decimals: fixture.decimals,
});
@@ -471,4 +431,4 @@ describe("hookguard", function () {
expect(await getTokenAmount(provider, fixture.destinationTokenAccount)).to.equal(10n);
});
});
-});
+});
\ No newline at end of file
diff --git a/tests/utils/helpers.ts b/tests/utils/helpers.ts
index 44c1049..17fb3fa 100644
--- a/tests/utils/helpers.ts
+++ b/tests/utils/helpers.ts
@@ -1,19 +1,4 @@
import * as anchor from "@anchor-lang/core";
-import {
- fromLegacyKeypair,
- fromLegacyTransactionInstruction,
-} from "@solana/compat";
-import {
- appendTransactionMessageInstructions,
- createSolanaRpc,
- createSolanaRpcSubscriptions,
- createTransactionMessage,
- pipe,
- sendAndConfirmTransactionFactory,
- setTransactionMessageFeePayerSigner,
- setTransactionMessageLifetimeUsingBlockhash,
- signTransactionMessageWithSigners,
-} from "@solana/kit";
import {
ExtensionType,
TOKEN_2022_PROGRAM_ID,
@@ -30,7 +15,15 @@ import {
import type { Jetty } from "../../target/types/jetty";
type JettyProgram = anchor.Program;
-type LocalWallet = anchor.Wallet & { payer: anchor.web3.Keypair };
+
+// The provider wallet as a keypair — only used where @solana/spl-token
+// requires a raw Keypair (getOrCreateAssociatedTokenAccount, mintToChecked).
+// Never used to derive a pubkey; use provider.wallet.publicKey for that.
+function getWalletKeypair(provider: anchor.AnchorProvider): anchor.web3.Keypair {
+ const wallet = provider.wallet as anchor.Wallet & { payer?: anchor.web3.Keypair };
+ if (!wallet.payer) throw new Error("Provider wallet does not expose a payer keypair");
+ return wallet.payer;
+}
export type HookFixture = {
mint: anchor.web3.Keypair;
@@ -51,8 +44,10 @@ export function getProvider(): anchor.AnchorProvider {
return anchor.getProvider() as anchor.AnchorProvider;
}
-export function getPayer(provider: anchor.AnchorProvider): anchor.web3.Keypair {
- return (provider.wallet as LocalWallet).payer;
+// Returns the provider wallet's public key — the key Anchor uses to sign
+// all .rpc() calls. Always consistent with what gets stored on-chain.
+export function getPayer(provider: anchor.AnchorProvider): anchor.web3.PublicKey {
+ return provider.wallet.publicKey;
}
export function deriveHookConfigPda(
@@ -88,32 +83,34 @@ export function deriveAllowlistEntryPda(
export async function createFundedUser(
provider: anchor.AnchorProvider,
- lamports = 1_000_000_000
+ lamports = 2_000_000_000
): Promise {
const user = anchor.web3.Keypair.generate();
- const signature = await provider.connection.requestAirdrop(
- user.publicKey,
- lamports
+ const signature = await provider.connection.requestAirdrop(user.publicKey, lamports);
+ const latestBlockhash = await provider.connection.getLatestBlockhash("confirmed");
+ await provider.connection.confirmTransaction(
+ { signature, ...latestBlockhash },
+ "confirmed"
);
- await provider.connection.confirmTransaction(signature, "confirmed");
return user;
}
+// Creates a Token-2022 mint with a TransferHook extension pointing at programId.
+// provider.sendAndConfirm signs with the provider wallet — consistent with
+// provider.wallet.publicKey used everywhere else.
export async function createTransferHookMint(
provider: anchor.AnchorProvider,
transferHookProgramId: anchor.web3.PublicKey,
decimals = 2
): Promise {
- const payer = getPayer(provider);
+ const payerPubkey = provider.wallet.publicKey;
const mint = anchor.web3.Keypair.generate();
const mintSpace = getMintLen([ExtensionType.TransferHook]);
- const lamports = await provider.connection.getMinimumBalanceForRentExemption(
- mintSpace
- );
+ const lamports = await provider.connection.getMinimumBalanceForRentExemption(mintSpace);
const transaction = new anchor.web3.Transaction().add(
anchor.web3.SystemProgram.createAccount({
- fromPubkey: payer.publicKey,
+ fromPubkey: payerPubkey,
newAccountPubkey: mint.publicKey,
space: mintSpace,
lamports,
@@ -121,14 +118,14 @@ export async function createTransferHookMint(
}),
createInitializeTransferHookInstruction(
mint.publicKey,
- payer.publicKey,
+ payerPubkey,
transferHookProgramId,
TOKEN_2022_PROGRAM_ID
),
createInitializeMintInstruction(
mint.publicKey,
decimals,
- payer.publicKey,
+ payerPubkey,
null,
TOKEN_2022_PROGRAM_ID
)
@@ -143,7 +140,7 @@ export async function getOrCreateToken2022Ata(
mint: anchor.web3.PublicKey,
owner: anchor.web3.PublicKey
): Promise {
- const payer = getPayer(provider);
+ const payer = getWalletKeypair(provider);
const account = await getOrCreateAssociatedTokenAccount(
provider.connection,
payer,
@@ -151,7 +148,7 @@ export async function getOrCreateToken2022Ata(
owner,
false,
"confirmed",
- undefined,
+ { commitment: "confirmed" },
TOKEN_2022_PROGRAM_ID
);
return account.address;
@@ -164,7 +161,7 @@ export async function mintToken2022To(
amount: bigint,
decimals: number
): Promise {
- const payer = getPayer(provider);
+ const payer = getWalletKeypair(provider);
await mintToChecked(
provider.connection,
payer,
@@ -179,43 +176,6 @@ export async function mintToken2022To(
);
}
-function getWsUrl(httpUrl: string): string {
- const url = new URL(httpUrl);
- url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
- return url.toString();
-}
-
-export async function sendProviderInstructionsWithKit(
- provider: anchor.AnchorProvider,
- instructions: anchor.web3.TransactionInstruction[]
-): Promise {
- const rpc: any = createSolanaRpc(provider.connection.rpcEndpoint as never);
- const rpcSubscriptions: any = createSolanaRpcSubscriptions(
- getWsUrl(provider.connection.rpcEndpoint) as never
- );
- const sendAndConfirm: any = sendAndConfirmTransactionFactory({
- rpc,
- rpcSubscriptions,
- } as never);
- const payerSigner: any = await fromLegacyKeypair(getPayer(provider));
- const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
-
- const message = pipe(
- createTransactionMessage({ version: 0 }),
- (tx) => setTransactionMessageFeePayerSigner(payerSigner, tx),
- (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
- (tx) =>
- appendTransactionMessageInstructions(
- instructions.map((instruction) =>
- fromLegacyTransactionInstruction(instruction)
- ),
- tx
- )
- );
- const signedTransaction = await signTransactionMessageWithSigners(message);
- await sendAndConfirm(signedTransaction as never, { commitment: "confirmed" });
-}
-
export async function transferWithHook(
provider: anchor.AnchorProvider,
params: {
@@ -239,47 +199,53 @@ export async function transferWithHook(
"confirmed",
TOKEN_2022_PROGRAM_ID
);
- await sendProviderInstructionsWithKit(provider, [instruction]);
+ const tx = new anchor.web3.Transaction().add(instruction);
+ await provider.sendAndConfirm(tx, []);
}
+// Creates a full fixture: mint → HookConfig → ExtraAccountMetaList → ATAs → minted tokens.
+// All authority accounts use provider.wallet.publicKey so they match what
+// Anchor signs with in every subsequent .rpc() call.
export async function createHookFixture(
program: JettyProgram,
initialAmount = 1_000n
): Promise {
const provider = program.provider as anchor.AnchorProvider;
- const payer = getPayer(provider);
+ const authority = provider.wallet.publicKey;
+
const mint = await createTransferHookMint(provider, program.programId);
- const [hookConfigPda, hookConfigBump] = deriveHookConfigPda(
+
+ const [hookConfigPda, hookConfigBump] = deriveHookConfigPda(mint.publicKey, program.programId);
+ const [extraAccountMetaListPda, extraAccountMetaListBump] = deriveExtraAccountMetaListPda(
mint.publicKey,
program.programId
);
- const [extraAccountMetaListPda, extraAccountMetaListBump] =
- deriveExtraAccountMetaListPda(mint.publicKey, program.programId);
await program.methods
.initializeHookConfig()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
await program.methods
.initExtraAccountMetaList()
.accounts({
- payer: payer.publicKey,
- policyAuthority: payer.publicKey,
+ payer: authority,
+ policyAuthority: authority,
mint: mint.publicKey,
tokenProgram: TOKEN_2022_PROGRAM_ID,
})
- .rpc();
+ .rpc({ commitment: "confirmed" });
const sourceTokenAccount = await getOrCreateToken2022Ata(
provider,
mint.publicKey,
- payer.publicKey
+ authority
);
+
const destinationOwner = await createFundedUser(provider);
const destinationTokenAccount = await getOrCreateToken2022Ata(
provider,
@@ -287,13 +253,7 @@ export async function createHookFixture(
destinationOwner.publicKey
);
- await mintToken2022To(
- provider,
- mint.publicKey,
- sourceTokenAccount,
- initialAmount,
- 2
- );
+ await mintToken2022To(provider, mint.publicKey, sourceTokenAccount, initialAmount, 2);
return {
mint,
@@ -302,7 +262,7 @@ export async function createHookFixture(
hookConfigBump,
extraAccountMetaListPda,
extraAccountMetaListBump,
- sourceOwner: payer.publicKey,
+ sourceOwner: authority,
sourceTokenAccount,
destinationOwner,
destinationTokenAccount,
@@ -326,12 +286,7 @@ export function expectedAta(
mint: anchor.web3.PublicKey,
owner: anchor.web3.PublicKey
): anchor.web3.PublicKey {
- return getAssociatedTokenAddressSync(
- mint,
- owner,
- false,
- TOKEN_2022_PROGRAM_ID
- );
+ return getAssociatedTokenAddressSync(mint, owner, false, TOKEN_2022_PROGRAM_ID);
}
export function extractErrorCode(error: unknown): number | null {
@@ -339,18 +294,33 @@ export function extractErrorCode(error: unknown): number | null {
error?: { errorCode?: { number?: number } };
code?: number;
logs?: string[];
+ message?: string;
};
+
if (candidate.error?.errorCode?.number !== undefined) {
return candidate.error.errorCode.number;
}
+
if (candidate.code !== undefined && candidate.code >= 6000) {
return candidate.code;
}
+
if (candidate.logs) {
const parsed = anchor.AnchorError.parse(candidate.logs);
- if (parsed) {
- return parsed.error.errorCode.number;
+ if (parsed) return parsed.error.errorCode.number;
+ }
+
+ if (candidate.message && typeof candidate.message === "string") {
+ const m = candidate.message.match(/custom program error: 0x([0-9a-fA-F]+)/);
+ if (m) {
+ const parsed = parseInt(m[1], 16);
+ if (!Number.isNaN(parsed)) {
+ if (parsed >= 6000) return parsed;
+ if (parsed > 0) return parsed + 6000;
+ return parsed;
+ }
}
}
+
return null;
-}
+}
\ No newline at end of file