diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1a7cae9..a2a341c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,6 +7,7 @@ on: pull_request: branches: - main + - next workflow_dispatch: env: @@ -27,7 +28,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '22' + node-version: '24' - name: Enable Corepack run: corepack enable @@ -35,17 +36,27 @@ jobs: - name: Install dependencies run: yarn install --immutable + - name: Extract Aztec version + id: aztec-version + run: | + VERSION=$(jq -r '.dependencies["@aztec/aztec.js"]' package.json) + VERSION_NO_V=${VERSION#v} + echo "version=$VERSION_NO_V" >> $GITHUB_OUTPUT + echo "Aztec version: $VERSION_NO_V" + - name: Install Aztec CLI run: | - curl -s https://install.aztec.network > tmp.sh - bash tmp.sh <<< yes "yes" + export CI=1 + export FOUNDRY_DIR="$HOME/.foundry" + echo "Running version-specific installer for ${{ steps.aztec-version.outputs.version }}..." + curl -fsSL "https://install.aztec.network/${{ steps.aztec-version.outputs.version }}/install" | VERSION="${{ steps.aztec-version.outputs.version }}" bash + echo "Installation completed" + ls -la ~/.aztec/versions/${{ steps.aztec-version.outputs.version }}/bin/ - name: Update path - run: echo "/home/runner/.aztec/bin" >> $GITHUB_PATH - - - name: Set Aztec version run: | - aztec-up ${{ vars.VERSION }} + echo "$HOME/.aztec/versions/${{ steps.aztec-version.outputs.version }}/bin" >> $GITHUB_PATH + echo "$HOME/.aztec/versions/${{ steps.aztec-version.outputs.version }}/node_modules/.bin" >> $GITHUB_PATH - name: Compile contracts run: yarn compile:contracts @@ -59,7 +70,11 @@ jobs: - name: Deploy to Vercel id: deploy run: | - DEPLOY_URL=$(vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes) + if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]; then + DEPLOY_URL=$(vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes) + else + DEPLOY_URL=$(vercel deploy --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes) + fi echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT - name: Comment deployment URL on PR diff --git a/.github/workflows/update-nightly.yml b/.github/workflows/update-nightly.yml new file mode 100644 index 0000000..06d0148 --- /dev/null +++ b/.github/workflows/update-nightly.yml @@ -0,0 +1,88 @@ +name: Update to Latest Nightly + +on: + schedule: + # Run daily at 6 AM UTC (after nextnet deploys at 5 AM) + - cron: '0 6 * * *' + workflow_dispatch: + inputs: + version: + description: 'Nightly version (e.g., 4.0.0-nightly.20260206)' + required: false + type: string + deploy: + description: 'Deploy to nextnet after update' + required: false + type: boolean + default: false + +permissions: + contents: write + pull-requests: write + +jobs: + update-nightly: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/next' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: next + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '24' + + - name: Enable Corepack + run: corepack enable + + - name: Run update script + env: + PASSWORD: ${{ secrets.PASSWORD }} + CI: 1 + run: | + ARGS="" + + if [ -n "${{ inputs.version }}" ]; then + ARGS="$ARGS --version ${{ inputs.version }}" + fi + + if [ "${{ inputs.deploy }}" == "true" ]; then + ARGS="$ARGS --deploy" + fi + + node scripts/update-to-nightly.js $ARGS + + - name: Update PATH + run: | + VERSION=$(node -e "const p = JSON.parse(require('fs').readFileSync('package.json','utf-8')); console.log(p.dependencies['@aztec/aztec.js'].replace(/^v/,''))") + echo "$HOME/.aztec/versions/${VERSION}/bin" >> $GITHUB_PATH + echo "$HOME/.aztec/versions/${VERSION}/node_modules/.bin" >> $GITHUB_PATH + + - name: Get updated version + id: version + run: | + VERSION=$(node -e "const p = JSON.parse(require('fs').readFileSync('package.json','utf-8')); console.log(p.dependencies['@aztec/aztec.js'])") + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + commit-message: "chore: update to ${{ steps.version.outputs.version }}" + title: "chore: update to ${{ steps.version.outputs.version }}" + body: | + Automated update to Aztec nightly version ${{ steps.version.outputs.version }} + + **Changes:** + - Updated all @aztec/* dependencies in package.json + - Updated Nargo.toml files with new tag + - Updated README.md references + - Compiled contracts with new version + + **Note:** This PR was created automatically by the update-nightly workflow. + branch: automated-nightly-update-${{ steps.version.outputs.version }} + delete-branch: true + base: next diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6940f82 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,484 @@ +# Claude Context: GregoSwap + +## Project Overview + +GregoSwap is a decentralized token swap application built on the Aztec blockchain. It demonstrates private token swaps using an Automated Market Maker (AMM), with a token faucet (drip) mechanism using proof-of-password. + +**Key Features:** + +- Private token swaps (GregoCoin ↔ GregoCoinPremium) via AMM +- Token faucet with proof-of-password (PoP) contract +- Multi-flow onboarding supporting embedded and external wallets +- Network switching (local sandbox / devnet) + +**Tech Stack:** + +- React 18 + TypeScript +- Material-UI (MUI) component library +- Vite build tooling +- Aztec SDK (@aztec/aztec.js, @aztec/wallet-sdk) +- Yarn 4.5.2 package manager + +## Architecture + +### Layer Overview + +``` +src/ +├── contexts/ # State management (Context + Reducer pattern) +├── services/ # Pure functions for wallet/contract operations +├── components/ # React UI components +├── config/ # Network configuration +├── types/ # Shared type definitions +└── utils/ # Utility functions +``` + +### Provider Hierarchy (main.tsx) + +```tsx + + + + + + + + + + + +``` + +## State Management Pattern + +Each context uses a **colocated reducer pattern** with a factory function: + +``` +src/contexts/ +├── utils.ts # createReducerHook factory +├── network/ +│ ├── NetworkContext.tsx # No reducer (simple state) +│ └── index.ts +├── wallet/ +│ ├── WalletContext.tsx +│ ├── reducer.ts # State, actions, reducer, hook +│ └── index.ts +├── contracts/ +│ ├── ContractsContext.tsx +│ ├── reducer.ts +│ └── index.ts +├── onboarding/ +│ ├── OnboardingContext.tsx +│ ├── reducer.ts +│ └── index.ts +└── swap/ + ├── SwapContext.tsx + ├── reducer.ts + └── index.ts +``` + +### Reducer Factory Pattern (src/contexts/utils.ts) + +```typescript +// Creates a hook that returns [state, boundActions] tuple +export const useSwapReducer = createReducerHook(swapReducer, swapActions, initialSwapState); + +// Usage in context: +const [state, actions] = useSwapReducer(); +actions.setFromAmount('100'); // Type-safe, no dispatch() needed +``` + +**Key benefits:** + +- Type-safe action creators +- No dispatch callback boilerplate +- Actions bound automatically via `bindActions()` + +### Reducer File Structure + +Each reducer.ts exports: + +- **State type and initial state** (e.g., `SwapState`, `initialSwapState`) +- **Actions object** with action creators (e.g., `swapActions`) +- **Action union type** via `ActionsFrom` +- **Reducer function** (e.g., `swapReducer`) +- **Hook** created via `createReducerHook()` (e.g., `useSwapReducer`) + +## Contexts Reference + +### NetworkContext + +**Purpose:** Network selection and configuration + +**State:** + +- `activeNetwork: NetworkConfig` - Currently selected network +- `availableNetworks: NetworkConfig[]` - All discovered networks +- `isLoading: boolean` + +**Key behavior:** + +- Loads network configs from `src/config/networks/deployed-addresses.json` +- Persists selection to localStorage +- Excludes local network in production builds + +### WalletContext + +**Purpose:** Wallet instance management (embedded vs external) + +**State:** + +- `wallet: Wallet | null` - Active wallet +- `node: AztecNode | null` - Aztec node client +- `currentAddress: AztecAddress | null` - Selected account +- `isUsingEmbeddedWallet: boolean` - Wallet type flag +- `isLoading: boolean` / `error: string | null` + +**Key methods:** + +```typescript +discoverWallets(timeout?): DiscoverySession +initiateConnection(provider): Promise +confirmConnection(provider, pending): Promise +cancelConnection(pending): void +setCurrentAddress(address): void +disconnectWallet(): Promise +onWalletDisconnect(callback): () => void // Returns unsubscribe +``` + +**Key behavior:** + +- Auto-creates embedded wallet on network change +- Manages disconnect callback registry +- Reverts to embedded wallet on external disconnect + +### ContractsContext + +**Purpose:** Contract instances and registration + +**State:** + +- `contracts: { gregoCoin, gregoCoinPremium, amm, pop }` +- `isLoading: boolean` + +**Key methods:** + +```typescript +registerBaseContracts(): Promise // AMM + tokens +registerDripContracts(): Promise // PoP contract +getExchangeRate(): Promise +fetchBalances(): Promise<[bigint, bigint]> +simulateOnboardingQueries(): Promise<[rate, gcBal, gcpBal]> +swap(amountOut, amountInMax): Promise +drip(password, recipient): Promise +``` + +### OnboardingContext + +**Purpose:** Orchestrates multi-step onboarding flow + +**Status flow:** + +``` +idle → connecting → registering → simulating → + [if balance=0] → registering_drip → awaiting_drip → executing_drip → +completed +``` + +**State:** + +- `status: OnboardingStatus` - Current flow state +- `result: OnboardingResult | null` - Simulation results +- `needsDrip: boolean` - User needs to claim tokens +- `dripPassword: string | null` - PoP password +- `dripPhase: DripPhase` - Drip execution phase +- `pendingSwap: boolean` - Swap queued after onboarding +- `hasRegisteredBase/hasSimulated` - Tracking flags + +**Key behavior:** + +- Effects drive automatic state transitions +- Checks balance after simulation to determine drip need +- Persists completion to localStorage per address + +### SwapContext + +**Purpose:** Swap UI state and execution + +**State:** + +- `fromAmount: string` / `toAmount: string` +- `exchangeRate: number | null` +- `isLoadingRate: boolean` +- `phase: SwapPhase` - 'idle' | 'sending' | 'success' | 'error' +- `error: string | null` + +**Computed values (in context):** + +- `fromAmountUSD` / `toAmountUSD` +- `canSwap` - Whether swap button is enabled +- `isSwapping` - phase === 'sending' + +## Services Layer + +Pure functions in `src/services/` - contexts call these: + +### walletService.ts + +```typescript +createNodeClient(nodeUrl): AztecNode +createEmbeddedWallet(node): Promise +getChainInfo(network): ChainInfo +discoverWallets(chainInfo, timeout?): DiscoverySession +initiateConnection(provider): Promise +confirmConnection(pending): Promise +cancelConnection(pending): void +disconnectProvider(provider): Promise +``` + +### contractService.ts + +```typescript +// Registration +registerSwapContracts(wallet, node, network): Promise +registerDripContracts(wallet, node, network): Promise + +// Queries +getExchangeRate(wallet, contracts, fromAddress): Promise +fetchBalances(wallet, contracts, address): Promise<[bigint, bigint]> +simulateOnboardingQueries(wallet, contracts, address): Promise + +// Execution +executeSwap(contracts, fromAddress, amountOut, amountInMax): Promise +executeDrip(pop, password, recipient): Promise + +// Error parsing +parseSwapError(error): string +parseDripError(error): string +``` + +## Components Structure + +``` +src/components/ +├── App.tsx # Root component +├── OnboardingModal.tsx # Onboarding flow orchestrator +├── WalletChip.tsx # Header wallet button +├── NetworkSwitcher.tsx # Network dropdown +├── FooterInfo.tsx # Footer display +├── GregoSwapLogo.tsx # Logo +├── swap/ +│ ├── SwapContainer.tsx # Main swap interface +│ ├── SwapBox.tsx # Token input with balance +│ ├── SwapButton.tsx # Execute button +│ ├── ExchangeRateDisplay.tsx +│ ├── SwapProgress.tsx # Transaction progress +│ └── SwapErrorAlert.tsx # Error display +└── onboarding/ + ├── OnboardingProgress.tsx # Progress indicator + ├── WalletDiscovery.tsx # Scanning for wallets + ├── WalletSelection.tsx # Wallet list + ├── EmojiVerification.tsx # Secure channel verification + ├── EmojiGrid.tsx # Emoji selection grid + ├── AccountSelection.tsx # Account list + ├── ConnectingWallet.tsx # Connection status + ├── DripPasswordInput.tsx # PoP password form + ├── FlowMessages.tsx # Status messages + └── CompletionTransition.tsx # Success animation +``` + +## Types (src/types/index.ts) + +```typescript +interface NetworkConfig { + id: string; + name: string; + nodeUrl: string; + chainId: string; + rollupVersion: string; + contracts: { + gregoCoin: string; + gregoCoinPremium: string; + amm: string; + liquidityToken: string; + pop: string; + salt: string; + }; + deployer: { address: string }; + deployedAt: string; +} + +interface Balances { + gregoCoin: bigint | null; + gregoCoinPremium: bigint | null; +} + +const GREGOCOIN_USD_PRICE = 10; +const EXCHANGE_RATE_POLL_INTERVAL_MS = 10000; +``` + +## Key Data Flows + +### Initial Load + +``` +App mounts + → NetworkProvider loads deployed-addresses.json + → WalletProvider creates embedded wallet + node + → ContractsProvider registers base contracts (embedded wallet) + → OnboardingProvider ready for external wallet flow +``` + +### External Wallet Onboarding + +``` +User clicks "Connect Wallet" + → startOnboarding() → status='connecting' + → OnboardingModal discovers wallets + → User selects wallet → initiateConnection() + → User verifies emojis → confirmConnection() + → OnboardingContext detects wallet → registerBaseContracts() + → simulateOnboardingQueries() → check balance + → IF balance=0: registerDripContracts() → await password → drip() + → ELSE: complete onboarding +``` + +### Token Swap + +``` +User enters fromAmount + → setFromAmount() calculates toAmount + → User clicks "Swap" + → executeSwap() sends transaction + → phase: sending → mining → success + → SwapContainer refetches balances +``` + +## Smart Contracts + +Located in `contracts/`: + +1. **GregoCoin & GregoCoinPremium** (TokenContract) + - Standard Aztec token contracts + +2. **AMM** (AMMContract) + - `swap_tokens_for_exact_tokens()` method + +3. **ProofOfPassword** (ProofOfPasswordContract) + - `check_password_and_mint()` method + - Uses SponsoredFPC for fee payment + +## Build Configuration + +### vite.config.ts + +- **Node polyfills:** buffer, path for browser +- **WASM headers:** Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy +- **Chunk size limits:** Main bundle < 1500KB, others < 8000KB + +### Scripts (package.json) + +```bash +yarn serve # Dev server +yarn build # Production build +yarn compile:contracts # Compile Noir contracts +yarn deploy:local # Deploy to local sandbox +yarn deploy:devnet # Deploy to devnet +yarn test # Run contract tests +``` + +### Local Development + +```bash +# Terminal 1: Start Aztec sandbox +aztec start --local-network + +# Terminal 2: Deploy contracts +PASSWORD=test123 yarn deploy:local + +# Terminal 3: Run dev server +yarn serve +``` + +## Theme (src/theme.ts) + +**Color palette:** + +- Primary: Chartreuse green (#D4FF28) - Aztec branded +- Secondary: Deep purple (#80336A) +- Background: Pure black (#000000) +- Text: Light parchment (#F2EEE1) + +**Typography:** Geist font family + +## Important Patterns + +### Effect-Driven State Machine (OnboardingContext) + +Effects check preconditions and advance state automatically: + +```typescript +// When wallet connects, mark registered and advance +useEffect(() => { + if (status === 'connecting' && wallet && currentAddress) { + actions.markRegistered(); + actions.advanceStatus('registering'); + } +}, [status, wallet, currentAddress]); +``` + +### Lazy Contract Registration + +- Embedded wallet: Auto-register on mount +- External wallet: Register during onboarding +- Two stages: Base (swap) then Drip (PoP) if needed + +### BigDecimal Precision (src/utils/bigDecimal.ts) + +Used for exchange rate calculations with 18 decimal precision. + +## Common Pitfalls + +1. **Don't use re-exports** - Import directly from specific files + + ```typescript + // WRONG + import { useWallet } from '../contexts'; + + // RIGHT + import { useWallet } from '../contexts/wallet'; + ``` + +2. **Keep reducer actions namespaced** - e.g., `'swap/SET_RATE'` + +3. **Effect dependencies** - OnboardingContext effects must include all dependencies to avoid stale closures + +4. **Balance checks** - Embedded wallet can't query private balances; only external wallets show balances + +5. **Network switching** - Requires wallet disconnect and state reset + +## File Reference + +### Critical Files + +- `src/main.tsx` - Provider hierarchy +- `src/contexts/*/reducer.ts` - State machines +- `src/contexts/*/Context.tsx` - Context providers with effects +- `src/services/*.ts` - Business logic (pure functions) +- `src/components/OnboardingModal.tsx` - Onboarding orchestration +- `src/components/swap/SwapContainer.tsx` - Swap UI logic + +### Configuration + +- `vite.config.ts` - Build configuration +- `tsconfig.json` - TypeScript config +- `package.json` - Dependencies and scripts +- `src/config/networks/` - Network config loader + +## Version Information + +- **Aztec SDK:** v4.0.0-nightly.20260205 +- **React:** 18.3.1 +- **Vite:** 7.1.4 +- **Node.js:** v22+ +- **Yarn:** 4.5.2 diff --git a/README.md b/README.md index 075247a..4dfc64c 100644 --- a/README.md +++ b/README.md @@ -28,17 +28,27 @@ yarn install ### 2. Install Aztec CLI ```bash -curl -s https://install.aztec.network | bash +VERSION=4.0.0-nightly.20260205 bash -i <(curl -sL https://install.aztec.network/4.0.0-nightly.20260205/) ``` ### 3. Set Aztec Version -The project uses Aztec version `v3.0.0-devnet.6-patch.1`. Set it using: +The project uses Aztec version `v4.0.0-devnet.1-patch.0`. Set it using: ```bash -aztec-up 3.0.0-devnet.6-patch.1 +aztec-up install 4.0.0-nightly.20260205 ``` +## Updating to Latest Nightly + +```bash +node scripts/update-to-nightly.js # auto-detect latest +node scripts/update-to-nightly.js --version 4.0.0-nightly.20260206 # specific version +PASSWORD= node scripts/update-to-nightly.js --deploy # update + deploy to nextnet +``` + +Use `--skip-aztec-up` to skip Aztec CLI installation. In CI (`CI=1`), the script installs Aztec via curl instead of aztec-up. + ## Development Setup ### Running Locally with Aztec Sandbox diff --git a/contracts/proof_of_password/Nargo.toml b/contracts/proof_of_password/Nargo.toml index fae683b..db3517d 100644 --- a/contracts/proof_of_password/Nargo.toml +++ b/contracts/proof_of_password/Nargo.toml @@ -4,7 +4,7 @@ type = "contract" authors = [""] [dependencies] -aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-devnet.6-patch.1", directory = "noir-projects/aztec-nr/aztec" } -token = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-devnet.6-patch.1", directory = "noir-projects/noir-contracts/contracts/app/token_contract" } +aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.1-patch.0", directory = "noir-projects/aztec-nr/aztec" } +token = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.1-patch.0", directory = "noir-projects/noir-contracts/contracts/app/token_contract" } poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } -compressed_string = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-devnet.6-patch.1", directory = "noir-projects/aztec-nr/compressed-string" } \ No newline at end of file +compressed_string = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.1-patch.0", directory = "noir-projects/aztec-nr/compressed-string" } \ No newline at end of file diff --git a/contracts/proof_of_password/src/main.nr b/contracts/proof_of_password/src/main.nr index 92c675a..09d48a2 100644 --- a/contracts/proof_of_password/src/main.nr +++ b/contracts/proof_of_password/src/main.nr @@ -8,7 +8,7 @@ pub contract ProofOfPassword { use aztec::{ macros::{functions::{external, initializer, only_self}, storage::storage}, oracle::notes::set_sender_for_tags, - protocol_types::{address::AztecAddress, hash::poseidon2_hash, traits::{Serialize, ToField}}, + protocol::{address::AztecAddress, hash::poseidon2_hash, traits::{Serialize, ToField}}, state_vars::PublicImmutable, }; use compressed_string::FieldCompressedString; diff --git a/contracts/proof_of_password/src/test/mod.nr b/contracts/proof_of_password/src/test/mod.nr index c524a50..82c6ae6 100644 --- a/contracts/proof_of_password/src/test/mod.nr +++ b/contracts/proof_of_password/src/test/mod.nr @@ -1,7 +1,5 @@ use super::ProofOfPassword; -use aztec::{ - protocol_types::address::AztecAddress, test::helpers::test_environment::TestEnvironment, -}; +use aztec::{protocol::address::AztecAddress, test::helpers::test_environment::TestEnvironment}; use token::Token; global PASSWORD: str<31> = "potato0000000000000000000000000"; @@ -66,7 +64,7 @@ unconstrained fn fails_on_incorrect_password() { ); } -#[test(should_fail_with = "Contract execution has reverted: Attempted to emit duplicate siloed nullifier")] +#[test(should_fail_with = "Attempted to emit duplicate siloed nullifier")] unconstrained fn fails_on_double_dip() { let (env, pop_contract_address, _, recipient) = setup(); diff --git a/package.json b/package.json index b3f5a07..2a45b1d 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,13 @@ "serve": "vite", "build": "tsc -b && vite build", "lint": "eslint .", - "copy:dependencies": "cd contracts && aztec check && WORKDIR=$(pwd) && cd $HOME/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.6-patch.1/noir-projects/noir-contracts && aztec compile --package token_contract && mkdir -p $WORKDIR/target && cp $HOME/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.6-patch.1/noir-projects/noir-contracts/target/token_contract-Token.json $WORKDIR/target/token_contract-Token.json", + "copy:dependencies": "cd contracts && nargo check && WORKDIR=$(pwd) && cd $HOME/nargo/github.com/AztecProtocol/aztec-packages/v4.0.0-devnet.1-patch.0/noir-projects/noir-contracts && aztec compile --package token_contract && mkdir -p $WORKDIR/target && cp $HOME/nargo/github.com/AztecProtocol/aztec-packages/v4.0.0-devnet.1-patch.0/noir-projects/noir-contracts/target/token_contract-Token.json $WORKDIR/target/token_contract-Token.json", "compile:contracts": "cd contracts && aztec compile --package proof_of_password && aztec codegen ./target/proof_of_password-ProofOfPassword.json", "test": "cd contracts && aztec test", "preview": "vite preview", "deploy:local": "node --experimental-transform-types scripts/deploy.ts --network local", "deploy:devnet": "node --experimental-transform-types scripts/deploy.ts --network devnet", + "deploy:nextnet": "node --experimental-transform-types scripts/deploy.ts --network nextnet", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "local-aztec:enable": "node scripts/toggle-local-aztec.js enable && corepack yarn install", @@ -22,15 +23,15 @@ "local-aztec:status": "node scripts/toggle-local-aztec.js status" }, "dependencies": { - "@aztec/accounts": "v3.0.0-devnet.6-patch.1", - "@aztec/aztec.js": "v3.0.0-devnet.6-patch.1", - "@aztec/constants": "v3.0.0-devnet.6-patch.1", - "@aztec/entrypoints": "v3.0.0-devnet.6-patch.1", - "@aztec/foundation": "v3.0.0-devnet.6-patch.1", - "@aztec/noir-contracts.js": "v3.0.0-devnet.6-patch.1", - "@aztec/pxe": "v3.0.0-devnet.6-patch.1", - "@aztec/stdlib": "v3.0.0-devnet.6-patch.1", - "@aztec/wallet-sdk": "v3.0.0-devnet.6-patch.1", + "@aztec/accounts": "v4.0.0-devnet.1-patch.0", + "@aztec/aztec.js": "v4.0.0-devnet.1-patch.0", + "@aztec/constants": "v4.0.0-devnet.1-patch.0", + "@aztec/entrypoints": "v4.0.0-devnet.1-patch.0", + "@aztec/foundation": "v4.0.0-devnet.1-patch.0", + "@aztec/noir-contracts.js": "v4.0.0-devnet.1-patch.0", + "@aztec/pxe": "v4.0.0-devnet.1-patch.0", + "@aztec/stdlib": "v4.0.0-devnet.1-patch.0", + "@aztec/wallet-sdk": "v4.0.0-devnet.1-patch.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.3.1", @@ -43,7 +44,7 @@ "zod": "^3.23.8" }, "devDependencies": { - "@aztec/test-wallet": "v3.0.0-devnet.6-patch.1", + "@aztec/test-wallet": "v4.0.0-devnet.1-patch.0", "@eslint/js": "^9.18.0", "@playwright/test": "1.49.0", "@types/buffer-json": "^2", diff --git a/scripts/deploy.ts b/scripts/deploy.ts index 8800d39..af3be80 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -12,23 +12,23 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { createAztecNodeClient, type AztecNode } from '@aztec/aztec.js/node'; import { getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract'; import { Fr } from '@aztec/foundation/curves/bn254'; -import type { DeployAccountOptions } from '@aztec/aztec.js/wallet'; import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; import { ProofOfPasswordContract } from '../contracts/target/ProofOfPassword.ts'; import { createLogger } from '@aztec/foundation/log'; +import { BatchCall } from '@aztec/aztec.js/contracts'; // Parse network from CLI args (--network ) function getNetworkFromArgs(): string { const args = process.argv.slice(2); const networkIndex = args.indexOf('--network'); if (networkIndex === -1 || networkIndex === args.length - 1) { - console.error('Usage: node deploy.ts --network '); + console.error('Usage: node deploy.ts --network '); process.exit(1); } const network = args[networkIndex + 1]; - if (!['local', 'devnet'].includes(network)) { - console.error(`Invalid network: ${network}. Must be 'local' or 'devnet'`); + if (!['local', 'devnet', 'nextnet'].includes(network)) { + console.error(`Invalid network: ${network}. Must be 'local', 'devnet' or 'nextnet'`); process.exit(1); } return network; @@ -39,7 +39,8 @@ const NETWORK = getNetworkFromArgs(); // Network-specific node URLs (hardcoded, not configurable) const NETWORK_URLS: Record = { local: 'http://localhost:8080', - devnet: 'https://next.devnet.aztec-labs.com', + devnet: 'https://v4-devnet-1.aztec-labs.com', + nextnet: 'https://nextnet.aztec-labs.com', }; const AZTEC_NODE_URL = NETWORK_URLS[NETWORK]; @@ -59,7 +60,7 @@ async function setupWallet(aztecNode: AztecNode) { fs.rmSync(PXE_STORE_DIR, { recursive: true, force: true }); const config = getPXEConfig(); - config.dataDirectory = PXE_STORE_DIR; + //config.dataDirectory = PXE_STORE_DIR; config.proverEnabled = PROVER_ENABLED; return await TestWallet.create(aztecNode, config, { @@ -86,15 +87,16 @@ async function createAccount(wallet: TestWallet) { const deployMethod = await accountManager.getDeployMethod(); const sponsoredPFCContract = await getSponsoredPFCContract(); const paymentMethod = new SponsoredFeePaymentMethod(sponsoredPFCContract.address); - const deployOpts: DeployAccountOptions = { + const deployOpts = { from: AztecAddress.ZERO, fee: { paymentMethod, }, skipClassPublication: true, skipInstancePublication: true, + wait: { timeout: 120 }, }; - await deployMethod.send(deployOpts).wait({ timeout: 120 }); + await deployMethod.send(deployOpts); return { address: accountManager.address, @@ -109,32 +111,39 @@ async function deployContracts(wallet: TestWallet, deployer: AztecAddress) { const contractAddressSalt = Fr.random(); - const gregoCoin = await TokenContract.deploy(wallet, deployer, 'GregoCoin', 'GRG', 18) - .send({ from: deployer, fee: { paymentMethod }, contractAddressSalt }) - .deployed({ timeout: 120 }); - - const gregoCoinPremium = await TokenContract.deploy(wallet, deployer, 'GregoCoinPremium', 'GRGP', 18) - .send({ from: deployer, fee: { paymentMethod }, contractAddressSalt }) - .deployed({ timeout: 120 }); + const gregoCoin = await TokenContract.deploy(wallet, deployer, 'GregoCoin', 'GRG', 18).send({ + from: deployer, + fee: { paymentMethod }, + contractAddressSalt, + wait: { timeout: 120 }, + }); - const liquidityToken = await TokenContract.deploy(wallet, deployer, 'LiquidityToken', 'LQT', 18) - .send({ from: deployer, fee: { paymentMethod }, contractAddressSalt }) - .deployed({ timeout: 120 }); + const gregoCoinPremium = await TokenContract.deploy(wallet, deployer, 'GregoCoinPremium', 'GRGP', 18).send({ + from: deployer, + fee: { paymentMethod }, + contractAddressSalt, + wait: { timeout: 120 }, + }); - const amm = await AMMContract.deploy(wallet, gregoCoin.address, gregoCoinPremium.address, liquidityToken.address) - .send({ from: deployer, fee: { paymentMethod }, contractAddressSalt }) - .deployed({ timeout: 120 }); + const liquidityToken = await TokenContract.deploy(wallet, deployer, 'LiquidityToken', 'LQT', 18).send({ + from: deployer, + fee: { paymentMethod }, + contractAddressSalt, + wait: { timeout: 120 }, + }); - await liquidityToken.methods.set_minter(amm.address, true).send({ from: deployer, fee: { paymentMethod } }).wait(); + const amm = await AMMContract.deploy( + wallet, + gregoCoin.address, + gregoCoinPremium.address, + liquidityToken.address, + ).send({ from: deployer, fee: { paymentMethod }, contractAddressSalt, wait: { timeout: 120 } }); - await gregoCoin.methods - .mint_to_private(deployer, INITIAL_TOKEN_BALANCE) - .send({ from: deployer, fee: { paymentMethod } }) - .wait({ timeout: 120 }); - await gregoCoinPremium.methods - .mint_to_private(deployer, INITIAL_TOKEN_BALANCE) - .send({ from: deployer, fee: { paymentMethod } }) - .wait({ timeout: 120 }); + await new BatchCall(wallet, [ + liquidityToken.methods.set_minter(amm.address, true), + gregoCoin.methods.mint_to_private(deployer, INITIAL_TOKEN_BALANCE), + gregoCoinPremium.methods.mint_to_private(deployer, INITIAL_TOKEN_BALANCE), + ]).send({ from: deployer, fee: { paymentMethod }, wait: { timeout: 120 } }); const nonceForAuthwits = Fr.random(); const token0Authwit = await wallet.createAuthWit(deployer, { @@ -156,25 +165,36 @@ async function deployContracts(wallet: TestWallet, deployer: AztecAddress) { ), }); - const addLiquidityInteraction = amm.methods - .add_liquidity( - INITIAL_TOKEN_BALANCE, - INITIAL_TOKEN_BALANCE, - INITIAL_TOKEN_BALANCE, - INITIAL_TOKEN_BALANCE, - nonceForAuthwits, - ) - .with({ authWitnesses: [token0Authwit, token1Authwit] }); - await addLiquidityInteraction.send({ from: deployer, fee: { paymentMethod } }).wait({ timeout: 120 }); - - const pop = await ProofOfPasswordContract.deploy(wallet, gregoCoin.address, PASSWORD) - .send({ from: deployer, contractAddressSalt, fee: { paymentMethod } }) - .deployed({ timeout: 120 }); - - await gregoCoin.methods - .set_minter(pop.address, true) - .send({ from: deployer, fee: { paymentMethod } }) - .wait({ timeout: 120 }); + await new BatchCall(wallet, [ + liquidityToken.methods.set_minter(amm.address, true), + gregoCoin.methods.mint_to_private(deployer, INITIAL_TOKEN_BALANCE), + gregoCoinPremium.methods.mint_to_private(deployer, INITIAL_TOKEN_BALANCE), + amm.methods + .add_liquidity( + INITIAL_TOKEN_BALANCE, + INITIAL_TOKEN_BALANCE, + INITIAL_TOKEN_BALANCE, + INITIAL_TOKEN_BALANCE, + nonceForAuthwits, + ) + .with({ authWitnesses: [token0Authwit, token1Authwit] }), + ]).send({ from: deployer, fee: { paymentMethod }, wait: { timeout: 120 } }); + + const popDeployMethod = ProofOfPasswordContract.deploy(wallet, gregoCoin.address, PASSWORD); + + // Address is computed lazily. This is bad + await popDeployMethod.getInstance(); + + const pop = ProofOfPasswordContract.at(popDeployMethod.address, wallet); + + await new BatchCall(wallet, [ + await popDeployMethod.request({ contractAddressSalt, deployer }), + gregoCoin.methods.set_minter(pop.address, true), + ]).send({ + from: deployer, + fee: { paymentMethod }, + wait: { timeout: 120 }, + }); return { gregoCoinAddress: gregoCoin.address.toString(), @@ -194,7 +214,6 @@ async function writeNetworkConfig(network: string, deploymentInfo: any) { const configPath = path.join(configDir, `${network}.json`); const config = { id: network, - name: network === 'local' ? 'Local Node' : 'Devnet', nodeUrl: AZTEC_NODE_URL, chainId: deploymentInfo.chainId, rollupVersion: deploymentInfo.rollupVersion, @@ -258,6 +277,7 @@ async function createAccountAndDeployContract() { // Clean up the PXE store fs.rmSync(PXE_STORE_DIR, { recursive: true, force: true }); + process.exit(0); } createAccountAndDeployContract().catch(error => { diff --git a/scripts/update-to-nightly.js b/scripts/update-to-nightly.js new file mode 100755 index 0000000..51244cc --- /dev/null +++ b/scripts/update-to-nightly.js @@ -0,0 +1,225 @@ +#!/usr/bin/env node + +/** + * Update gregoswap to the latest Aztec nightly version. + * + * Usage: + * node scripts/update-to-nightly.js [--version VERSION] [--deploy [NETWORK]] [--skip-aztec-up] + */ + +import { readFileSync, writeFileSync } from "fs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import { execSync } from "child_process"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = resolve(__dirname, ".."); + +// Color codes +const COLORS = { + reset: "\x1b[0m", + red: "\x1b[31m", + green: "\x1b[32m", + yellow: "\x1b[33m", +}; + +function log(color, message) { + console.log(`${color}${message}${COLORS.reset}`); +} + +function exec(command, options = {}) { + return execSync(command, { + cwd: ROOT, + stdio: options.silent ? "pipe" : "inherit", + encoding: "utf-8", + ...options, + }); +} + +async function fetchLatestNightly() { + log(COLORS.yellow, "Fetching latest nightly from npm..."); + try { + const output = exec("npm view @aztec/aztec.js versions --json", { silent: true }); + const versions = JSON.parse(output); + const nightlies = versions.filter((v) => v.match(/^4\.0\.0-nightly\.\d+$/)); + const latest = nightlies[nightlies.length - 1]; + if (!latest) { + throw new Error("No nightly versions found"); + } + return latest; + } catch (error) { + log(COLORS.red, "Failed to fetch latest nightly version from npm"); + log(COLORS.red, "Please specify a version with --version"); + process.exit(1); + } +} + +function updatePackageJson(version) { + log(COLORS.yellow, "[1/7] Updating package.json..."); + const path = resolve(ROOT, "package.json"); + let content = readFileSync(path, "utf-8"); + + // Update dependencies + content = content.replace( + /@aztec\/([^"]+)": "v4\.0\.0-nightly\.\d+"/g, + `@aztec/$1": "v${version}"` + ); + + // Update version in copy:dependencies script + content = content.replace(/v4\.0\.0-nightly\.\d+/g, `v${version}`); + + writeFileSync(path, content, "utf-8"); + log(COLORS.green, "✓ package.json updated\n"); +} + +function updateNargoToml(version) { + log(COLORS.yellow, "[2/7] Updating Nargo.toml files..."); + const path = resolve(ROOT, "contracts/proof_of_password/Nargo.toml"); + let content = readFileSync(path, "utf-8"); + + content = content.replace(/tag = "v4\.0\.0-nightly\.\d+"/g, `tag = "v${version}"`); + + writeFileSync(path, content, "utf-8"); + log(COLORS.green, "✓ Nargo.toml files updated\n"); +} + +function updateReadme(version) { + log(COLORS.yellow, "[3/7] Updating README.md..."); + const path = resolve(ROOT, "README.md"); + let content = readFileSync(path, "utf-8"); + + content = content.replace(/v4\.0\.0-nightly\.\d+/g, `v${version}`); + + writeFileSync(path, content, "utf-8"); + log(COLORS.green, "✓ README.md updated\n"); +} + +function installDependencies() { + log(COLORS.yellow, "[4/7] Running yarn install..."); + exec("yarn install"); + log(COLORS.green, "✓ Dependencies installed\n"); +} + +function installAztecCLI(version) { + log(COLORS.yellow, `[5/7] Installing Aztec CLI version ${version}...`); + + const isCI = !!process.env.CI; + + if (isCI) { + // CI environment - use direct curl install + log(COLORS.yellow, `Running version-specific installer for ${version}...`); + process.env.FOUNDRY_DIR = `${process.env.HOME}/.foundry`; + exec(`curl -fsSL "https://install.aztec.network/${version}/install" | VERSION="${version}" bash`); + + // Update PATH for current session + process.env.PATH = `${process.env.HOME}/.aztec/versions/${version}/bin:${process.env.PATH}`; + process.env.PATH = `${process.env.HOME}/.aztec/versions/${version}/node_modules/.bin:${process.env.PATH}`; + log(COLORS.green, "✓ Aztec CLI installed (CI mode)\n"); + } else { + // Local environment with aztec-up + try { + exec("command -v aztec-up", { silent: true }); + exec(`aztec-up install ${version}`); + log(COLORS.green, "✓ Aztec CLI updated\n"); + } catch { + log(COLORS.red, `Warning: aztec-up not found in PATH. Please install manually with: aztec-up install ${version}\n`); + } + } +} + +function compileContracts() { + log(COLORS.yellow, "[6/7] Compiling contracts..."); + exec("yarn compile:contracts"); + log(COLORS.green, "✓ Contracts compiled\n"); +} + +const VALID_NETWORKS = ["local", "devnet", "nextnet"]; + +function deploy(network) { + log(COLORS.yellow, `[7/7] Deploying to ${network}...`); + if (!process.env.PASSWORD) { + log(COLORS.red, "ERROR: PASSWORD environment variable not set"); + log(COLORS.red, "Please set PASSWORD before running with --deploy flag"); + process.exit(1); + } + exec(`yarn deploy:${network}`); + log(COLORS.green, `✓ Deployed to ${network}\n`); +} + +async function main() { + log(COLORS.green, "=== Gregoswap Nightly Update Script ===\n"); + + // Parse arguments + const args = process.argv.slice(2); + let version = null; + let deployNetwork = null; + let skipAztecUp = false; + + for (let i = 0; i < args.length; i++) { + if (args[i] === "--version" && args[i + 1]) { + version = args[i + 1].replace(/^v/, ""); + i++; + } else if (args[i] === "--deploy") { + const next = args[i + 1]; + if (next && !next.startsWith("--")) { + if (!VALID_NETWORKS.includes(next)) { + log(COLORS.red, `ERROR: Unknown network "${next}". Valid networks: ${VALID_NETWORKS.join(", ")}`); + process.exit(1); + } + deployNetwork = next; + i++; + } else { + deployNetwork = "nextnet"; + } + } else if (args[i] === "--skip-aztec-up") { + skipAztecUp = true; + } else if (args[i] === "--help") { + console.log("Usage: node scripts/update-to-nightly.js [OPTIONS]"); + console.log("\nOptions:"); + console.log(" --version VERSION Specify nightly version (e.g., 4.0.0-nightly.20260206)"); + console.log(" --deploy [NETWORK] Deploy after update (default: nextnet, options: local, devnet, nextnet)"); + console.log(" --skip-aztec-up Skip Aztec CLI installation"); + console.log(" --help Show this help message"); + process.exit(0); + } + } + + // Fetch latest if not specified + if (!version) { + version = await fetchLatestNightly(); + log(COLORS.green, `Latest nightly version: v${version}\n`); + } else { + log(COLORS.green, `Updating to version: v${version}\n`); + } + + // Run update steps + updatePackageJson(version); + updateNargoToml(version); + updateReadme(version); + installDependencies(); + + if (!skipAztecUp) { + installAztecCLI(version); + } else { + log(COLORS.yellow, "[5/7] Skipping Aztec CLI installation (--skip-aztec-up flag set)\n"); + } + + compileContracts(); + + if (deployNetwork) { + deploy(deployNetwork); + } else { + log(COLORS.yellow, "[7/7] Skipping deployment (use --deploy [network] flag to deploy)\n"); + } + + log(COLORS.green, "=== Update Complete ==="); + log(COLORS.green, `Version: v${version}`); + if (!deployNetwork) { + log(COLORS.yellow, "To deploy, run: PASSWORD= node scripts/update-to-nightly.js --deploy [local|devnet|nextnet]"); + } +} + +main().catch((error) => { + log(COLORS.red, `Error: ${error.message}`); + process.exit(1); +}); diff --git a/src/App.tsx b/src/App.tsx index acd9f22..2005cb3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,21 +5,21 @@ import { WalletChip } from './components/WalletChip'; import { NetworkSwitcher } from './components/NetworkSwitcher'; import { FooterInfo } from './components/FooterInfo'; import { SwapContainer } from './components/swap'; -import { useWallet } from './contexts/WalletContext'; -import { useOnboarding } from './contexts/OnboardingContext'; +import { useWallet } from './contexts/wallet'; +import { useOnboarding } from './contexts/onboarding'; import { OnboardingModal } from './components/OnboardingModal'; import type { AztecAddress } from '@aztec/aztec.js/addresses'; export function App() { const { disconnectWallet, setCurrentAddress, isUsingEmbeddedWallet, currentAddress, error: walletError, isLoading: walletLoading } = useWallet(); - const { isOnboardingModalOpen, startOnboardingFlow, resetOnboarding } = useOnboarding(); + const { isOnboardingModalOpen, startOnboarding, resetOnboarding } = useOnboarding(); const handleWalletClick = () => { // If already connected, start a new onboarding flow to change wallet if (!isUsingEmbeddedWallet && currentAddress) { resetOnboarding(); } - startOnboardingFlow('swap'); // Default to swap flow when clicked from wallet chip + startOnboarding(); // Start onboarding when clicked from wallet chip }; const handleDisconnect = async () => { diff --git a/src/components/DripModal.tsx b/src/components/DripModal.tsx deleted file mode 100644 index 3b57de7..0000000 --- a/src/components/DripModal.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import { useState } from 'react'; -import { - Dialog, - DialogTitle, - DialogContent, - DialogActions, - TextField, - Button, - Box, - Typography, - CircularProgress, - Alert, - LinearProgress, -} from '@mui/material'; -import WaterDropIcon from '@mui/icons-material/WaterDrop'; -import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import { useContracts } from '../contexts/ContractsContext'; -import { useWallet } from '../contexts/WalletContext'; -import { waitForTxWithPhases } from '../utils/txUtils'; - -interface DripModalProps { - open: boolean; - onClose: () => void; - onSuccess?: () => void; -} - -type DripPhase = 'sending' | 'mining'; - -export function DripModal({ open, onClose, onSuccess }: DripModalProps) { - const [password, setPassword] = useState(''); - const [isDripping, setIsDripping] = useState(false); - const [error, setError] = useState(null); - const [success, setSuccess] = useState(false); - const [currentPhase, setCurrentPhase] = useState(null); - const { drip } = useContracts(); - const { currentAddress } = useWallet(); - - const handleClose = () => { - if (!isDripping) { - setPassword(''); - setError(null); - setSuccess(false); - setCurrentPhase(null); - onClose(); - } - }; - - const handleDrip = async () => { - if (!password || !currentAddress) return; - - setError(null); - setSuccess(false); - setIsDripping(true); - setCurrentPhase('sending'); - - try { - const sentTx = await drip(password, currentAddress); - await waitForTxWithPhases(sentTx, setCurrentPhase); - setSuccess(true); - setPassword(''); - // Trigger success callback (e.g., refresh balances) - if (onSuccess) { - onSuccess(); - } - // Auto-close after 2 seconds on success - setTimeout(() => { - handleClose(); - }, 2000); - } catch (err) { - console.error('Drip error:', err); - const errorMessage = - err instanceof Error ? err.message : 'Failed to claim GregoCoin. Please check your password and try again.'; - setError(errorMessage); - setCurrentPhase(null); - } finally { - setIsDripping(false); - } - }; - - const getPhaseLabel = (phase: DripPhase | null) => { - switch (phase) { - case 'sending': - return 'Sending transaction...'; - case 'mining': - return 'Mining transaction...'; - default: - return ''; - } - }; - - return ( - - - - - Claim Free GregoCoin - - - - - {success ? ( - - - - GregoCoin Claimed Successfully! - - - Your tokens will be available shortly. - - - ) : ( - <> - - Enter the password to receive free GregoCoin tokens. This is a one-time claim to help you get started. - - - setPassword(e.target.value)} - disabled={isDripping} - onKeyPress={(e) => { - if (e.key === 'Enter' && password && !isDripping) { - handleDrip(); - } - }} - autoFocus - sx={{ mb: 2 }} - /> - - {isDripping && currentPhase && ( - - - - - {getPhaseLabel(currentPhase)} - - - - - )} - - {error && ( - - {error} - - )} - - )} - - - {!success && ( - - - - - )} - - ); -} diff --git a/src/components/NetworkSwitcher.tsx b/src/components/NetworkSwitcher.tsx index ae94cd4..dd6cbe8 100644 --- a/src/components/NetworkSwitcher.tsx +++ b/src/components/NetworkSwitcher.tsx @@ -11,9 +11,9 @@ import { Typography, } from '@mui/material'; import type { SelectChangeEvent } from '@mui/material'; -import { useNetwork } from '../contexts/NetworkContext'; -import { useWallet } from '../contexts/WalletContext'; -import { useOnboarding } from '../contexts/OnboardingContext'; +import { useNetwork } from '../contexts/network'; +import { useWallet } from '../contexts/wallet'; +import { useOnboarding } from '../contexts/onboarding'; export function NetworkSwitcher() { const { activeNetwork, availableNetworks, switchNetwork } = useNetwork(); @@ -107,7 +107,7 @@ export function NetworkSwitcher() { backgroundColor: network.id === activeNetwork.id ? 'primary.main' : 'text.disabled', }} /> - {network.name} + {network.id} ))} @@ -136,7 +136,7 @@ export function NetworkSwitcher() { {pendingNetwork && ( - {activeNetwork.name} → {availableNetworks.find(n => n.id === pendingNetwork)?.name} + {activeNetwork.id} → {availableNetworks.find(n => n.id === pendingNetwork)?.id} )} diff --git a/src/components/OnboardingModal.tsx b/src/components/OnboardingModal.tsx index 6e80be7..fa63ac9 100644 --- a/src/components/OnboardingModal.tsx +++ b/src/components/OnboardingModal.tsx @@ -1,39 +1,32 @@ +/** + * OnboardingModal Component + * Orchestrates the onboarding flow using subcomponents + */ + import { useEffect, useState } from 'react'; -import { - Dialog, - DialogTitle, - DialogContent, - Box, - Typography, - CircularProgress, - Alert, - List, - ListItem, - ListItemIcon, - ListItemText, - LinearProgress, - ListItemButton, - Fade, - Collapse, - TextField, - Button, - IconButton, -} from '@mui/material'; -import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked'; -import SwapHorizIcon from '@mui/icons-material/SwapHoriz'; -import WaterDropIcon from '@mui/icons-material/WaterDrop'; +import { Dialog, DialogTitle, DialogContent, Box, Alert, Button, IconButton, Collapse } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; -import ErrorIcon from '@mui/icons-material/Error'; -import SecurityIcon from '@mui/icons-material/Security'; -import { useOnboarding } from '../contexts/OnboardingContext'; -import { useWallet, type DiscoveredWalletWithEmoji } from '../contexts/WalletContext'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import { useOnboarding } from '../contexts/onboarding'; +import { useWallet } from '../contexts/wallet'; +import { useNetwork } from '../contexts/network'; import type { AztecAddress } from '@aztec/aztec.js/addresses'; import type { Aliased } from '@aztec/aztec.js/wallet'; -import RefreshIcon from '@mui/icons-material/Refresh'; -import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; - -type WalletConnectionPhase = 'discovering' | 'verifying' | 'connecting' | 'selecting_account'; +import type { WalletProvider, PendingConnection } from '@aztec/wallet-sdk/manager'; +import { createGregoSwapCapabilities } from '../config/capabilities'; +import { + OnboardingProgress, + WalletDiscovery, + WalletSelection, + EmojiVerification, + AccountSelection, + ConnectingWallet, + DripPasswordInput, + CompletionTransition, + FlowMessages, +} from './onboarding'; + +type WalletConnectionPhase = 'discovering' | 'selecting_wallet' | 'verifying' | 'connecting' | 'selecting_account'; interface OnboardingModalProps { open: boolean; @@ -46,157 +39,193 @@ export function OnboardingModal({ open, onAccountSelect }: OnboardingModalProps) error, currentStep, totalSteps, + steps, resetOnboarding, - flowType, - currentFlow, closeModal, completeDripOnboarding, isSwapPending, - isDripPending, + dripPhase, + dripError, + dismissDripError, + setSimulationGrant, + hasSimulationGrant, } = useOnboarding(); - const { discoverWallets, connectToProvider, onWalletDisconnect } = useWallet(); + const { discoverWallets, initiateConnection, confirmConnection, cancelConnection, onWalletDisconnect } = useWallet(); + const { activeNetwork } = useNetwork(); + + // Wallet connection state const [accounts, setAccounts] = useState[]>([]); const [isLoadingAccounts, setIsLoadingAccounts] = useState(false); const [accountsError, setAccountsError] = useState(null); - - // Wallet discovery and verification state const [connectionPhase, setConnectionPhase] = useState('discovering'); - const [discoveredWallets, setDiscoveredWallets] = useState([]); - const [selectedWallet, setSelectedWallet] = useState(null); - - // Track if we need to re-discover due to wallet disconnect + const [discoveredWallets, setDiscoveredWallets] = useState([]); + const [selectedWallet, setSelectedWallet] = useState(null); + const [pendingConnection, setPendingConnection] = useState(null); const [needsRediscovery, setNeedsRediscovery] = useState(false); - - // Drip flow state - const [password, setPassword] = useState(''); + const [cancelledWalletIds, setCancelledWalletIds] = useState>(new Set()); // Transition animation state const [showCompletionCheck, setShowCompletionCheck] = useState(false); const [showSwapIcon, setShowSwapIcon] = useState(false); - // Get steps from flow config - const steps = currentFlow?.steps || []; + const isLoading = status !== 'idle' && status !== 'completed' && status !== 'error'; // Listen for unexpected wallet disconnection useEffect(() => { const unsubscribe = onWalletDisconnect(() => { - // Mark that we need to re-discover wallets (old MessagePorts are now invalid) setNeedsRediscovery(true); - // Clear discovered wallets since they're now stale setDiscoveredWallets([]); setAccounts([]); - // Reset to discovering phase so user can reconnect - if (status === 'connecting_wallet') { + if (status === 'connecting') { setConnectionPhase('discovering'); setAccountsError('Wallet disconnected. Please reconnect.'); } }); - return unsubscribe; }, [onWalletDisconnect, status]); - // Start wallet discovery when modal opens and status is connecting_wallet + // Start wallet discovery when modal opens and status is connecting useEffect(() => { - async function startWalletDiscovery() { - if (!open || status !== 'connecting_wallet') return; + if (!open || status !== 'connecting') return; - // Reset state when entering connecting_wallet phase - setConnectionPhase('discovering'); - setDiscoveredWallets([]); - setSelectedWallet(null); - setAccounts([]); - setAccountsError(null); - setIsLoadingAccounts(true); - setNeedsRediscovery(false); - - try { - const wallets = await discoverWallets(); + setConnectionPhase('discovering'); + setDiscoveredWallets([]); + setSelectedWallet(null); + setPendingConnection(null); + setAccounts([]); + setAccountsError(null); + setNeedsRediscovery(false); + setCancelledWalletIds(new Set()); - if (wallets.length === 0) { - throw new Error('No wallets found'); - } + const discovery = discoverWallets(); - setDiscoveredWallets(wallets); - setConnectionPhase('verifying'); - setIsLoadingAccounts(false); - } catch (err) { - setAccountsError(err instanceof Error ? err.message : 'Failed to discover wallets'); - setIsLoadingAccounts(false); + (async () => { + let foundAny = false; + for await (const wallet of discovery.wallets) { + foundAny = true; + setConnectionPhase('selecting_wallet'); + setDiscoveredWallets(prev => [...prev, wallet]); } - } + if (!foundAny) { + setAccountsError('No wallets found. Make sure your wallet extension is installed.'); + } + })(); - startWalletDiscovery(); + return () => { + discovery.cancel(); + }; }, [open, status, discoverWallets]); - // Handle manual re-discovery (e.g., after disconnect or user request) + // Handle manual re-discovery const handleRediscover = async () => { + if (pendingConnection) { + cancelConnection(pendingConnection); + } + setConnectionPhase('discovering'); setDiscoveredWallets([]); setSelectedWallet(null); + setPendingConnection(null); setAccounts([]); setAccountsError(null); - setIsLoadingAccounts(true); setNeedsRediscovery(false); + setCancelledWalletIds(new Set()); + + const discovery = discoverWallets(); + let foundAny = false; + for await (const wallet of discovery.wallets) { + foundAny = true; + setConnectionPhase('selecting_wallet'); + setDiscoveredWallets(prev => [...prev, wallet]); + } - try { - const wallets = await discoverWallets(); - - if (wallets.length === 0) { - throw new Error('No wallets found.'); - } + if (!foundAny) { + setAccountsError('No wallets found. Make sure your wallet extension is installed.'); + } + }; - setDiscoveredWallets(wallets); + // Handle wallet selection + const handleWalletSelect = async (provider: WalletProvider) => { + try { + setSelectedWallet(provider); setConnectionPhase('verifying'); - setIsLoadingAccounts(false); + setAccountsError(null); + + const pending = await initiateConnection(provider); + setPendingConnection(pending); } catch (err) { - setAccountsError(err instanceof Error ? err.message : 'Failed to discover wallets'); - setIsLoadingAccounts(false); + setAccountsError(err instanceof Error ? err.message : 'Failed to initiate connection'); + setConnectionPhase('selecting_wallet'); + setSelectedWallet(null); + setPendingConnection(null); } }; - // Handle wallet selection after user verifies emoji - const handleWalletSelect = async (walletWithEmoji: DiscoveredWalletWithEmoji) => { + // Handle emoji verification confirmation + const handleConfirmConnection = async () => { + if (!selectedWallet || !pendingConnection) return; + try { - setSelectedWallet(walletWithEmoji); setConnectionPhase('connecting'); setIsLoadingAccounts(true); - setAccountsError(null); - const wallet = await connectToProvider(walletWithEmoji.provider); + const wallet = await confirmConnection(selectedWallet, pendingConnection); + + // Request capabilities with full manifest (includes account selection) + const manifest = createGregoSwapCapabilities(activeNetwork); + const capabilitiesResponse = await wallet.requestCapabilities(manifest); + + // Check if simulation capabilities were granted (affects step labels) + const simulationCapability = capabilitiesResponse.granted.find(cap => cap.type === 'simulation'); + setSimulationGrant(!!simulationCapability); - // Get accounts from wallet - const walletAccounts = await wallet.getAccounts(); + // Extract granted accounts from capability response + const accountsCapability = capabilitiesResponse.granted.find(cap => cap.type === 'accounts') as + | (typeof capabilitiesResponse.granted[0] & { accounts?: Aliased[] }) + | undefined; - if (!walletAccounts || walletAccounts.length === 0) { - throw new Error('No accounts found in wallet. Please create an account in your Aztec wallet.'); + if (!accountsCapability || !accountsCapability.accounts || accountsCapability.accounts.length === 0) { + throw new Error('No accounts were granted. Please select at least one account in your wallet.'); } + // Accounts are already in Aliased format from wallet response + const walletAccounts: Aliased[] = accountsCapability.accounts; + setAccounts(walletAccounts); setConnectionPhase('selecting_account'); setIsLoadingAccounts(false); + setPendingConnection(null); } catch (err) { setAccountsError(err instanceof Error ? err.message : 'Failed to connect to wallet'); - setConnectionPhase('verifying'); // Go back to wallet selection on error + setConnectionPhase('selecting_wallet'); setSelectedWallet(null); + setPendingConnection(null); setIsLoadingAccounts(false); } }; + // Handle emoji verification cancellation + const handleCancelConnection = () => { + if (pendingConnection) { + cancelConnection(pendingConnection); + } + if (selectedWallet) { + setCancelledWalletIds(prev => new Set(prev).add(selectedWallet.id)); + } + setPendingConnection(null); + setSelectedWallet(null); + setConnectionPhase('selecting_wallet'); + }; + // Handle completion animation and auto-close useEffect(() => { - // Only show transition animation if there's a pending action (swap or drip) - const hasPendingAction = isSwapPending || isDripPending; - - if (status === 'completed' && hasPendingAction) { - // Show completion check immediately + if (status === 'completed' && isSwapPending) { setShowCompletionCheck(true); - // Show action icon after 800ms (swap or drip icon based on flow) const iconTimer = setTimeout(() => { setShowSwapIcon(true); }, 800); - // Close modal 2 seconds after completion (transaction continues in background) const closeTimer = setTimeout(() => { closeModal(); }, 2000); @@ -205,46 +234,19 @@ export function OnboardingModal({ open, onAccountSelect }: OnboardingModalProps) clearTimeout(iconTimer); clearTimeout(closeTimer); }; - } else if (status === 'completed' && !hasPendingAction) { - // No pending action - close modal immediately (wallet connection only) + } else if (status === 'completed' && !isSwapPending) { closeModal(); } else { - // Reset animation state when not showing completion setShowCompletionCheck(false); setShowSwapIcon(false); } - }, [status, closeModal, isSwapPending, isDripPending]); - - const getStepStatus = (stepIndex: number): 'completed' | 'active' | 'pending' | 'error' => { - // If there's an error, mark the current step as error - if (status === 'error' && stepIndex === currentStep) return 'error'; - if (stepIndex < currentStep) return 'completed'; - if (stepIndex === currentStep) return 'active'; - return 'pending'; - }; - - const handleAccountSelect = (address: AztecAddress) => { - onAccountSelect(address); - }; - - const handlePasswordSubmit = async () => { - if (!password) return; - // Complete onboarding with password, which will trigger drip execution in SwapContainer - await completeDripOnboarding(password); - setPassword(''); - }; - - const isLoading = status !== 'not_started' && status !== 'completed' && status !== 'error'; - const progress = (currentStep / totalSteps) * 100; - - // Show wallet verification UI when in verifying phase - const showWalletVerification = - status === 'connecting_wallet' && connectionPhase === 'verifying' && discoveredWallets.length > 0; - // Show account selection UI when in selecting_account phase - const showAccountSelection = - status === 'connecting_wallet' && connectionPhase === 'selecting_account' && accounts.length > 0; + }, [status, closeModal, isSwapPending]); - // Show completion transition instead of steps when completed + // Computed display states + const showWalletSelection = + status === 'connecting' && connectionPhase === 'selecting_wallet' && discoveredWallets.length > 0; + const showEmojiVerification = status === 'connecting' && connectionPhase === 'verifying' && pendingConnection !== null; + const showAccountSelection = status === 'connecting' && connectionPhase === 'selecting_account' && accounts.length > 0; const showCompletionTransition = status === 'completed'; return ( @@ -278,106 +280,22 @@ export function OnboardingModal({ open, onAccountSelect }: OnboardingModalProps) - {/* Show completion transition or normal progress */} {showCompletionTransition ? ( - // Completion Transition Animation - - {/* Success Checkmark */} - - - - - Wallet Configured! - - - - - {/* Action Icon and Message */} - - - {flowType === 'drip' ? ( - - ) : ( - - )} - - {flowType === 'drip' ? 'Claiming GregoCoin...' : 'Executing swap...'} - - - - + ) : ( <> - {/* Progress Bar */} - - - - Step {currentStep} of {totalSteps} - - - {Math.round(progress)}% - - - - + {/* Progress Bar and Steps */} + {/* Error Display */} {(error || accountsError) && ( @@ -390,13 +308,9 @@ export function OnboardingModal({ open, onAccountSelect }: OnboardingModalProps) Reconnect ) : ( - + ) } > @@ -404,424 +318,57 @@ export function OnboardingModal({ open, onAccountSelect }: OnboardingModalProps) )} - {/* Steps List - Show only first step during connecting_wallet phase */} - - {steps.map((step, index) => { - const stepNum = index + 1; - const stepStatus = getStepStatus(stepNum); - const isActive = stepStatus === 'active'; - const isCompleted = stepStatus === 'completed'; - const isError = stepStatus === 'error'; - - // First step always visible - if (index === 0) { - return ( - - - {isError ? ( - - ) : isCompleted ? ( - - ) : isActive && isLoading ? ( - - ) : ( - - )} - - - {step.label} - - } - secondary={ - - {step.description} - - } - /> - - ); - } - - // Remaining steps - animate with Collapse - return ( - - - - {isError ? ( - - ) : isCompleted ? ( - - ) : isActive && isLoading ? ( - - ) : ( - - )} - - - {step.label} - - } - secondary={ - - {step.description} - - } - /> - - - ); - })} - - - {/* Wallet discovery, verification, and account selection below first step */} - + {/* Wallet Connection Flow */} + {isLoadingAccounts && connectionPhase === 'discovering' ? ( - // Discovering wallets - - - Discovering wallets... - - + ) : isLoadingAccounts && connectionPhase === 'connecting' && selectedWallet ? ( - // Connecting to selected wallet - show wallet info with emoji while loading - <> - - {selectedWallet.provider.icon ? ( - - ) : ( - - - - )} - - - {selectedWallet.provider.name} - - {selectedWallet.verificationEmoji && ( - - {selectedWallet.verificationEmoji} - - )} - - - - - - - - - Security Verification - - - - Verify the emoji code matches what your wallet is showing. - - - - - Connecting and retrieving accounts... - - - Please approve the request in your wallet - - - ) : showWalletVerification ? ( - // Wallet selection step - emojis hidden until user clicks - <> - - - Select your wallet to connect: - - - - - - - - - {discoveredWallets.map(walletWithEmoji => { - const { provider } = walletWithEmoji; - - return ( - - handleWalletSelect(walletWithEmoji)} - sx={{ - border: '1px solid', - borderColor: 'divider', - borderRadius: 1, - '&:hover': { - borderColor: 'primary.main', - backgroundColor: 'rgba(212, 255, 40, 0.05)', - }, - }} - > - - {provider.icon ? ( - - ) : ( - - - - )} - - - {provider.name} - - } - /> - - - ); - })} - - - + + ) : showWalletSelection ? ( + + ) : showEmojiVerification && selectedWallet && pendingConnection ? ( + ) : showAccountSelection ? ( - // Account selection (after wallet connected) - <> - - Select an account to continue: - - - - {accounts.map((account, index) => { - const alias = account.alias || `Account ${index + 1}`; - const addressStr = account.item.toString(); - - return ( - - handleAccountSelect(account.item)} - sx={{ - border: '1px solid', - borderColor: 'divider', - borderRadius: 1, - '&:hover': { - borderColor: 'primary.main', - backgroundColor: 'rgba(212, 255, 40, 0.05)', - }, - }} - > - - {alias} - - } - secondary={ - - {addressStr} - - } - /> - - - ); - })} - - - + ) : null} - {/* Swap flow: show approval message */} - {status === 'simulating_queries' && flowType === 'swap' && ( - - - Please approve the batched queries in your wallet. This is a one-time setup that enables seamless - interactions going forward. - - - )} + {/* Flow-specific Messages */} + - {/* Drip flow: show info message during registration */} - {status === 'registering_drip' && flowType === 'drip' && ( - - - - Uh oh! You have no GregoCoin balance! - - - Next steps: -
    -
  1. Approve the registration of ProofOfPassword contract in your wallet
  2. -
  3. Provide the password to claim your tokens
  4. -
  5. Authorize the transaction
  6. -
-
-
-
- )} + {/* Drip Password Input (shown when balance is 0) */} + + {status === 'awaiting_drip' && } + - {/* Drip flow: show password input - only when awaiting password, not during registration */} - - {status === 'awaiting_drip' && flowType === 'drip' && ( - - - Enter the password to claim your free GregoCoin tokens: - - - setPassword(e.target.value)} - autoFocus + {/* Drip Error Display (shown when drip fails during execution) */} + + {status === 'executing_drip' && dripPhase === 'error' && ( + + { - if (e.key === 'Enter' && password) { - handlePasswordSubmit(); - } - }} - /> - - + } > - Continue - + {dripError || 'Failed to claim tokens. Please try again.'} + + )} diff --git a/src/components/onboarding/AccountSelection.tsx b/src/components/onboarding/AccountSelection.tsx new file mode 100644 index 0000000..a304b62 --- /dev/null +++ b/src/components/onboarding/AccountSelection.tsx @@ -0,0 +1,71 @@ +/** + * AccountSelection Component + * Displays list of accounts for user selection + */ + +import { Box, Typography, List, ListItem, ListItemButton, ListItemText } from '@mui/material'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; + +interface AccountItem { + item: AztecAddress; + alias: string; +} + +interface AccountSelectionProps { + accounts: AccountItem[]; + onSelect: (address: AztecAddress) => void; +} + +export function AccountSelection({ accounts, onSelect }: AccountSelectionProps) { + return ( + <> + + Select an account to continue: + + + + {accounts.map((account, index) => { + const alias = account.alias || `Account ${index + 1}`; + const addressStr = account.item.toString(); + + return ( + + onSelect(account.item)} + sx={{ + border: '1px solid', + borderColor: 'divider', + borderRadius: 1, + '&:hover': { + borderColor: 'primary.main', + backgroundColor: 'rgba(212, 255, 40, 0.05)', + }, + }} + > + + {alias} + + } + secondary={ + + {addressStr} + + } + /> + + + ); + })} + + + + ); +} diff --git a/src/components/onboarding/CompletionTransition.tsx b/src/components/onboarding/CompletionTransition.tsx new file mode 100644 index 0000000..e428b27 --- /dev/null +++ b/src/components/onboarding/CompletionTransition.tsx @@ -0,0 +1,76 @@ +/** + * CompletionTransition Component + * Shows success animation when onboarding completes + */ + +import { Box, Typography, Fade } from '@mui/material'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import SwapHorizIcon from '@mui/icons-material/SwapHoriz'; + +interface CompletionTransitionProps { + showCheck: boolean; + showActionIcon: boolean; + hasPendingSwap: boolean; +} + +export function CompletionTransition({ showCheck, showActionIcon, hasPendingSwap }: CompletionTransitionProps) { + const pulseAnimation = { + animation: 'pulse 1s ease-in-out infinite', + '@keyframes pulse': { + '0%, 100%': { + opacity: 1, + transform: 'scale(1)', + }, + '50%': { + opacity: 0.7, + transform: 'scale(1.1)', + }, + }, + }; + + return ( + + {/* Success Checkmark */} + + + + + Wallet Configured! + + + + + {/* Action Icon and Message - only show if swap is pending */} + {hasPendingSwap && ( + + + + + Executing swap... + + + + )} + + ); +} diff --git a/src/components/onboarding/ConnectingWallet.tsx b/src/components/onboarding/ConnectingWallet.tsx new file mode 100644 index 0000000..785ecf2 --- /dev/null +++ b/src/components/onboarding/ConnectingWallet.tsx @@ -0,0 +1,96 @@ +/** + * ConnectingWallet Component + * Shows wallet info with emoji while connection is being established + */ + +import { Box, Typography, CircularProgress } from '@mui/material'; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; +import SecurityIcon from '@mui/icons-material/Security'; +import type { WalletProvider } from '@aztec/wallet-sdk/manager'; +import { hashToEmoji } from '@aztec/wallet-sdk/crypto'; + +interface ConnectingWalletProps { + wallet: WalletProvider; +} + +/** Computes verification emoji from provider metadata */ +function getVerificationEmoji(provider: WalletProvider): string { + return provider.metadata?.verificationHash ? hashToEmoji(provider.metadata.verificationHash as string) : ''; +} + +export function ConnectingWallet({ wallet }: ConnectingWalletProps) { + return ( + <> + + {wallet.icon ? ( + + ) : ( + + + + )} + + + {wallet.name} + + {getVerificationEmoji(wallet) && ( + + {getVerificationEmoji(wallet)} + + )} + + + + + + + + + Security Verification + + + + Verify the emoji code matches what your wallet is showing. + + + + + Connecting and retrieving accounts... + + + Please approve the request in your wallet + + + ); +} diff --git a/src/components/onboarding/DripPasswordInput.tsx b/src/components/onboarding/DripPasswordInput.tsx new file mode 100644 index 0000000..fb292a1 --- /dev/null +++ b/src/components/onboarding/DripPasswordInput.tsx @@ -0,0 +1,66 @@ +/** + * DripPasswordInput Component + * Password input form for claiming GregoCoin tokens + */ + +import { useState } from 'react'; +import { Box, Typography, TextField, Button } from '@mui/material'; +import WaterDropIcon from '@mui/icons-material/WaterDrop'; + +interface DripPasswordInputProps { + onSubmit: (password: string) => void; +} + +export function DripPasswordInput({ onSubmit }: DripPasswordInputProps) { + const [password, setPassword] = useState(''); + + const handleSubmit = () => { + if (password) { + onSubmit(password); + setPassword(''); + } + }; + + return ( + + + Enter the password to claim your free GregoCoin tokens: + + + setPassword(e.target.value)} + autoFocus + sx={{ mb: 2 }} + onKeyDown={e => { + if (e.key === 'Enter' && password) { + handleSubmit(); + } + }} + /> + + + + ); +} diff --git a/src/components/onboarding/EmojiGrid.tsx b/src/components/onboarding/EmojiGrid.tsx new file mode 100644 index 0000000..5369671 --- /dev/null +++ b/src/components/onboarding/EmojiGrid.tsx @@ -0,0 +1,41 @@ +/** + * EmojiGrid Component + * Renders a 3x3 emoji grid for wallet verification display + */ + +import { Box } from '@mui/material'; + +interface EmojiGridProps { + emojis: string; + size?: 'small' | 'medium' | 'large'; +} + +export function EmojiGrid({ emojis, size = 'medium' }: EmojiGridProps) { + const emojiArray = [...emojis]; + const rows = [emojiArray.slice(0, 3), emojiArray.slice(3, 6), emojiArray.slice(6, 9)]; + const fontSize = size === 'small' ? '0.9rem' : size === 'large' ? '1.8rem' : '1.4rem'; + + return ( + + {rows.map((row, i) => ( + + {row.map((emoji, j) => ( + + {emoji} + + ))} + + ))} + + ); +} diff --git a/src/components/onboarding/EmojiVerification.tsx b/src/components/onboarding/EmojiVerification.tsx new file mode 100644 index 0000000..ffcd78e --- /dev/null +++ b/src/components/onboarding/EmojiVerification.tsx @@ -0,0 +1,102 @@ +/** + * EmojiVerification Component + * Shows emoji verification UI for wallet connection + */ + +import { Box, Typography, Button } from '@mui/material'; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; +import SecurityIcon from '@mui/icons-material/Security'; +import type { WalletProvider, PendingConnection } from '@aztec/wallet-sdk/manager'; +import { hashToEmoji } from '@aztec/wallet-sdk/crypto'; +import { EmojiGrid } from './EmojiGrid'; + +interface EmojiVerificationProps { + wallet: WalletProvider; + pendingConnection: PendingConnection; + onConfirm: () => void; + onCancel: () => void; +} + +export function EmojiVerification({ wallet, pendingConnection, onConfirm, onCancel }: EmojiVerificationProps) { + return ( + <> + + + {wallet.icon ? ( + + ) : ( + + + + )} + + {wallet.name} + + + + {/* Verification emoji display */} + + + + + + + + + + Security Verification + + + + Verify the emoji code above matches what your wallet is showing. If they don't match, click "Cancel" - someone + may be trying to intercept your connection. + + + + + + + + + ); +} diff --git a/src/components/onboarding/FlowMessages.tsx b/src/components/onboarding/FlowMessages.tsx new file mode 100644 index 0000000..58ae51a --- /dev/null +++ b/src/components/onboarding/FlowMessages.tsx @@ -0,0 +1,59 @@ +/** + * FlowMessages Component + * Shows context-specific messages during onboarding + */ + +import { Box, Typography, Alert } from '@mui/material'; +import type { OnboardingStatus } from '../../contexts/onboarding'; + +interface FlowMessagesProps { + status: OnboardingStatus; + hasSimulationGrant?: boolean; +} + +export function FlowMessages({ status, hasSimulationGrant }: FlowMessagesProps) { + // Show message during simulation - different text based on whether grant was given + if (status === 'simulating') { + return ( + + + {hasSimulationGrant + ? 'Fetching your token balances...' + : 'Please approve the batched queries in your wallet. This is a one-time setup that enables seamless interactions going forward.'} + + + ); + } + + // Show info message during drip registration (when balance is 0) + if (status === 'registering_drip') { + return ( + + + + Uh oh! You have no GregoCoin balance! + + + Next steps: +
    +
  1. Approve the registration of ProofOfPassword contract in your wallet
  2. +
  3. Provide the password to claim your tokens
  4. +
  5. Authorize the transaction
  6. +
+
+
+
+ ); + } + + return null; +} diff --git a/src/components/onboarding/OnboardingProgress.tsx b/src/components/onboarding/OnboardingProgress.tsx new file mode 100644 index 0000000..8c54adc --- /dev/null +++ b/src/components/onboarding/OnboardingProgress.tsx @@ -0,0 +1,139 @@ +/** + * OnboardingProgress Component + * Displays the progress bar and step list for onboarding + */ + +import { + Box, + Typography, + LinearProgress, + List, + ListItem, + ListItemIcon, + ListItemText, + CircularProgress, + Collapse, +} from '@mui/material'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked'; +import ErrorIcon from '@mui/icons-material/Error'; +import type { OnboardingStep, OnboardingStatus } from '../../contexts/onboarding'; + +interface OnboardingProgressProps { + currentStep: number; + totalSteps: number; + steps: OnboardingStep[]; + status: OnboardingStatus; + isLoading: boolean; +} + +export function OnboardingProgress({ + currentStep, + totalSteps, + steps, + status, + isLoading, +}: OnboardingProgressProps) { + const progress = (currentStep / totalSteps) * 100; + + const getStepStatus = (stepIndex: number): 'completed' | 'active' | 'pending' | 'error' => { + if (status === 'error' && stepIndex === currentStep) return 'error'; + if (stepIndex < currentStep) return 'completed'; + if (stepIndex === currentStep) return 'active'; + return 'pending'; + }; + + return ( + <> + {/* Progress Bar */} + + + + Step {currentStep} of {totalSteps} + + + {Math.round(progress)}% + + + + + + {/* Steps List */} + + {steps.map((step, index) => { + const stepNum = index + 1; + const stepStatus = getStepStatus(stepNum); + const isActive = stepStatus === 'active'; + const isCompleted = stepStatus === 'completed'; + const isError = stepStatus === 'error'; + + // First step always visible, remaining steps animate in + const shouldAnimate = index > 0; + + const stepContent = ( + + + {isError ? ( + + ) : isCompleted ? ( + + ) : isActive && isLoading ? ( + + ) : ( + + )} + + + {step.label} + + } + secondary={ + + {step.description} + + } + /> + + ); + + if (shouldAnimate) { + return ( + + {stepContent} + + ); + } + + return {stepContent}; + })} + + + ); +} diff --git a/src/components/onboarding/WalletDiscovery.tsx b/src/components/onboarding/WalletDiscovery.tsx new file mode 100644 index 0000000..a374a3e --- /dev/null +++ b/src/components/onboarding/WalletDiscovery.tsx @@ -0,0 +1,25 @@ +/** + * WalletDiscovery Component + * Shows discovery animation while searching for wallets + */ + +import { Box, Typography } from '@mui/material'; + +export function WalletDiscovery() { + return ( + + + Discovering wallets... + + + ); +} diff --git a/src/components/onboarding/WalletSelection.tsx b/src/components/onboarding/WalletSelection.tsx new file mode 100644 index 0000000..2fa232b --- /dev/null +++ b/src/components/onboarding/WalletSelection.tsx @@ -0,0 +1,110 @@ +/** + * WalletSelection Component + * Displays list of discovered wallets for user selection + */ + +import { Box, Typography, List, ListItem, ListItemButton, ListItemIcon, ListItemText, IconButton } from '@mui/material'; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import type { WalletProvider } from '@aztec/wallet-sdk/manager'; + +interface WalletSelectionProps { + wallets: WalletProvider[]; + cancelledWalletIds: Set; + onSelect: (wallet: WalletProvider) => void; + onRefresh: () => void; +} + +export function WalletSelection({ wallets, cancelledWalletIds, onSelect, onRefresh }: WalletSelectionProps) { + return ( + <> + + + Select your wallet to connect: + + + + + + + + + {wallets.map(provider => { + const isCancelled = cancelledWalletIds.has(provider.id); + return ( + + onSelect(provider)} + disabled={isCancelled} + sx={{ + border: '1px solid', + borderColor: 'divider', + borderRadius: 1, + opacity: isCancelled ? 0.5 : 1, + '&:hover': { + borderColor: isCancelled ? 'divider' : 'primary.main', + backgroundColor: isCancelled ? 'transparent' : 'rgba(212, 255, 40, 0.05)', + }, + '&.Mui-disabled': { + opacity: 0.5, + }, + }} + > + + {provider.icon ? ( + + ) : ( + + + + )} + + + {provider.name} + + } + secondary={ + isCancelled ? ( + + Connection cancelled - refresh to retry + + ) : undefined + } + /> + + + ); + })} + + + + ); +} diff --git a/src/components/onboarding/index.ts b/src/components/onboarding/index.ts new file mode 100644 index 0000000..6764b2f --- /dev/null +++ b/src/components/onboarding/index.ts @@ -0,0 +1,14 @@ +/** + * Onboarding Components Index + * Re-exports all onboarding subcomponents + */ + +export { OnboardingProgress } from './OnboardingProgress'; +export { WalletDiscovery } from './WalletDiscovery'; +export { WalletSelection } from './WalletSelection'; +export { EmojiVerification } from './EmojiVerification'; +export { AccountSelection } from './AccountSelection'; +export { ConnectingWallet } from './ConnectingWallet'; +export { DripPasswordInput } from './DripPasswordInput'; +export { CompletionTransition } from './CompletionTransition'; +export { FlowMessages } from './FlowMessages'; diff --git a/src/components/swap/DripProgress.tsx b/src/components/swap/DripProgress.tsx deleted file mode 100644 index 12e4bc9..0000000 --- a/src/components/swap/DripProgress.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { Box, Typography, keyframes } from '@mui/material'; -import WaterDropIcon from '@mui/icons-material/WaterDrop'; - -const pulse = keyframes` - 0%, 100% { - opacity: 0.4; - } - 50% { - opacity: 1; - } -`; - -const shimmer = keyframes` - 0% { - background-position: -200% center; - } - 100% { - background-position: 200% center; - } -`; - -const drip = keyframes` - 0% { - transform: translateY(-10px); - opacity: 0; - } - 50% { - opacity: 1; - } - 100% { - transform: translateY(10px); - opacity: 0; - } -`; - -type DripPhase = 'sending' | 'mining'; - -interface DripProgressProps { - phase?: DripPhase; -} - -export function DripProgress({ phase = 'sending' }: DripProgressProps) { - const statusText = phase === 'sending' ? 'Proving & sending transaction' : 'Mining transaction'; - const statusDetail = phase === 'sending' ? 'Claiming your GregoCoin...' : 'Waiting for confirmation...'; - - return ( - - {/* Animated water drop icon */} - - - - - {/* Status text */} - - - - {statusText} - - - {/* Loading dots */} - - {[0, 1, 2].map(i => ( - - ))} - - - - {/* Detail text */} - - {statusDetail} - - - - ); -} diff --git a/src/components/swap/ExchangeRateDisplay.tsx b/src/components/swap/ExchangeRateDisplay.tsx index 4d3e991..54f112f 100644 --- a/src/components/swap/ExchangeRateDisplay.tsx +++ b/src/components/swap/ExchangeRateDisplay.tsx @@ -1,15 +1,11 @@ import { Box, Typography, CircularProgress } from '@mui/material'; -import { useContracts } from '../../contexts/ContractsContext'; interface ExchangeRateDisplayProps { - exchangeRate: number | undefined; + exchangeRate: number | null; isLoadingRate: boolean; } export function ExchangeRateDisplay({ exchangeRate, isLoadingRate }: ExchangeRateDisplayProps) { - const { isLoadingContracts } = useContracts(); - - const isLoading = isLoadingContracts || isLoadingRate; return ( Exchange Rate: - {isLoading || exchangeRate === undefined ? ( + {isLoadingRate || exchangeRate === null ? ( diff --git a/src/components/swap/SwapButton.tsx b/src/components/swap/SwapButton.tsx index aaf536a..b2d856f 100644 --- a/src/components/swap/SwapButton.tsx +++ b/src/components/swap/SwapButton.tsx @@ -3,12 +3,11 @@ import { Button } from '@mui/material'; interface SwapButtonProps { onClick: () => void; disabled: boolean; - loading: boolean; contractsLoading: boolean; hasAmount: boolean; } -export function SwapButton({ onClick, disabled, loading, contractsLoading, hasAmount }: SwapButtonProps) { +export function SwapButton({ onClick, disabled, contractsLoading, hasAmount }: SwapButtonProps) { const getButtonText = () => { if (contractsLoading) { return 'Loading contracts...'; @@ -24,7 +23,7 @@ export function SwapButton({ onClick, disabled, loading, contractsLoading, hasAm fullWidth variant="contained" size="large" - disabled={disabled || loading} + disabled={disabled} onClick={onClick} sx={{ mt: 3, diff --git a/src/components/swap/SwapContainer.tsx b/src/components/swap/SwapContainer.tsx index 8b60fe5..f6765eb 100644 --- a/src/components/swap/SwapContainer.tsx +++ b/src/components/swap/SwapContainer.tsx @@ -1,225 +1,94 @@ -import { useState, useRef, useEffect } from 'react'; -import { Paper, Box, Button, Typography } from '@mui/material'; +/** + * SwapContainer Component + * Main swap interface using contexts + */ + +import { useEffect, useRef, useState, useCallback } from 'react'; +import { Paper, Box } from '@mui/material'; import SwapVertIcon from '@mui/icons-material/SwapVert'; -import WaterDropIcon from '@mui/icons-material/WaterDrop'; import { SwapBox } from './SwapBox'; import { SwapProgress } from './SwapProgress'; -import { DripProgress } from './DripProgress'; import { ExchangeRateDisplay } from './ExchangeRateDisplay'; import { SwapButton } from './SwapButton'; import { SwapErrorAlert } from './SwapErrorAlert'; -import { DripModal } from '../DripModal'; -import { useContracts } from '../../contexts/ContractsContext'; -import { useWallet } from '../../contexts/WalletContext'; -import { useOnboarding } from '../../contexts/OnboardingContext'; -import { useSwap } from '../../hooks/useSwap'; -import { useBalances } from '../../hooks/useBalances'; -import { waitForTxWithPhases } from '../../utils/txUtils'; +import { useContracts } from '../../contexts/contracts'; +import { useWallet } from '../../contexts/wallet'; +import { useOnboarding } from '../../contexts/onboarding'; +import { useSwap } from '../../contexts/swap'; +import type { Balances } from '../../types'; export function SwapContainer() { - const { isLoadingContracts, drip } = useContracts(); + const { isLoadingContracts, fetchBalances } = useContracts(); const { isUsingEmbeddedWallet, currentAddress } = useWallet(); const { status: onboardingStatus, - isSwapPending, - isDripPending, - dripPassword, - clearSwapPending, - clearDripPassword, - completeDripExecution, - startOnboardingFlow, + startOnboarding, + isDripping, + dripError, + dismissDripError, } = useOnboarding(); - const swapErrorRef = useRef(null); - - // Get balances using the hook - const { balances, isLoading: isLoadingBalances, refetch: refetchBalances } = useBalances(); - - // State for amounts - const [fromAmount, setFromAmount] = useState(''); - const [toAmount, setToAmount] = useState(''); - - // State for drip modal (for users already onboarded) - const [isDripModalOpen, setIsDripModalOpen] = useState(false); - - // State for drip execution (after onboarding) - const [isDripping, setIsDripping] = useState(false); - const [dripPhase, setDripPhase] = useState<'sending' | 'mining' | null>(null); - const [dripError, setDripError] = useState(null); - - // Use swap hook for calculations, validation, swap logic, and exchange rate const { + fromAmount, + toAmount, exchangeRate, isLoadingRate, fromAmountUSD, toAmountUSD, canSwap, isSwapping, - swapPhase, - swapError, + phase: swapPhase, + error: swapError, + setFromAmount, + setToAmount, executeSwap, - dismissError, - } = useSwap({ - fromAmount, - toAmount, - isDripping, - fromTokenBalance: balances.gregoCoin, - }); + dismissError: dismissSwapError, + } = useSwap(); - // Recalculate amounts when exchange rate becomes available - const prevExchangeRateRef = useRef(exchangeRate); - useEffect(() => { - const wasUnavailable = prevExchangeRateRef.current === undefined; - const isNowAvailable = exchangeRate !== undefined; + // Local balance state + const [balances, setBalances] = useState({ gregoCoin: null, gregoCoinPremium: null }); + const [isLoadingBalances, setIsLoadingBalances] = useState(false); - // If rate just became available, recalculate the empty field - if (wasUnavailable && isNowAvailable) { - if (fromAmount !== '' && toAmount === '') { - // Recalculate To amount from From amount - const numValue = parseFloat(fromAmount); - if (!isNaN(numValue)) { - setToAmount((numValue * exchangeRate).toFixed(6)); - } - } else if (toAmount !== '' && fromAmount === '') { - // Recalculate From amount from To amount - const numValue = parseFloat(toAmount); - if (!isNaN(numValue)) { - setFromAmount((numValue / exchangeRate).toFixed(6)); - } - } - } - - prevExchangeRateRef.current = exchangeRate; - }, [exchangeRate, fromAmount, toAmount]); - - // Track if a swap was actually in progress (to distinguish from initial mount) - const wasSwappingRef = useRef(false); - useEffect(() => { - if (isSwapping) { - wasSwappingRef.current = true; - } - }, [isSwapping]); - - useEffect(() => { - // If swap just completed successfully (was swapping, now not swapping, no error) - if (wasSwappingRef.current && !isSwapping && !swapError) { - wasSwappingRef.current = false; - setFromAmount(''); - setToAmount(''); - // Refresh balances after successful swap - refetchBalances(); - } - }, [isSwapping, swapError, refetchBalances]); + const swapErrorRef = useRef(null); - // Handle amount changes with recalculation - const handleFromChange = (value: string) => { - setFromAmount(value); - if (value === '' || exchangeRate === undefined) { - setToAmount(''); - } else { - const numValue = parseFloat(value); - if (!isNaN(numValue)) { - setToAmount((numValue * exchangeRate).toFixed(6)); - } + // Fetch balances + const refetchBalances = useCallback(async () => { + if (isUsingEmbeddedWallet || !currentAddress) { + setBalances({ gregoCoin: null, gregoCoinPremium: null }); + return; } - }; - const handleToChange = (value: string) => { - setToAmount(value); - if (value === '' || exchangeRate === undefined) { - setFromAmount(''); - } else { - const numValue = parseFloat(value); - if (!isNaN(numValue)) { - setFromAmount((numValue / exchangeRate).toFixed(6)); - } + setIsLoadingBalances(true); + try { + const [gcBalance, gcpBalance] = await fetchBalances(); + setBalances({ gregoCoin: gcBalance, gregoCoinPremium: gcpBalance }); + } catch { + setBalances({ gregoCoin: null, gregoCoinPremium: null }); + } finally { + setIsLoadingBalances(false); } - }; - - const handleSwapClick = () => { - // Check if user needs onboarding - if (isUsingEmbeddedWallet || onboardingStatus === 'not_started') { - // Start onboarding flow with swap type - user initiated a swap transaction - startOnboardingFlow('swap', true); - } else if (onboardingStatus === 'completed') { - // Already onboarded, execute swap directly - executeSwap(); - } - }; - - // Track if swap was triggered after onboarding - const swapTriggeredAfterOnboardingRef = useRef(false); + }, [fetchBalances, currentAddress, isUsingEmbeddedWallet]); + // Clear balances when switching to embedded wallet or losing address useEffect(() => { - if (onboardingStatus === 'completed' && isSwapPending) { - executeSwap(); - swapTriggeredAfterOnboardingRef.current = true; + if (isUsingEmbeddedWallet || !currentAddress) { + setBalances({ gregoCoin: null, gregoCoinPremium: null }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [onboardingStatus, isSwapPending]); + }, [isUsingEmbeddedWallet, currentAddress]); - // Clear swap pending flag only after swap actually completes - // (not just when onboarding completes but before swap starts) + // Refetch balances when onboarding completes useEffect(() => { - if (swapTriggeredAfterOnboardingRef.current && isSwapPending && !isSwapping) { - swapTriggeredAfterOnboardingRef.current = false; - clearSwapPending(); + if (onboardingStatus === 'completed') { + refetchBalances(); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isSwapPending, isSwapping]); + }, [onboardingStatus, refetchBalances]); - // Execute drip after onboarding completes with password + // Refetch balances when swap succeeds useEffect(() => { - async function executeDrip() { - if (!isDripPending || !dripPassword || !currentAddress || isDripping) return; - - console.log('Starting drip execution'); - setIsDripping(true); - setDripPhase('sending'); - setDripError(null); - - // Complete onboarding immediately to show transition animation - // Transaction will continue in background - completeDripExecution(); - clearDripPassword(); - - try { - const sentTx = await drip(dripPassword, currentAddress); - await waitForTxWithPhases(sentTx, setDripPhase); - - // Success - refresh balances and clear state - refetchBalances(); - setIsDripping(false); - setDripPhase(null); - } catch (error) { - console.error('Drip error:', error); - // Extract meaningful error message - let errorMessage = 'Failed to claim GregoCoin. Please try again.'; - - if (error instanceof Error) { - // Check for common error patterns - if (error.message.includes('Simulation failed')) { - errorMessage = error.message; - } else if (error.message.includes('User denied') || error.message.includes('rejected')) { - errorMessage = 'Transaction was rejected in wallet'; - } else if (error.message.includes('password') || error.message.includes('Password')) { - errorMessage = 'Invalid password. Please try again.'; - } else if (error.message.includes('already claimed') || error.message.includes('Already claimed')) { - errorMessage = 'You have already claimed your GregoCoin tokens.'; - } else { - errorMessage = error.message; - } - } - - setDripError(errorMessage); - setDripPhase(null); - setIsDripping(false); - } + if (swapPhase === 'success') { + refetchBalances(); } - - executeDrip(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isDripPending, dripPassword, currentAddress, completeDripExecution]); + }, [swapPhase, refetchBalances]); // Scroll to error when it appears useEffect(() => { @@ -230,15 +99,26 @@ export function SwapContainer() { } }, [swapError, dripError]); + const handleSwapClick = () => { + // Check if user needs onboarding + if (isUsingEmbeddedWallet || onboardingStatus === 'idle') { + // Start onboarding - user initiated a swap transaction + startOnboarding(true); + } else if (onboardingStatus === 'completed') { + // Already onboarded, execute swap directly + executeSwap(); + } + }; + const handleMaxFromClick = () => { if (balances.gregoCoin !== null) { - handleFromChange(balances.gregoCoin.toString()); + setFromAmount(balances.gregoCoin.toString()); } }; const handleMaxToClick = () => { if (balances.gregoCoinPremium !== null) { - handleToChange(balances.gregoCoinPremium.toString()); + setToAmount(balances.gregoCoinPremium.toString()); } }; @@ -249,7 +129,7 @@ export function SwapContainer() { const disableToBox = isSwapping; // Show "..." placeholder when rate is unavailable and opposite box has value - const isRateUnavailable = isLoadingRate || exchangeRate === undefined; + const isRateUnavailable = isLoadingRate || exchangeRate === null; const fromPlaceholder = isRateUnavailable && toAmount !== '' ? '...' : '0.0'; const toPlaceholder = isRateUnavailable && fromAmount !== '' ? '...' : '0.0'; @@ -260,6 +140,13 @@ export function SwapContainer() { fromAmount !== '' && parseFloat(fromAmount) > Number(balances.gregoCoin); + // Combined error handling + const displayError = swapError || dripError; + const handleDismissError = () => { + if (dripError) dismissDripError(); + if (swapError) dismissSwapError(); + }; + return ( {/* Swap Button or Progress */} - {isDripping ? ( - - ) : isSwapping ? ( - + {isSwapping ? ( + ) : ( 0} /> )} {/* Error Display */} - { - if (dripError) setDripError(null); - if (swapError) dismissError(); - }} - errorRef={swapErrorRef} - /> - - {/* Drip Modal */} - setIsDripModalOpen(false)} onSuccess={() => refetchBalances()} /> + ); } diff --git a/src/components/swap/SwapProgress.tsx b/src/components/swap/SwapProgress.tsx index 2c193ed..5bed5f2 100644 --- a/src/components/swap/SwapProgress.tsx +++ b/src/components/swap/SwapProgress.tsx @@ -39,15 +39,9 @@ const shimmer = keyframes` } `; -type SwapPhase = 'sending' | 'mining'; - -interface SwapProgressProps { - phase?: SwapPhase; -} - -export function SwapProgress({ phase = 'sending' }: SwapProgressProps) { - const statusText = phase === 'sending' ? 'Proving & sending transaction' : 'Mining transaction'; - const statusDetail = phase === 'sending' ? 'Preparing your swap...' : 'Waiting for confirmation...'; +export function SwapProgress() { + const statusText = 'Swapping'; + const statusDetail = 'Proving & sending transaction...'; return ( Promise; - swap: (amountOut: number, amountInMax: number) => Promise; - fetchBalances: () => Promise<[bigint, bigint]>; - simulateOnboardingQueries: () => Promise<[number, bigint, bigint]>; - registerContractsForFlow: (flowType: 'swap' | 'drip' | 'gregocoin-only') => Promise; - drip: (password: string, recipient: AztecAddress) => Promise; -} - -const ContractsContext = createContext(undefined); - -export function useContracts() { - const context = useContext(ContractsContext); - if (context === undefined) { - throw new Error('useContracts must be used within a ContractsProvider'); - } - return context; -} - -interface ContractsProviderProps { - children: ReactNode; -} - -// Helper function to get SponsoredFPC contract data -async function getSponsoredFPCData() { - const { SponsoredFPCContractArtifact } = await import('@aztec/noir-contracts.js/SponsoredFPC'); - const sponsoredFPCInstance = await getContractInstanceFromInstantiationParams(SponsoredFPCContractArtifact, { - salt: new Fr(SPONSORED_FPC_SALT), - }); - return { artifact: SponsoredFPCContractArtifact, instance: sponsoredFPCInstance }; -} - -export function ContractsProvider({ children }: ContractsProviderProps) { - const { wallet, currentAddress, isLoading: walletLoading, node, isUsingEmbeddedWallet } = useWallet(); - const { activeNetwork } = useNetwork(); - const [gregoCoin, setGregoCoin] = useState(null); - const [gregoCoinPremium, setGregoCoinPremium] = useState(null); - const [amm, setAmm] = useState(null); - const [pop, setPop] = useState(null); - const [isLoadingContracts, setIsLoadingContracts] = useState(true); - - const drip = useCallback( - async (password: string, recipient: AztecAddress) => { - if (!pop) { - throw new Error('ProofOfPassword contract not initialized'); - } - - const { instance: sponsoredFPCInstance } = await getSponsoredFPCData(); - - return pop.methods.check_password_and_mint(password, recipient).send({ - from: AztecAddress.ZERO, - fee: { - paymentMethod: new SponsoredFeePaymentMethod(sponsoredFPCInstance.address), - }, - }); - }, - [wallet, pop], - ); - - const getExchangeRate = useCallback(async () => { - if (!amm) throw new Error('AMM contract not initialized'); - - const batchCall = new BatchCall(wallet, [ - gregoCoin.methods.balance_of_public(amm.address), - gregoCoinPremium.methods.balance_of_public(amm.address), - ]); - const [token0Reserve, token1Reserve] = await batchCall.simulate({ from: currentAddress }); - return parseFloat(new BigDecimal(token1Reserve).divide(new BigDecimal(token0Reserve)).toString()); - }, [amm, wallet, gregoCoin, gregoCoinPremium, currentAddress]); - - const swap = useCallback( - async (amountOut: number, amountInMax: number) => { - if (!wallet || !amm || !currentAddress || !gregoCoin || !gregoCoinPremium) { - throw new Error('Contracts not initialized'); - } - - const authwitNonce = Fr.random(); - return amm.methods - .swap_tokens_for_exact_tokens( - gregoCoin.address, - gregoCoinPremium.address, - BigInt(Math.round(amountOut)), - BigInt(Math.round(amountInMax)), - authwitNonce, - ) - .send({ from: currentAddress }); - }, - [wallet, amm, currentAddress, gregoCoin, gregoCoinPremium], - ); - - const fetchBalances = useCallback(async () => { - if (!wallet || !gregoCoin || !gregoCoinPremium || !currentAddress) { - return; - } - - const batchCall = new BatchCall(wallet, [ - gregoCoin.methods.balance_of_private(currentAddress), - gregoCoinPremium.methods.balance_of_private(currentAddress), - ]); - const [gcBalance, gcpBalance] = await batchCall.simulate({ from: currentAddress }); - return [gcBalance, gcpBalance] as [bigint, bigint]; - }, [wallet, gregoCoin, gregoCoinPremium, currentAddress]); - - const simulateOnboardingQueries = useCallback(async () => { - if (!wallet || !gregoCoin || !gregoCoinPremium || !amm || !currentAddress) { - throw new Error('Contracts not initialized'); - } - - // Create a batched simulation that includes: - // 1. Exchange rate data (public balances of AMM) - // 2. User's private balances - // This triggers wallet approval for these queries, so future reads are seamless - const batchCall = new BatchCall(wallet, [ - gregoCoin.methods.balance_of_public(amm.address), - gregoCoinPremium.methods.balance_of_public(amm.address), - gregoCoin.methods.balance_of_private(currentAddress), - gregoCoinPremium.methods.balance_of_private(currentAddress), - ]); - - const [token0Reserve, token1Reserve, gcBalance, gcpBalance] = await batchCall.simulate({ from: currentAddress }); - const exchangeRate = parseFloat(new BigDecimal(token1Reserve).divide(new BigDecimal(token0Reserve)).toString()); - return [exchangeRate, gcBalance, gcpBalance] as [number, bigint, bigint]; - }, [wallet, gregoCoin, gregoCoinPremium, amm, currentAddress]); - - const registerContractsForFlow = useCallback( - async (flowType: 'swap' | 'drip') => { - if (!wallet || !node) { - throw new Error('Wallet not initialized'); - } - - const gregoCoinAddress = AztecAddress.fromString(activeNetwork.contracts.gregoCoin); - const deployerAddress = AztecAddress.fromString(activeNetwork.deployer.address); - const contractSalt = Fr.fromString(activeNetwork.contracts.salt); - - if (flowType === 'swap') { - // Register GregoCoin, GregoCoinPremium, and AMM for external wallet onboarding - setIsLoadingContracts(true); - - const gregoCoinPremiumAddress = AztecAddress.fromString(activeNetwork.contracts.gregoCoinPremium); - const liquidityTokenAddress = AztecAddress.fromString(activeNetwork.contracts.liquidityToken); - const ammAddress = AztecAddress.fromString(activeNetwork.contracts.amm); - - // Import contract artifacts - const { TokenContract, TokenContractArtifact } = await import('@aztec/noir-contracts.js/Token'); - const { AMMContract, AMMContractArtifact } = await import('@aztec/noir-contracts.js/AMM'); - - // Reconstruct contract instances using the actual salt from deployment - const [ammInstance, gregoCoinInstance, gregoCoinPremiumInstance] = await Promise.all([ - getContractInstanceFromInstantiationParams(AMMContractArtifact, { - salt: contractSalt, - deployer: deployerAddress, - constructorArgs: [gregoCoinAddress, gregoCoinPremiumAddress, liquidityTokenAddress], - }), - getContractInstanceFromInstantiationParams(TokenContractArtifact, { - salt: contractSalt, - deployer: deployerAddress, - constructorArgs: [deployerAddress, 'GregoCoin', 'GRG', 18], - }), - getContractInstanceFromInstantiationParams(TokenContractArtifact, { - salt: contractSalt, - deployer: deployerAddress, - constructorArgs: [deployerAddress, 'GregoCoinPremium', 'GRGP', 18], - }), - ]); - - // Register contracts in batch - await wallet.batch([ - { name: 'registerContract', args: [ammInstance, AMMContractArtifact, undefined] }, - { name: 'registerContract', args: [gregoCoinInstance, TokenContractArtifact, undefined] }, - { name: 'registerContract', args: [gregoCoinPremiumInstance, TokenContractArtifact, undefined] }, - ] as unknown as any); - - // After registration, instantiate the contracts - const gregoCoinContract = TokenContract.at(gregoCoinAddress, wallet); - const gregoCoinPremiumContract = TokenContract.at(gregoCoinPremiumAddress, wallet); - const ammContract = AMMContract.at(ammAddress, wallet); - - setGregoCoin(gregoCoinContract); - setGregoCoinPremium(gregoCoinPremiumContract); - setAmm(ammContract); - - setIsLoadingContracts(false); - } else { - // Register ProofOfPassword and SponsoredFPC for drip flow - setIsLoadingContracts(true); - - const popAddress = AztecAddress.fromString(activeNetwork.contracts.pop); - const { ProofOfPasswordContract, ProofOfPasswordContractArtifact } = await import( - '../../contracts/target/ProofOfPassword.ts' - ); - - const instance = await node.getContract(popAddress); - const { instance: sponsoredFPCInstance, artifact: SponsoredFPCContractArtifact } = await getSponsoredFPCData(); - - await wallet.batch([ - { name: 'registerContract', args: [instance, ProofOfPasswordContractArtifact, undefined] }, - { name: 'registerContract', args: [sponsoredFPCInstance, SponsoredFPCContractArtifact, undefined] }, - ]); - - // After registration, instantiate the ProofOfPassword contract - const popContract = ProofOfPasswordContract.at(popAddress, wallet); - setPop(popContract); - - setIsLoadingContracts(false); - } - }, - [wallet, node, activeNetwork], - ); - - // Initialize contracts for embedded wallet (external wallets register during onboarding) - useEffect(() => { - async function initializeContracts() { - if (walletLoading || !wallet) { - setIsLoadingContracts(walletLoading); - return; - } - - // For external wallets, don't initialize until onboarding registers contracts - if (!isUsingEmbeddedWallet) { - return; - } - - try { - // Use registerContractsForFlow to avoid code duplication - await registerContractsForFlow('swap'); - } catch (err) { - setIsLoadingContracts(false); - } - } - - initializeContracts(); - }, [wallet, walletLoading, isUsingEmbeddedWallet, registerContractsForFlow]); - - const value: ContractsContextType = { - isLoadingContracts, - getExchangeRate, - swap, - fetchBalances, - simulateOnboardingQueries, - registerContractsForFlow, - drip, - }; - - return {children}; -} diff --git a/src/contexts/OnboardingContext.tsx b/src/contexts/OnboardingContext.tsx deleted file mode 100644 index f1deb41..0000000 --- a/src/contexts/OnboardingContext.tsx +++ /dev/null @@ -1,351 +0,0 @@ -import { createContext, useContext, useState, useCallback, useEffect, useRef, type ReactNode } from 'react'; -import type { AztecAddress } from '@aztec/aztec.js/addresses'; -import { useWallet } from './WalletContext'; -import { useContracts } from './ContractsContext'; - -export type OnboardingFlowType = 'swap' | 'drip'; - -export type OnboardingStatus = - | 'not_started' // Using embedded wallet - | 'connecting_wallet' // Modal open, selecting account - | 'registering_contracts' // Batch registering contracts - | 'simulating_queries' // Batched simulation for approval (swap flow) - | 'awaiting_drip' // Waiting for user to enter password (drip flow) - | 'registering_drip' // Registering ProofOfPassword contract after password entry - | 'executing_drip' // Executing drip transaction (drip flow) - | 'completed' // Onboarded, ready for seamless ops - | 'error'; // Something failed - -export interface OnboardingStep { - label: string; - description: string; -} - -interface FlowConfig { - type: OnboardingFlowType; - steps: OnboardingStep[]; - totalSteps: number; - requiresAction: boolean; // true for drip (needs password) -} - -export const FLOW_CONFIGS: Record = { - swap: { - type: 'swap', - steps: [ - { label: 'Connect Wallet', description: 'Select your account from the wallet extension' }, - { label: 'Register Contracts', description: 'Setting up contracts' }, - { label: 'Approve Queries', description: 'Review and approve batched queries in your wallet' }, - ], - totalSteps: 4, - requiresAction: false, - }, - drip: { - type: 'drip', - steps: [ - { label: 'Connect Wallet', description: 'Select your account from the wallet extension' }, - { label: 'Setup Contracts', description: 'Setting up contracts and checking balances' }, - { label: 'Claim Tokens', description: 'Claiming your free GregoCoin tokens' }, - ], - totalSteps: 4, - requiresAction: true, - }, -}; - -interface OnboardingResult { - exchangeRate: number; - balances: { - gregoCoin: bigint; - gregoCoinPremium: bigint; - }; -} - -interface OnboardingState { - status: OnboardingStatus; - error: string | null; - currentStep: number; // Current step number (1-based) - totalSteps: number; // Total number of steps - flowType: OnboardingFlowType | null; - currentFlow: FlowConfig | null; -} - -// Minimal API exposed to consumers -interface OnboardingContextType extends OnboardingState { - // Modal states - isOnboardingModalOpen: boolean; - onboardingResult: OnboardingResult | null; - - // Pending operations after onboarding - isSwapPending: boolean; // Derived from flowType === 'swap' - isDripPending: boolean; // Derived from flowType === 'drip' - - // Drip state - dripPassword: string | null; // Password from drip onboarding - - // Actions - startOnboardingFlow: (flowType: OnboardingFlowType, initiatedSwap?: boolean) => void; - closeModal: () => void; - clearSwapPending: () => void; - completeDripOnboarding: (password: string) => void; - completeDripExecution: () => void; - clearDripPassword: () => void; - resetOnboarding: () => void; -} - -const OnboardingContext = createContext(undefined); - -export function useOnboarding() { - const context = useContext(OnboardingContext); - if (context === undefined) { - throw new Error('useOnboarding must be used within an OnboardingProvider'); - } - return context; -} - -interface OnboardingProviderProps { - children: ReactNode; -} - -// Helper to set onboarding status in localStorage -function setStoredOnboardingStatus(address: AztecAddress | null, completed: boolean) { - if (!address) return; - try { - localStorage.setItem(`onboarding_complete_${address.toString()}`, String(completed)); - } catch { - // Ignore localStorage errors - } -} - -export function OnboardingProvider({ children }: OnboardingProviderProps) { - // Pull from other contexts needed for flow orchestration - const { currentAddress, isUsingEmbeddedWallet } = useWallet(); - const { simulateOnboardingQueries, isLoadingContracts, registerContractsForFlow } = useContracts(); - - // Internal state - const [status, setStatusState] = useState('not_started'); - const [error, setError] = useState(null); - const [flowType, setFlowType] = useState(null); - const [onboardingResult, setOnboardingResult] = useState(null); - const [storedAddress] = useState(null); - const [dripPassword, setDripPassword] = useState(null); - - // Flow state - modal visibility - const [isOnboardingModalOpen, setIsOnboardingModalOpen] = useState(false); - - // Refs to prevent duplicate operations - const hasRegisteredBaseContractsRef = useRef(false); - const hasSimulatedRef = useRef(false); - - // Completed flow tracking - persists after status becomes 'completed' to trigger execution - const [completedFlowType, setCompletedFlowType] = useState(null); - // Track if user initiated a swap transaction (clicked Swap button with amount entered) - const [swapInitiated, setSwapInitiated] = useState(false); - - // Computed values - const currentFlow = flowType ? FLOW_CONFIGS[flowType] : null; - // isSwapPending: true after swap onboarding completes AND user initiated a swap - const isSwapPending = completedFlowType === 'swap' && swapInitiated; - const isDripPending = flowType === 'drip' && dripPassword !== null; - - // Calculate current step based on status - const currentStep = (() => { - switch (status) { - case 'not_started': - return 0; - case 'connecting_wallet': - return 1; - case 'registering_contracts': - return 2; // Step 2 - registering base contracts - case 'simulating_queries': - // For swap flow: step 3 (Approve Queries) - // For drip flow (before switching): step 2 (still setting up) - return flowType === 'swap' ? 3 : 2; - case 'registering_drip': - return 2; // Drip flow step 2 - registering drip-specific contracts - case 'awaiting_drip': - case 'executing_drip': - return 3; // Drip flow step 3 - waiting for password or executing - case 'completed': - return 4; // Final step is 4 for both flows - default: - return 0; - } - })(); - - const totalSteps = currentFlow?.totalSteps || 3; - - // Internal helpers - const setStatus = useCallback((newStatus: OnboardingStatus, errorMessage?: string) => { - setStatusState(newStatus); - if (errorMessage) { - setError(errorMessage); - } else if (newStatus !== 'error') { - setError(null); - } - }, []); - - const completeOnboarding = useCallback(() => { - // Track which flow completed to trigger post-onboarding actions (swap execution) - setCompletedFlowType(flowType); - setStatusState('completed'); - setError(null); - // Store completion in localStorage - setStoredOnboardingStatus(storedAddress, true); - }, [storedAddress, flowType]); - - // Onboarding orchestration - advance through steps - useEffect(() => { - async function handleOnboardingFlow() { - if (!flowType) return; - - try { - // SWAP FLOW: Full onboarding with simulation to detect if user needs drip - if (flowType === 'swap') { - // Step 1: After wallet connection, register swap contracts (GregoCoin, GregoCoinPremium, AMM) - if ( - status === 'connecting_wallet' && - currentAddress && - !isUsingEmbeddedWallet && - !hasRegisteredBaseContractsRef.current - ) { - hasRegisteredBaseContractsRef.current = true; - setStatus('registering_contracts'); - await registerContractsForFlow('swap'); - } - - // Step 2: After contracts are registered, simulate to determine the path - if (status === 'registering_contracts' && !isLoadingContracts && currentAddress && !hasSimulatedRef.current) { - hasSimulatedRef.current = true; - setStatus('simulating_queries'); - const [exchangeRate, gcBalance, gcpBalance] = await simulateOnboardingQueries(); - setOnboardingResult({ - exchangeRate, - balances: { - gregoCoin: gcBalance, - gregoCoinPremium: gcpBalance, - }, - }); - - // Decide flow based on balances - const hasNoTokens = gcBalance === 0n; - - if (hasNoTokens) { - // User has no tokens - switch to drip flow and register ProofOfPassword contracts - setFlowType('drip'); - setStatus('registering_drip'); - await registerContractsForFlow('drip'); - // After drip contracts are registered, transition to awaiting password - setStatus('awaiting_drip'); - } else { - // User has tokens - complete swap onboarding - completeOnboarding(); - } - } - } - } catch (error) { - setStatus('error', error instanceof Error ? error.message : 'Onboarding failed'); - } - } - - handleOnboardingFlow(); - }, [ - status, - flowType, - currentAddress, - isUsingEmbeddedWallet, - isLoadingContracts, - setStatus, - completeOnboarding, - simulateOnboardingQueries, - registerContractsForFlow, - ]); - - // Note: Modal auto-closes itself via OnboardingModal's completion animation effect - // No need to close it here - let the modal's animation complete first - - // Public API - const startOnboardingFlow = useCallback((newFlowType: OnboardingFlowType, initiatedSwap: boolean = false) => { - // Reset refs to allow new onboarding session - hasRegisteredBaseContractsRef.current = false; - hasSimulatedRef.current = false; - - setFlowType(newFlowType); - setCompletedFlowType(null); - setSwapInitiated(initiatedSwap); // Track if this is for a swap transaction - setStatusState('connecting_wallet'); - setError(null); - setIsOnboardingModalOpen(true); - }, []); - - const closeModal = useCallback(() => { - setIsOnboardingModalOpen(false); - // Clear flow state when modal closes - setFlowType(null); - setDripPassword(null); - }, []); - - const clearSwapPending = useCallback(() => { - if (flowType === 'swap') { - setFlowType(null); - } - setCompletedFlowType(null); - setSwapInitiated(false); - setIsOnboardingModalOpen(false); - }, [flowType]); - - const completeDripOnboarding = useCallback(async (password: string) => { - // Registration already happened in step 2, store password and transition to executing - console.log('completeDripOnboarding called with password:', !!password); - setDripPassword(password); - setStatusState('executing_drip'); - console.log('Status set to executing_drip, password set'); - }, []); - - const completeDripExecution = useCallback(() => { - // Called after drip transaction succeeds - completeOnboarding(); - }, [completeOnboarding]); - - const clearDripPassword = useCallback(() => { - setDripPassword(null); - // Don't clear flowType here - let it persist for modal display - // It will be cleared when modal closes or when starting a new flow - }, []); - - const resetOnboarding = useCallback(() => { - // Reset refs to allow new onboarding session - hasRegisteredBaseContractsRef.current = false; - hasSimulatedRef.current = false; - - setStatusState('not_started'); - setError(null); - setFlowType(null); - setCompletedFlowType(null); - setSwapInitiated(false); - setOnboardingResult(null); - setIsOnboardingModalOpen(false); - setDripPassword(null); - }, []); - - const value: OnboardingContextType = { - status, - error, - currentStep, - totalSteps, - flowType, - currentFlow, - isOnboardingModalOpen, - isSwapPending, - isDripPending, - onboardingResult, - dripPassword, - startOnboardingFlow, - closeModal, - clearSwapPending, - completeDripOnboarding, - completeDripExecution, - clearDripPassword, - resetOnboarding, - }; - - return {children}; -} diff --git a/src/contexts/WalletContext.tsx b/src/contexts/WalletContext.tsx deleted file mode 100644 index 1962624..0000000 --- a/src/contexts/WalletContext.tsx +++ /dev/null @@ -1,310 +0,0 @@ -import { createContext, useContext, useState, useEffect, useRef, type ReactNode, useCallback } from 'react'; -import { EmbeddedWallet } from '../embedded_wallet'; -import { createAztecNodeClient, type AztecNode } from '@aztec/aztec.js/node'; -import type { Wallet } from '@aztec/aztec.js/wallet'; -import type { AztecAddress } from '@aztec/aztec.js/addresses'; -import type { ChainInfo } from '@aztec/aztec.js/account'; -import { useNetwork } from './NetworkContext'; -import { Fr } from '@aztec/aztec.js/fields'; -import { WalletManager, type WalletProvider as WalletProviderType } from '@aztec/wallet-sdk/manager'; -import { hashToEmoji } from '@aztec/wallet-sdk/crypto'; - -/** - * Discovered wallet with verification emoji for anti-MITM protection - */ -export interface DiscoveredWalletWithEmoji { - provider: WalletProviderType; - verificationEmoji: string; -} - -/** - * Callback type for wallet disconnect events - */ -export type WalletDisconnectCallback = () => void; - -interface WalletContextType { - wallet: Wallet | null; - node: AztecNode | null; - currentAddress: AztecAddress | null; - isLoading: boolean; - error: string | null; - isUsingEmbeddedWallet: boolean; - /** Discovers available wallet extensions with verification emojis */ - discoverWallets: () => Promise; - /** Connects to a specific wallet provider (after user verifies emoji) */ - connectToProvider: (provider: WalletProviderType) => Promise; - /** Legacy: discovers and connects to first available wallet (no verification) */ - connectWallet: () => Promise; - setCurrentAddress: (address: AztecAddress | null) => void; - disconnectWallet: () => Promise; - /** Register a callback to be notified when the wallet unexpectedly disconnects */ - onWalletDisconnect: (callback: WalletDisconnectCallback) => () => void; -} - -const WalletContext = createContext(undefined); - -export function useWallet() { - const context = useContext(WalletContext); - if (context === undefined) { - throw new Error('useWallet must be used within a WalletProvider'); - } - return context; -} - -interface WalletProviderProps { - children: ReactNode; -} - -export function WalletProvider({ children }: WalletProviderProps) { - const { activeNetwork } = useNetwork(); - - const [wallet, setWallet] = useState(null); - const [currentAddress, setCurrentAddress] = useState(null); - const [node, setNode] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - const [isUsingEmbeddedWallet, setIsUsingEmbeddedWallet] = useState(true); - - const embeddedWalletRef = useRef(null); - const embeddedAddressRef = useRef(null); - const previousNodeUrlRef = useRef(null); - const hasConnectedExternalWalletRef = useRef(false); // Track if user explicitly connected external wallet - - // Track current provider and disconnect unsubscribe function - const currentProviderRef = useRef(null); - const providerDisconnectUnsubscribeRef = useRef<(() => void) | null>(null); - - // Callbacks registered by consumers to be notified of unexpected disconnects - const disconnectCallbacksRef = useRef>(new Set()); - - useEffect(() => { - const nodeUrl = activeNetwork?.nodeUrl; - - if (!nodeUrl) { - return; - } - - // Only initialize if nodeUrl has actually changed - if (previousNodeUrlRef.current === nodeUrl) { - return; - } - - previousNodeUrlRef.current = nodeUrl; - hasConnectedExternalWalletRef.current = false; // Reset when changing networks - - async function initializeWallet() { - try { - setIsLoading(true); - setError(null); - - const aztecNode = createAztecNodeClient(nodeUrl); - - setNode(aztecNode); - - const embeddedWallet = await EmbeddedWallet.create(aztecNode); - const defaultAccountAddress = (await embeddedWallet.getAccounts())[0]?.item; - - // Store embedded wallet and address for later restoration - embeddedWalletRef.current = embeddedWallet; - embeddedAddressRef.current = defaultAccountAddress; - - // Only set embedded wallet as active if user hasn't connected an external wallet - if (!hasConnectedExternalWalletRef.current) { - setIsUsingEmbeddedWallet(true); - setCurrentAddress(defaultAccountAddress); - setWallet(embeddedWallet); - } - setIsLoading(false); - } catch (err) { - const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; - - // Add helpful message for connection issues - const fullError = - errorMessage.includes('timeout') || errorMessage.includes('unreachable') - ? `${errorMessage}\n\nIf using local network, make sure Aztec sandbox is running:\n aztec start --sandbox\n\nThen deploy contracts:\n yarn deploy:local` - : errorMessage; - - setError(fullError); - setIsLoading(false); - } - } - - initializeWallet(); - }, [activeNetwork]); // Depend on activeNetwork but check nodeUrl manually - - /** - * Handles unexpected wallet disconnection. - * Cleans up provider references and notifies registered callbacks. - */ - const handleUnexpectedDisconnect = useCallback(() => { - console.log('Wallet disconnected unexpectedly'); - - // Clean up provider references - if (providerDisconnectUnsubscribeRef.current) { - providerDisconnectUnsubscribeRef.current(); - providerDisconnectUnsubscribeRef.current = null; - } - currentProviderRef.current = null; - - // Reset wallet state - restore embedded wallet - hasConnectedExternalWalletRef.current = false; - if (embeddedWalletRef.current) { - setWallet(embeddedWalletRef.current); - setCurrentAddress(embeddedAddressRef.current); - setIsUsingEmbeddedWallet(true); - } else { - setWallet(null); - setCurrentAddress(null); - setIsUsingEmbeddedWallet(true); - } - - // Notify all registered callbacks - for (const callback of disconnectCallbacksRef.current) { - try { - callback(); - } catch { - // Ignore errors in callbacks - } - } - }, []); - - /** - * Discovers available wallet extensions and returns them with verification emojis. - * The emoji is derived from the ECDH shared secret - both dApp and wallet compute - * the same emoji independently, allowing users to verify no MITM attack. - */ - const discoverWallets = useCallback(async (): Promise => { - const chainInfo: ChainInfo = { - chainId: Fr.fromString(activeNetwork.chainId), - version: Fr.fromString(activeNetwork.rollupVersion), - }; - - const manager = WalletManager.configure({ extensions: { enabled: true } }); - const providers = await manager.getAvailableWallets({ chainInfo, timeout: 2000 }); - - // Map providers to include verification emoji - return providers.map(provider => ({ - provider, - verificationEmoji: provider.metadata.verificationHash - ? hashToEmoji(provider.metadata.verificationHash as string) - : '', - })); - }, [activeNetwork]); - - /** - * Connects to a specific wallet provider after user has verified the emoji. - */ - const connectToProvider = useCallback(async (provider: WalletProviderType): Promise => { - // Disconnect from previous provider if any - if (currentProviderRef.current && currentProviderRef.current.disconnect) { - // Unsubscribe from previous disconnect callback - if (providerDisconnectUnsubscribeRef.current) { - providerDisconnectUnsubscribeRef.current(); - providerDisconnectUnsubscribeRef.current = null; - } - try { - await currentProviderRef.current.disconnect(); - } catch (error) { - console.warn('Error disconnecting previous wallet:', error); - } - } - - const appId = 'gregoswap'; - const extensionWallet = await provider.connect(appId); - - // Store provider reference - currentProviderRef.current = provider; - - // Register for disconnect events from the provider - if (provider.onDisconnect) { - providerDisconnectUnsubscribeRef.current = provider.onDisconnect(handleUnexpectedDisconnect); - } - - // Mark that user explicitly connected an external wallet - hasConnectedExternalWalletRef.current = true; - - // Replace the current wallet with extension wallet - setWallet(extensionWallet); - setCurrentAddress(null); - setIsUsingEmbeddedWallet(false); - return extensionWallet; - }, [handleUnexpectedDisconnect]); - - /** - * Legacy: discovers and connects to first available wallet (no verification step). - * Kept for backwards compatibility. - */ - const connectWallet = useCallback(async (): Promise => { - const wallets = await discoverWallets(); - - if (wallets.length === 0) { - throw new Error('No wallet extensions found. Please install a compatible Aztec wallet extension.'); - } - - // Connect to the first available wallet provider - return connectToProvider(wallets[0].provider); - }, [discoverWallets, connectToProvider]); - - const disconnectWallet = useCallback(async () => { - // Unsubscribe from disconnect callback before disconnecting - if (providerDisconnectUnsubscribeRef.current) { - providerDisconnectUnsubscribeRef.current(); - providerDisconnectUnsubscribeRef.current = null; - } - - // Disconnect from current provider - if (currentProviderRef.current && currentProviderRef.current.disconnect) { - try { - await currentProviderRef.current.disconnect(); - } catch (error) { - console.warn('Error disconnecting wallet:', error); - } - } - currentProviderRef.current = null; - - // Restore embedded wallet and address - if (embeddedWalletRef.current) { - hasConnectedExternalWalletRef.current = false; // Reset flag when disconnecting - setWallet(embeddedWalletRef.current); - setCurrentAddress(embeddedAddressRef.current); - setIsUsingEmbeddedWallet(true); - } - }, []); - - /** - * Register a callback to be notified when the wallet unexpectedly disconnects. - * Returns a function to unregister the callback. - */ - const onWalletDisconnect = useCallback((callback: WalletDisconnectCallback): (() => void) => { - disconnectCallbacksRef.current.add(callback); - return () => { - disconnectCallbacksRef.current.delete(callback); - }; - }, []); - - // Cleanup on unmount - useEffect(() => { - return () => { - if (providerDisconnectUnsubscribeRef.current) { - providerDisconnectUnsubscribeRef.current(); - } - }; - }, []); - - const value: WalletContextType = { - currentAddress, - wallet, - node, - isLoading, - error, - isUsingEmbeddedWallet, - discoverWallets, - connectToProvider, - connectWallet, - setCurrentAddress, - disconnectWallet, - onWalletDisconnect, - }; - - return {children}; -} diff --git a/src/contexts/contracts/ContractsContext.tsx b/src/contexts/contracts/ContractsContext.tsx new file mode 100644 index 0000000..7c626a8 --- /dev/null +++ b/src/contexts/contracts/ContractsContext.tsx @@ -0,0 +1,218 @@ +/** + * Contracts Context + * Manages contract instances and registration state + */ + +import { createContext, useContext, useEffect, type ReactNode, useCallback } from 'react'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import type { TxReceipt } from '@aztec/stdlib/tx'; +import { Fr } from '@aztec/aztec.js/fields'; +import { useWallet } from '../wallet'; +import { useNetwork } from '../network'; +import * as contractService from '../../services/contractService'; +import { useContractsReducer } from './reducer'; + +interface ContractsContextType { + isLoadingContracts: boolean; + + // Registration methods + registerBaseContracts: () => Promise; + registerDripContracts: () => Promise; + + // Utility methods + getExchangeRate: () => Promise; + swap: (amountOut: number, amountInMax: number) => Promise; + fetchBalances: () => Promise<[bigint, bigint]>; + simulateOnboardingQueries: () => Promise<[number, bigint, bigint]>; + drip: (password: string, recipient: AztecAddress) => Promise; +} + +const ContractsContext = createContext(undefined); + +export function useContracts() { + const context = useContext(ContractsContext); + if (context === undefined) { + throw new Error('useContracts must be used within a ContractsProvider'); + } + return context; +} + +interface ContractsProviderProps { + children: ReactNode; +} + +export function ContractsProvider({ children }: ContractsProviderProps) { + const { wallet, currentAddress, isLoading: walletLoading, node, isUsingEmbeddedWallet } = useWallet(); + const { activeNetwork } = useNetwork(); + + const [state, actions] = useContractsReducer(); + + // Register base contracts (AMM, tokens) + const registerBaseContracts = useCallback(async () => { + if (!wallet || !node) { + throw new Error('Wallet not initialized'); + } + + actions.registerStart(); + + try { + const swapContracts = await contractService.registerSwapContracts(wallet, node, activeNetwork); + actions.registerSuccess('base', swapContracts); + } catch (error) { + actions.registerFail(error instanceof Error ? error.message : 'Registration failed'); + throw error; + } + }, [wallet, node, activeNetwork, actions]); + + // Register drip contracts (ProofOfPassword) + const registerDripContracts = useCallback(async () => { + if (!wallet || !node) { + throw new Error('Wallet not initialized'); + } + + actions.registerStart(); + + try { + const dripContracts = await contractService.registerDripContracts(wallet, node, activeNetwork); + actions.registerSuccess('drip', dripContracts); + } catch (error) { + actions.registerFail(error instanceof Error ? error.message : 'Registration failed'); + throw error; + } + }, [wallet, node, activeNetwork, actions]); + + // Get exchange rate + const getExchangeRate = useCallback(async (): Promise => { + if (!wallet || !state.contracts.amm || !state.contracts.gregoCoin || !state.contracts.gregoCoinPremium) { + throw new Error('Contracts not initialized'); + } + + return contractService.getExchangeRate( + wallet, + { + gregoCoin: state.contracts.gregoCoin, + gregoCoinPremium: state.contracts.gregoCoinPremium, + amm: state.contracts.amm, + }, + currentAddress!, + ); + }, [wallet, state.contracts, currentAddress]); + + // Execute swap + const swap = useCallback( + async (amountOut: number, amountInMax: number): Promise => { + if ( + !wallet || + !currentAddress || + !state.contracts.amm || + !state.contracts.gregoCoin || + !state.contracts.gregoCoinPremium + ) { + throw new Error('Contracts not initialized'); + } + + const authwitNonce = Fr.random(); + + return state.contracts.amm.methods + .swap_tokens_for_exact_tokens( + state.contracts.gregoCoin.address, + state.contracts.gregoCoinPremium.address, + BigInt(Math.round(amountOut)), + BigInt(Math.round(amountInMax)), + authwitNonce, + ) + .send({ from: currentAddress }); + }, + [wallet, currentAddress, state.contracts], + ); + + // Fetch balances + const fetchBalances = useCallback(async (): Promise<[bigint, bigint]> => { + if (!wallet || !currentAddress || !state.contracts.gregoCoin || !state.contracts.gregoCoinPremium) { + throw new Error('Contracts not initialized'); + } + + return contractService.fetchBalances( + wallet, + { + gregoCoin: state.contracts.gregoCoin, + gregoCoinPremium: state.contracts.gregoCoinPremium, + amm: state.contracts.amm!, + }, + currentAddress, + ); + }, [wallet, currentAddress, state.contracts]); + + // Simulate onboarding queries + const simulateOnboardingQueries = useCallback(async (): Promise<[number, bigint, bigint]> => { + if ( + !wallet || + !currentAddress || + !state.contracts.amm || + !state.contracts.gregoCoin || + !state.contracts.gregoCoinPremium + ) { + throw new Error('Contracts not initialized'); + } + + const result = await contractService.simulateOnboardingQueries( + wallet, + { + gregoCoin: state.contracts.gregoCoin, + gregoCoinPremium: state.contracts.gregoCoinPremium, + amm: state.contracts.amm, + }, + currentAddress, + ); + + return [result.exchangeRate, result.balances.gregoCoin, result.balances.gregoCoinPremium]; + }, [wallet, currentAddress, state.contracts]); + + // Execute drip + const drip = useCallback( + async (password: string, recipient: AztecAddress): Promise => { + if (!state.contracts.pop) { + throw new Error('ProofOfPassword contract not initialized'); + } + + return contractService.executeDrip(state.contracts.pop, password, recipient); + }, + [state.contracts.pop], + ); + + // Initialize contracts for embedded wallet + useEffect(() => { + async function initializeContracts() { + if (walletLoading || !wallet) { + actions.registerStart(); + return; + } + + // For external wallets, don't initialize until onboarding registers contracts + if (!isUsingEmbeddedWallet) { + return; + } + + try { + await registerBaseContracts(); + } catch (err) { + actions.registerFail(err instanceof Error ? err.message : 'Failed to initialize'); + } + } + + initializeContracts(); + }, [wallet, walletLoading, isUsingEmbeddedWallet, registerBaseContracts, actions]); + + const value: ContractsContextType = { + isLoadingContracts: state.isLoading, + registerBaseContracts, + registerDripContracts, + getExchangeRate, + swap, + fetchBalances, + simulateOnboardingQueries, + drip, + }; + + return {children}; +} diff --git a/src/contexts/contracts/index.ts b/src/contexts/contracts/index.ts new file mode 100644 index 0000000..bbde192 --- /dev/null +++ b/src/contexts/contracts/index.ts @@ -0,0 +1,2 @@ +export { ContractsProvider, useContracts } from './ContractsContext'; +export type { Contracts, ContractRegistrationStage, ContractsState } from './reducer'; diff --git a/src/contexts/contracts/reducer.ts b/src/contexts/contracts/reducer.ts new file mode 100644 index 0000000..4cc7ccb --- /dev/null +++ b/src/contexts/contracts/reducer.ts @@ -0,0 +1,83 @@ +/** + * Contracts Reducer + * Manages contract instances and registration state + */ + +import type { TokenContract } from '@aztec/noir-contracts.js/Token'; +import type { AMMContract } from '@aztec/noir-contracts.js/AMM'; +import type { ProofOfPasswordContract } from '../../../contracts/target/ProofOfPassword'; +import { createReducerHook, type ActionsFrom } from '../utils'; + +// ============================================================================= +// State +// ============================================================================= + +export interface Contracts { + gregoCoin: TokenContract | null; + gregoCoinPremium: TokenContract | null; + amm: AMMContract | null; + pop: ProofOfPasswordContract | null; +} + +export type ContractRegistrationStage = 'base' | 'drip'; + +export interface ContractsState { + contracts: Contracts; + isLoading: boolean; +} + +export const initialContractsState: ContractsState = { + contracts: { + gregoCoin: null, + gregoCoinPremium: null, + amm: null, + pop: null, + }, + isLoading: true, +}; + +// ============================================================================= +// Actions +// ============================================================================= + +export const contractsActions = { + registerStart: () => ({ type: 'contracts/REGISTER_START' as const }), + registerSuccess: (stage: ContractRegistrationStage, contracts: Partial) => ({ + type: 'contracts/REGISTER_SUCCESS' as const, + stage, + contracts, + }), + registerFail: (error: string) => ({ type: 'contracts/REGISTER_FAIL' as const, error }), +}; + +export type ContractsAction = ActionsFrom; + +// ============================================================================= +// Reducer +// ============================================================================= + +export function contractsReducer(state: ContractsState, action: ContractsAction): ContractsState { + switch (action.type) { + case 'contracts/REGISTER_START': + return { ...state, isLoading: true }; + + case 'contracts/REGISTER_SUCCESS': + return { + ...state, + contracts: { ...state.contracts, ...action.contracts }, + isLoading: false, + }; + + case 'contracts/REGISTER_FAIL': + return { ...state, isLoading: false }; + + default: + return state; + } +} + +// ============================================================================= +// Hook +// ============================================================================= + +export const useContractsReducer = createReducerHook(contractsReducer, contractsActions, initialContractsState); diff --git a/src/contexts/NetworkContext.tsx b/src/contexts/network/NetworkContext.tsx similarity index 95% rename from src/contexts/NetworkContext.tsx rename to src/contexts/network/NetworkContext.tsx index 470c9ac..4bcb6f3 100644 --- a/src/contexts/NetworkContext.tsx +++ b/src/contexts/network/NetworkContext.tsx @@ -1,5 +1,5 @@ import { createContext, useContext, useState, useEffect, useCallback, type ReactNode } from 'react'; -import { initializeNetworks, getNetworkById, type NetworkConfig } from '../config/networks'; +import { initializeNetworks, type NetworkConfig } from '../../config/networks'; interface NetworkContextType { activeNetwork: NetworkConfig; @@ -53,7 +53,7 @@ export function NetworkProvider({ children }: NetworkProviderProps) { if (stored && networks.some(n => n.id === stored)) { initialNetwork = stored; } - } catch (err) { + } catch { // Silently fail - localStorage not available } @@ -86,7 +86,7 @@ export function NetworkProvider({ children }: NetworkProviderProps) { // Persist to localStorage try { localStorage.setItem(STORAGE_KEY, networkId); - } catch (err) { + } catch { // Silently fail - localStorage not available } }, diff --git a/src/contexts/network/index.ts b/src/contexts/network/index.ts new file mode 100644 index 0000000..823bbca --- /dev/null +++ b/src/contexts/network/index.ts @@ -0,0 +1 @@ +export { NetworkProvider, useNetwork } from './NetworkContext'; diff --git a/src/contexts/onboarding/OnboardingContext.tsx b/src/contexts/onboarding/OnboardingContext.tsx new file mode 100644 index 0000000..cb51770 --- /dev/null +++ b/src/contexts/onboarding/OnboardingContext.tsx @@ -0,0 +1,245 @@ +/** + * Onboarding Context + * Manages the onboarding flow orchestration using a reducer + * Single unified flow: connect → register → simulate → [if no balance: drip detour] → completed + */ + +import { createContext, useContext, useCallback, useEffect, useRef, type ReactNode } from 'react'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import { useWallet } from '../wallet'; +import { useContracts } from '../contracts'; +import { + useOnboardingReducer, + calculateCurrentStep, + getOnboardingSteps, + getOnboardingStepsWithDrip, + ONBOARDING_STEPS, + ONBOARDING_STEPS_WITH_DRIP, + type OnboardingStatus, + type OnboardingStep, + type OnboardingResult, + type DripPhase, +} from './reducer'; +import { parseDripError } from '../../services/contractService'; + +export type { OnboardingStatus, OnboardingStep }; +export { ONBOARDING_STEPS, ONBOARDING_STEPS_WITH_DRIP, getOnboardingSteps, getOnboardingStepsWithDrip }; + +interface OnboardingContextType { + // State + status: OnboardingStatus; + error: string | null; + currentStep: number; + totalSteps: number; + steps: OnboardingStep[]; + isOnboardingModalOpen: boolean; + onboardingResult: OnboardingResult | null; + needsDrip: boolean; + + // Derived state + isSwapPending: boolean; + isDripPending: boolean; + dripPassword: string | null; + + // Tracking state + hasRegisteredBase: boolean; + hasSimulated: boolean; + hasSimulationGrant: boolean; + + // Drip execution state + dripPhase: DripPhase; + dripError: string | null; + isDripping: boolean; + + // Actions + startOnboarding: (initiatedSwap?: boolean) => void; + advanceStatus: (status: OnboardingStatus) => void; + setOnboardingResult: (result: OnboardingResult) => void; + markRegistered: () => void; + markSimulated: () => void; + setSimulationGrant: (granted: boolean) => void; + closeModal: () => void; + clearSwapPending: () => void; + completeDripOnboarding: (password: string) => void; + completeDripExecution: () => void; + clearDripPassword: () => void; + resetOnboarding: () => void; + dismissDripError: () => void; +} + +const OnboardingContext = createContext(undefined); + +export function useOnboarding() { + const context = useContext(OnboardingContext); + if (context === undefined) { + throw new Error('useOnboarding must be used within an OnboardingProvider'); + } + return context; +} + +interface OnboardingProviderProps { + children: ReactNode; +} + +function setStoredOnboardingStatus(address: AztecAddress | null, completed: boolean) { + if (!address) return; + try { + localStorage.setItem(`onboarding_complete_${address.toString()}`, String(completed)); + } catch { + // Ignore localStorage errors + } +} + +export function OnboardingProvider({ children }: OnboardingProviderProps) { + const { currentAddress, isUsingEmbeddedWallet } = useWallet(); + const { simulateOnboardingQueries, isLoadingContracts, registerBaseContracts, registerDripContracts, drip } = + useContracts(); + + const [state, actions] = useOnboardingReducer(); + + // Ref to prevent duplicate drip execution + const dripTriggeredRef = useRef(false); + + // Computed values + const steps = state.needsDrip + ? getOnboardingStepsWithDrip(state.hasSimulationGrant) + : getOnboardingSteps(state.hasSimulationGrant); + const currentStep = calculateCurrentStep(state.status, state.needsDrip); + const totalSteps = state.needsDrip ? 5 : 4; + const isSwapPending = state.status === 'completed' && state.pendingSwap; + const isDripPending = state.status === 'executing_drip' && state.dripPassword !== null; + const isDripping = state.dripPhase === 'sending' || state.dripPhase === 'mining'; + + // Onboarding orchestration effect + useEffect(() => { + async function handleOnboardingFlow() { + if (state.status === 'idle' || state.status === 'completed' || state.status === 'error') return; + + try { + // Step 1: After wallet connection, register base contracts (AMM, tokens) + if ( + state.status === 'connecting' && + currentAddress && + !isUsingEmbeddedWallet && + !state.hasRegisteredBase + ) { + actions.markRegistered(); + actions.advanceStatus('registering'); + await registerBaseContracts(); + } + + // Step 2: After contracts are registered, simulate to check balances + if (state.status === 'registering' && !isLoadingContracts && currentAddress && !state.hasSimulated) { + actions.markSimulated(); + actions.advanceStatus('simulating'); + + const [exchangeRate, gcBalance, gcpBalance] = await simulateOnboardingQueries(); + + const result: OnboardingResult = { + exchangeRate, + balances: { + gregoCoin: gcBalance, + gregoCoinPremium: gcpBalance, + }, + }; + actions.setResult(result); + + // Check if user has no tokens - need drip detour + const hasNoTokens = gcBalance === 0n; + + if (hasNoTokens) { + actions.markNeedsDrip(); + actions.advanceStatus('registering_drip'); + await registerDripContracts(); + actions.advanceStatus('awaiting_drip'); + } else { + // User has tokens, complete onboarding + setStoredOnboardingStatus(currentAddress, true); + actions.complete(); + } + } + } catch (error) { + actions.setError(error instanceof Error ? error.message : 'Onboarding failed'); + } + } + + handleOnboardingFlow(); + }, [ + state.status, + state.hasRegisteredBase, + state.hasSimulated, + currentAddress, + isUsingEmbeddedWallet, + isLoadingContracts, + simulateOnboardingQueries, + registerBaseContracts, + registerDripContracts, + actions, + ]); + + // Drip execution effect - triggers when password is provided during onboarding + useEffect(() => { + async function handleDrip() { + if (!isDripPending || !state.dripPassword || isDripping || state.dripPhase === 'error' || dripTriggeredRef.current || !currentAddress) { + return; + } + + dripTriggeredRef.current = true; + actions.startDrip(); + + try { + await drip(state.dripPassword, currentAddress); + actions.dripSuccess(); + setStoredOnboardingStatus(currentAddress, true); + actions.complete(); + } catch (error) { + actions.dripError(parseDripError(error)); + } finally { + dripTriggeredRef.current = false; + } + } + + handleDrip(); + }, [isDripPending, state.dripPassword, isDripping, currentAddress, drip, actions]); + + // Only need useCallback for functions that do more than just forward to actions + const completeDripExecution = useCallback(() => { + setStoredOnboardingStatus(currentAddress, true); + actions.complete(); + }, [currentAddress, actions]); + + const value: OnboardingContextType = { + status: state.status, + error: state.error, + currentStep, + totalSteps, + steps, + isOnboardingModalOpen: state.isModalOpen, + onboardingResult: state.result, + needsDrip: state.needsDrip, + isSwapPending, + isDripPending, + dripPassword: state.dripPassword, + hasRegisteredBase: state.hasRegisteredBase, + hasSimulated: state.hasSimulated, + hasSimulationGrant: state.hasSimulationGrant, + dripPhase: state.dripPhase, + dripError: state.dripError, + isDripping, + startOnboarding: actions.startFlow, + advanceStatus: actions.advanceStatus, + setOnboardingResult: actions.setResult, + markRegistered: actions.markRegistered, + markSimulated: actions.markSimulated, + setSimulationGrant: actions.setSimulationGrant, + closeModal: actions.closeModal, + clearSwapPending: actions.clearPendingSwap, + completeDripOnboarding: actions.setPassword, + completeDripExecution, + clearDripPassword: actions.closeModal, + resetOnboarding: actions.reset, + dismissDripError: actions.dismissDripError, + }; + + return {children}; +} diff --git a/src/contexts/onboarding/index.ts b/src/contexts/onboarding/index.ts new file mode 100644 index 0000000..46eda37 --- /dev/null +++ b/src/contexts/onboarding/index.ts @@ -0,0 +1,3 @@ +export { OnboardingProvider, useOnboarding, ONBOARDING_STEPS, ONBOARDING_STEPS_WITH_DRIP } from './OnboardingContext'; +export type { OnboardingStatus, OnboardingStep } from './OnboardingContext'; +export type { OnboardingResult, DripPhase } from './reducer'; diff --git a/src/contexts/onboarding/reducer.ts b/src/contexts/onboarding/reducer.ts new file mode 100644 index 0000000..e6fdbc2 --- /dev/null +++ b/src/contexts/onboarding/reducer.ts @@ -0,0 +1,221 @@ +/** + * Onboarding Reducer + * Manages the onboarding flow state machine and drip execution + */ + +import { createReducerHook, type ActionsFrom } from '../utils'; + +// ============================================================================= +// State +// ============================================================================= + +export type OnboardingStatus = + | 'idle' + | 'connecting' + | 'registering' + | 'simulating' + | 'registering_drip' + | 'awaiting_drip' + | 'executing_drip' + | 'completed' + | 'error'; + +export type DripPhase = 'idle' | 'sending' | 'mining' | 'success' | 'error'; + +export interface OnboardingResult { + exchangeRate: number; + balances: { + gregoCoin: bigint; + gregoCoinPremium: bigint; + }; +} + +export interface OnboardingStep { + label: string; + description: string; +} + +export interface OnboardingState { + status: OnboardingStatus; + isModalOpen: boolean; + result: OnboardingResult | null; + pendingSwap: boolean; + dripPassword: string | null; + error: string | null; + hasRegisteredBase: boolean; + hasSimulated: boolean; + needsDrip: boolean; + dripPhase: DripPhase; + dripError: string | null; + /** Whether simulation capabilities were granted in the manifest */ + hasSimulationGrant: boolean; +} + +export const initialOnboardingState: OnboardingState = { + status: 'idle', + isModalOpen: false, + result: null, + pendingSwap: false, + dripPassword: null, + error: null, + hasRegisteredBase: false, + hasSimulated: false, + needsDrip: false, + dripPhase: 'idle', + dripError: null, + hasSimulationGrant: false, +}; + +// ============================================================================= +// Actions +// ============================================================================= + +export const onboardingActions = { + startFlow: (initiatedSwap: boolean) => ({ type: 'onboarding/START_FLOW' as const, initiatedSwap }), + advanceStatus: (status: OnboardingStatus) => ({ type: 'onboarding/ADVANCE_STATUS' as const, status }), + setResult: (result: OnboardingResult) => ({ type: 'onboarding/SET_RESULT' as const, result }), + setPassword: (password: string) => ({ type: 'onboarding/SET_PASSWORD' as const, password }), + markRegistered: () => ({ type: 'onboarding/MARK_REGISTERED' as const }), + markSimulated: () => ({ type: 'onboarding/MARK_SIMULATED' as const }), + markNeedsDrip: () => ({ type: 'onboarding/MARK_NEEDS_DRIP' as const }), + setSimulationGrant: (granted: boolean) => ({ type: 'onboarding/SET_SIMULATION_GRANT' as const, granted }), + complete: () => ({ type: 'onboarding/COMPLETE' as const }), + closeModal: () => ({ type: 'onboarding/CLOSE_MODAL' as const }), + clearPendingSwap: () => ({ type: 'onboarding/CLEAR_PENDING_SWAP' as const }), + setError: (error: string) => ({ type: 'onboarding/SET_ERROR' as const, error }), + reset: () => ({ type: 'onboarding/RESET' as const }), + // Drip actions + startDrip: () => ({ type: 'onboarding/START_DRIP' as const }), + dripSuccess: () => ({ type: 'onboarding/DRIP_SUCCESS' as const }), + dripError: (error: string) => ({ type: 'onboarding/DRIP_ERROR' as const, error }), + dismissDripError: () => ({ type: 'onboarding/DISMISS_DRIP_ERROR' as const }), +}; + +export type OnboardingAction = ActionsFrom; + +// ============================================================================= +// Reducer +// ============================================================================= + +export function onboardingReducer(state: OnboardingState, action: OnboardingAction): OnboardingState { + switch (action.type) { + case 'onboarding/START_FLOW': + return { + ...initialOnboardingState, + status: 'connecting', + isModalOpen: true, + pendingSwap: action.initiatedSwap, + }; + + case 'onboarding/ADVANCE_STATUS': + return { + ...state, + status: action.status, + error: action.status === 'error' ? state.error : null, + }; + + case 'onboarding/SET_RESULT': + return { ...state, result: action.result }; + + case 'onboarding/SET_PASSWORD': + return { ...state, dripPassword: action.password, status: 'executing_drip' }; + + case 'onboarding/MARK_REGISTERED': + return { ...state, hasRegisteredBase: true }; + + case 'onboarding/MARK_SIMULATED': + return { ...state, hasSimulated: true }; + + case 'onboarding/MARK_NEEDS_DRIP': + return { ...state, needsDrip: true, pendingSwap: false }; + + case 'onboarding/SET_SIMULATION_GRANT': + return { ...state, hasSimulationGrant: action.granted }; + + case 'onboarding/COMPLETE': + return { ...state, status: 'completed', error: null }; + + case 'onboarding/CLOSE_MODAL': + return { ...state, isModalOpen: false, dripPassword: null }; + + case 'onboarding/CLEAR_PENDING_SWAP': + return { ...state, pendingSwap: false, isModalOpen: false }; + + case 'onboarding/SET_ERROR': + return { ...state, status: 'error', error: action.error }; + + case 'onboarding/RESET': + return initialOnboardingState; + + // Drip actions + case 'onboarding/START_DRIP': + return { ...state, dripPhase: 'sending', dripError: null }; + + case 'onboarding/DRIP_SUCCESS': + return { ...state, dripPhase: 'success', dripError: null }; + + case 'onboarding/DRIP_ERROR': + return { ...state, dripPhase: 'error', dripError: action.error }; + + case 'onboarding/DISMISS_DRIP_ERROR': + return { ...state, dripPhase: 'idle', dripError: null }; + + default: + return state; + } +} + +// ============================================================================= +// Helpers +// ============================================================================= + +export function calculateCurrentStep(status: OnboardingStatus, needsDrip: boolean): number { + switch (status) { + case 'idle': + return 0; + case 'connecting': + return 1; + case 'registering': + return 2; + case 'simulating': + return 3; + case 'registering_drip': + return 3; + case 'awaiting_drip': + case 'executing_drip': + return 4; + case 'completed': + return needsDrip ? 5 : 4; + default: + return 0; + } +} + +export function getOnboardingSteps(hasSimulationGrant: boolean): OnboardingStep[] { + return [ + { label: 'Connect Wallet', description: 'Select your account from the wallet extension' }, + { label: 'Register Contracts', description: 'Registering any missing contracts' }, + hasSimulationGrant + ? { label: 'Fetch Balances', description: 'Fetching your token balances' } + : { label: 'Approve Queries', description: 'Review and approve batched queries in your wallet' }, + ]; +} + +export function getOnboardingStepsWithDrip(hasSimulationGrant: boolean): OnboardingStep[] { + return [ + { label: 'Connect Wallet', description: 'Select your account from the wallet extension' }, + { label: 'Register Contracts', description: 'Registering any missing contracts' }, + { label: 'Register Faucet', description: 'Registering the token faucet contract if needed' }, + { label: 'Claim Tokens', description: 'Claiming your free GregoCoin tokens' }, + ]; +} + +// Keep backwards-compatible exports for default (no grant) case +export const ONBOARDING_STEPS: OnboardingStep[] = getOnboardingSteps(false); +export const ONBOARDING_STEPS_WITH_DRIP: OnboardingStep[] = getOnboardingStepsWithDrip(false); + +// ============================================================================= +// Hook +// ============================================================================= + +export const useOnboardingReducer = createReducerHook(onboardingReducer, onboardingActions, initialOnboardingState); diff --git a/src/contexts/swap/SwapContext.tsx b/src/contexts/swap/SwapContext.tsx new file mode 100644 index 0000000..e4514d6 --- /dev/null +++ b/src/contexts/swap/SwapContext.tsx @@ -0,0 +1,245 @@ +/** + * Swap Context + * Manages swap UI state and execution + */ + +import { createContext, useContext, useCallback, useEffect, useRef, type ReactNode } from 'react'; +import { useContracts } from '../contracts'; +import { useOnboarding } from '../onboarding'; +import { useSwapReducer, type SwapState } from './reducer'; +import { GREGOCOIN_USD_PRICE, EXCHANGE_RATE_POLL_INTERVAL_MS } from '../../types'; + +interface SwapContextType extends SwapState { + // Computed values + fromAmountUSD: number; + toAmountUSD: number; + canSwap: boolean; + isSwapping: boolean; + + // Actions + setFromAmount: (amount: string) => void; + setToAmount: (amount: string) => void; + executeSwap: () => Promise; + dismissError: () => void; + reset: () => void; +} + +const SwapContext = createContext(undefined); + +export function useSwap() { + const context = useContext(SwapContext); + if (context === undefined) { + throw new Error('useSwap must be used within a SwapProvider'); + } + return context; +} + +interface SwapProviderProps { + children: ReactNode; +} + +export function SwapProvider({ children }: SwapProviderProps) { + const { swap, isLoadingContracts, getExchangeRate } = useContracts(); + const { + status: onboardingStatus, + onboardingResult, + isSwapPending, + isDripPending, + clearSwapPending, + } = useOnboarding(); + + const [state, actions] = useSwapReducer(); + + // Refs for rate fetching and orchestration + const isFetchingRateRef = useRef(false); + const hasUsedOnboardingResultRef = useRef(false); + const swapTriggeredRef = useRef(false); + const prevExchangeRateRef = useRef(null); + + // Computed value used by multiple effects + const isSwapping = state.phase === 'sending'; + + // Internal swap execution (for use in effects) + const doSwap = useCallback(async () => { + if (isLoadingContracts || !state.fromAmount || parseFloat(state.fromAmount) <= 0) { + actions.swapError('Cannot perform swap: Missing data or invalid amount'); + return; + } + + actions.startSwap(); + + try { + await swap(parseFloat(state.toAmount), parseFloat(state.fromAmount) * 1.1); + actions.swapSuccess(); + } catch (error) { + let errorMessage = 'Swap failed. Please try again.'; + + if (error instanceof Error) { + if (error.message.includes('Simulation failed')) { + errorMessage = error.message; + } else if (error.message.includes('User denied') || error.message.includes('rejected')) { + errorMessage = 'Transaction was rejected in wallet'; + } else if (error.message.includes('Insufficient') || error.message.includes('insufficient')) { + errorMessage = 'Insufficient GregoCoin balance for swap'; + } else { + errorMessage = error.message; + } + } + + actions.swapError(errorMessage); + } + }, [isLoadingContracts, state.fromAmount, state.toAmount, swap, actions]); + + // Pre-populate exchange rate from onboarding result + useEffect(() => { + if (onboardingResult && !hasUsedOnboardingResultRef.current) { + actions.setRate(onboardingResult.exchangeRate); + hasUsedOnboardingResultRef.current = true; + } + }, [onboardingResult, actions]); + + // Execute swap when onboarding completes with pending swap + useEffect(() => { + if (onboardingStatus === 'completed' && isSwapPending && !swapTriggeredRef.current) { + swapTriggeredRef.current = true; + doSwap(); + } + }, [onboardingStatus, isSwapPending, doSwap]); + + // Clear pending flag after swap completes + useEffect(() => { + if (swapTriggeredRef.current && isSwapPending && !isSwapping) { + swapTriggeredRef.current = false; + clearSwapPending(); + } + }, [isSwapPending, isSwapping, clearSwapPending]); + + // Recalculate amounts when exchange rate becomes available + useEffect(() => { + const wasUnavailable = prevExchangeRateRef.current === null; + const isNowAvailable = state.exchangeRate !== null; + + if (wasUnavailable && isNowAvailable) { + if (state.fromAmount !== '' && state.toAmount === '') { + const numValue = parseFloat(state.fromAmount); + if (!isNaN(numValue)) { + actions.setToAmount((numValue * state.exchangeRate).toFixed(6)); + } + } else if (state.toAmount !== '' && state.fromAmount === '') { + const numValue = parseFloat(state.toAmount); + if (!isNaN(numValue)) { + actions.setFromAmount((numValue / state.exchangeRate).toFixed(6)); + } + } + } + + prevExchangeRateRef.current = state.exchangeRate; + }, [state.exchangeRate, state.fromAmount, state.toAmount, actions]); + + // Reset exchange rate when contracts are loading + useEffect(() => { + if (isLoadingContracts) { + actions.setLoadingRate(false); + isFetchingRateRef.current = false; + } + }, [isLoadingContracts, actions]); + + // Fetch exchange rate with auto-refresh + useEffect(() => { + async function fetchExchangeRate() { + const isSwapping = state.phase === 'sending'; + const isBusy = isLoadingContracts || isSwapping || isSwapPending || isDripPending; + const isOnboardingInProgress = onboardingStatus !== 'completed' && onboardingStatus !== 'idle'; + + if (isBusy || isOnboardingInProgress) { + actions.setLoadingRate(false); + return; + } + + if (isFetchingRateRef.current) { + return; + } + + try { + isFetchingRateRef.current = true; + actions.setLoadingRate(true); + + const rate = await getExchangeRate(); + actions.setRate(rate); + } finally { + actions.setLoadingRate(false); + isFetchingRateRef.current = false; + } + } + + fetchExchangeRate(); + + const intervalId = setInterval(() => { + fetchExchangeRate(); + }, EXCHANGE_RATE_POLL_INTERVAL_MS); + + return () => { + clearInterval(intervalId); + actions.setLoadingRate(false); + isFetchingRateRef.current = false; + }; + }, [isLoadingContracts, state.phase, isDripPending, getExchangeRate, onboardingStatus, isSwapPending, actions]); + + // Amount change handlers with recalculation + const setFromAmount = useCallback( + (value: string) => { + actions.setFromAmount(value); + + if (value === '' || state.exchangeRate === null) { + actions.setToAmount(''); + } else { + const numValue = parseFloat(value); + if (!isNaN(numValue)) { + actions.setToAmount((numValue * state.exchangeRate).toFixed(6)); + } + } + }, + [state.exchangeRate, actions] + ); + + const setToAmount = useCallback( + (value: string) => { + actions.setToAmount(value); + + if (value === '' || state.exchangeRate === null) { + actions.setFromAmount(''); + } else { + const numValue = parseFloat(value); + if (!isNaN(numValue)) { + actions.setFromAmount((numValue / state.exchangeRate).toFixed(6)); + } + } + }, + [state.exchangeRate, actions] + ); + + // Computed values + const fromAmountUSD = state.fromAmount ? parseFloat(state.fromAmount) * GREGOCOIN_USD_PRICE : 0; + const toAmountUSD = state.toAmount ? parseFloat(state.toAmount) * GREGOCOIN_USD_PRICE : 0; + + const canSwap = + !!state.fromAmount && + parseFloat(state.fromAmount) > 0 && + !isLoadingContracts && + (onboardingStatus === 'idle' || onboardingStatus === 'completed'); + + const value: SwapContextType = { + ...state, + fromAmountUSD, + toAmountUSD, + canSwap, + isSwapping, + setFromAmount, + setToAmount, + executeSwap: doSwap, + dismissError: actions.dismissError, + reset: actions.reset, + }; + + return {children}; +} diff --git a/src/contexts/swap/index.ts b/src/contexts/swap/index.ts new file mode 100644 index 0000000..d7413e7 --- /dev/null +++ b/src/contexts/swap/index.ts @@ -0,0 +1,2 @@ +export { SwapProvider, useSwap } from './SwapContext'; +export type { SwapPhase, SwapState } from './reducer'; diff --git a/src/contexts/swap/reducer.ts b/src/contexts/swap/reducer.ts new file mode 100644 index 0000000..7a59265 --- /dev/null +++ b/src/contexts/swap/reducer.ts @@ -0,0 +1,92 @@ +/** + * Swap Reducer + * Manages swap UI state and transaction phases + */ + +import { createReducerHook, type ActionsFrom } from '../utils'; + +// ============================================================================= +// State +// ============================================================================= + +export type SwapPhase = 'idle' | 'sending' | 'success' | 'error'; + +export interface SwapState { + fromAmount: string; + toAmount: string; + exchangeRate: number | null; + isLoadingRate: boolean; + phase: SwapPhase; + error: string | null; +} + +export const initialSwapState: SwapState = { + fromAmount: '', + toAmount: '', + exchangeRate: null, + isLoadingRate: false, + phase: 'idle', + error: null, +}; + +// ============================================================================= +// Actions +// ============================================================================= + +export const swapActions = { + setFromAmount: (amount: string) => ({ type: 'swap/SET_FROM_AMOUNT' as const, amount }), + setToAmount: (amount: string) => ({ type: 'swap/SET_TO_AMOUNT' as const, amount }), + setRate: (rate: number) => ({ type: 'swap/SET_RATE' as const, rate }), + setLoadingRate: (loading: boolean) => ({ type: 'swap/SET_LOADING_RATE' as const, loading }), + startSwap: () => ({ type: 'swap/START_SWAP' as const }), + swapSuccess: () => ({ type: 'swap/SWAP_SUCCESS' as const }), + swapError: (error: string) => ({ type: 'swap/SWAP_ERROR' as const, error }), + dismissError: () => ({ type: 'swap/DISMISS_ERROR' as const }), + reset: () => ({ type: 'swap/RESET' as const }), +}; + +export type SwapAction = ActionsFrom; + +// ============================================================================= +// Reducer +// ============================================================================= + +export function swapReducer(state: SwapState, action: SwapAction): SwapState { + switch (action.type) { + case 'swap/SET_FROM_AMOUNT': + return { ...state, fromAmount: action.amount }; + + case 'swap/SET_TO_AMOUNT': + return { ...state, toAmount: action.amount }; + + case 'swap/SET_RATE': + return { ...state, exchangeRate: action.rate, isLoadingRate: false }; + + case 'swap/SET_LOADING_RATE': + return { ...state, isLoadingRate: action.loading }; + + case 'swap/START_SWAP': + return { ...state, phase: 'sending', error: null }; + + case 'swap/SWAP_SUCCESS': + return { ...state, phase: 'success', fromAmount: '', toAmount: '' }; + + case 'swap/SWAP_ERROR': + return { ...state, phase: 'error', error: action.error }; + + case 'swap/DISMISS_ERROR': + return { ...state, phase: 'idle', error: null }; + + case 'swap/RESET': + return { ...initialSwapState, exchangeRate: state.exchangeRate }; + + default: + return state; + } +} + +// ============================================================================= +// Hook +// ============================================================================= + +export const useSwapReducer = createReducerHook(swapReducer, swapActions, initialSwapState); diff --git a/src/contexts/utils.ts b/src/contexts/utils.ts new file mode 100644 index 0000000..f65f9e8 --- /dev/null +++ b/src/contexts/utils.ts @@ -0,0 +1,62 @@ +/** + * Reducer Utilities + * Helper functions for creating type-safe reducers with bound actions + */ + +import { useMemo, useReducer } from 'react'; + +/** + * Generic type for action creator objects + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ActionCreators = Record { type: string }>; + +/** + * Extracts the return type union from an action creators object + */ +export type ActionsFrom = ReturnType; + +/** + * Creates bound action dispatchers from action creators + * + * @example + * const actions = bindActions(swapActions, dispatch); + * actions.setFromAmount('100'); // Dispatches { type: 'SET_FROM_AMOUNT', amount: '100' } + */ +export function bindActions( + actionCreators: T, + dispatch: React.Dispatch> +): { [K in keyof T]: (...args: Parameters) => void } { + const bound = {} as { [K in keyof T]: (...args: Parameters) => void }; + + for (const key in actionCreators) { + bound[key] = ((...args: Parameters) => + dispatch(actionCreators[key](...args) as ReturnType)) as (typeof bound)[typeof key]; + } + + return bound; +} + +/** + * Creates a useReducer hook pre-configured with a specific reducer, actions, and initial state. + * Returns a hook that provides [state, boundActions] tuple. + * + * @example + * // In reducer file: + * export const useContractsReducer = createReducerHook(contractsReducer, contractsActions, initialContractsState); + * + * // In context: + * const [state, actions] = useContractsReducer(); + * actions.registerStart(); // Type-safe! + */ +export function createReducerHook( + reducer: (state: S, action: ReturnType) => S, + actionCreators: T, + initialState: S +): () => [S, { [K in keyof T]: (...args: Parameters) => void }] { + return function useReducerWithActions() { + const [state, dispatch] = useReducer(reducer, initialState); + const actions = useMemo(() => bindActions(actionCreators, dispatch), [dispatch]); + return [state, actions]; + }; +} diff --git a/src/contexts/wallet/WalletContext.tsx b/src/contexts/wallet/WalletContext.tsx new file mode 100644 index 0000000..0e8e8e2 --- /dev/null +++ b/src/contexts/wallet/WalletContext.tsx @@ -0,0 +1,285 @@ +/** + * Wallet Context + * Manages wallet instances (embedded vs external) and current address + * Connection flow logic has been extracted to WalletConnectionContext + */ + +import { createContext, useContext, useEffect, useRef, type ReactNode, useCallback } from 'react'; +import type { AztecNode } from '@aztec/aztec.js/node'; +import type { Wallet } from '@aztec/aztec.js/wallet'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import type { WalletProvider, PendingConnection, DiscoverySession } from '@aztec/wallet-sdk/manager'; +import { useNetwork } from '../network'; +import * as walletService from '../../services/walletService'; +import { useWalletReducer } from './reducer'; + +export type WalletDisconnectCallback = () => void; + +interface WalletContextType { + wallet: Wallet | null; + node: AztecNode | null; + currentAddress: AztecAddress | null; + isLoading: boolean; + error: string | null; + isUsingEmbeddedWallet: boolean; + discoverWallets: (timeout?: number) => DiscoverySession; + initiateConnection: (provider: WalletProvider) => Promise; + confirmConnection: (provider: WalletProvider, pendingConnection: PendingConnection) => Promise; + cancelConnection: (pendingConnection: PendingConnection) => void; + + // State management + setCurrentAddress: (address: AztecAddress | null) => void; + setExternalWallet: (wallet: Wallet) => void; + disconnectWallet: () => Promise; + onWalletDisconnect: (callback: WalletDisconnectCallback) => () => void; +} + +const WalletContext = createContext(undefined); + +export function useWallet() { + const context = useContext(WalletContext); + if (context === undefined) { + throw new Error('useWallet must be used within a WalletProvider'); + } + return context; +} + +interface WalletProviderProps { + children: ReactNode; +} + +export function WalletProvider({ children }: WalletProviderProps) { + const { activeNetwork } = useNetwork(); + + const [state, actions] = useWalletReducer(); + + // Refs for embedded wallet restoration and provider tracking + const embeddedWalletRef = useRef(null); + const embeddedAddressRef = useRef(null); + const previousNodeUrlRef = useRef(null); + const hasConnectedExternalWalletRef = useRef(false); + + // Provider tracking for disconnect handling + const currentProviderRef = useRef(null); + const providerDisconnectUnsubscribeRef = useRef<(() => void) | null>(null); + const activeDiscoveryRef = useRef(null); + const disconnectCallbacksRef = useRef>(new Set()); + + // Initialize embedded wallet when network changes + useEffect(() => { + const nodeUrl = activeNetwork?.nodeUrl; + + if (!nodeUrl) { + return; + } + + // Only initialize if nodeUrl has actually changed + if (previousNodeUrlRef.current === nodeUrl) { + return; + } + + previousNodeUrlRef.current = nodeUrl; + hasConnectedExternalWalletRef.current = false; + + async function initializeWallet() { + try { + actions.initStart(); + + const node = walletService.createNodeClient(nodeUrl); + const embeddedWallet = await walletService.createEmbeddedWallet(node); + const accounts = await embeddedWallet.getAccounts(); + const defaultAccountAddress = accounts[0]?.item; + + // Store embedded wallet for later restoration + embeddedWalletRef.current = embeddedWallet; + embeddedAddressRef.current = defaultAccountAddress; + + // Only set embedded wallet as active if user hasn't connected an external wallet + if (!hasConnectedExternalWalletRef.current) { + actions.initEmbedded(embeddedWallet, node, defaultAccountAddress); + } + } catch (err) { + const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; + + const fullError = + errorMessage.includes('timeout') || errorMessage.includes('unreachable') + ? `${errorMessage}\n\nIf using local network, make sure Aztec sandbox is running:\n aztec start --sandbox\n\nThen deploy contracts:\n yarn deploy:local` + : errorMessage; + + actions.setError(fullError); + } + } + + initializeWallet(); + }, [activeNetwork, actions]); + + // Handle unexpected wallet disconnection + const handleUnexpectedDisconnect = useCallback(() => { + console.log('Wallet disconnected unexpectedly'); + + // Clean up provider references + if (providerDisconnectUnsubscribeRef.current) { + providerDisconnectUnsubscribeRef.current(); + providerDisconnectUnsubscribeRef.current = null; + } + currentProviderRef.current = null; + + // Reset wallet state - restore embedded wallet + hasConnectedExternalWalletRef.current = false; + if (embeddedWalletRef.current) { + actions.restoreEmbedded(embeddedWalletRef.current, embeddedAddressRef.current); + } else { + actions.disconnect(); + } + + // Notify all registered callbacks + for (const callback of disconnectCallbacksRef.current) { + try { + callback(); + } catch { + // Ignore errors in callbacks + } + } + }, [actions]); + + // Wallet discovery + const discoverWallets = useCallback( + (timeout?: number): DiscoverySession => { + if (activeDiscoveryRef.current) { + activeDiscoveryRef.current.cancel(); + } + + const chainInfo = walletService.getChainInfo(activeNetwork); + const discovery = walletService.discoverWallets(chainInfo, timeout); + + activeDiscoveryRef.current = discovery; + return discovery; + }, + [activeNetwork], + ); + + // Initiate connection + const initiateConnection = useCallback(async (provider: WalletProvider): Promise => { + // Disconnect from previous provider if any + if (currentProviderRef.current && currentProviderRef.current.disconnect) { + if (providerDisconnectUnsubscribeRef.current) { + providerDisconnectUnsubscribeRef.current(); + providerDisconnectUnsubscribeRef.current = null; + } + try { + await currentProviderRef.current.disconnect(); + } catch (error) { + console.warn('Error disconnecting previous wallet:', error); + } + } + + return walletService.initiateConnection(provider); + }, []); + + // Confirm connection + const confirmConnection = useCallback( + async (provider: WalletProvider, pendingConnection: PendingConnection): Promise => { + const extensionWallet = await walletService.confirmConnection(pendingConnection); + + // Store provider reference + currentProviderRef.current = provider; + + // Register for disconnect events + if (provider.onDisconnect) { + providerDisconnectUnsubscribeRef.current = provider.onDisconnect(handleUnexpectedDisconnect); + } + + // Mark that user explicitly connected an external wallet + hasConnectedExternalWalletRef.current = true; + + // Update state + actions.setExternal(extensionWallet); + + return extensionWallet; + }, + [handleUnexpectedDisconnect, actions], + ); + + // Cancel connection + const cancelConnection = useCallback((pendingConnection: PendingConnection): void => { + walletService.cancelConnection(pendingConnection); + }, []); + + // Set current address + const setCurrentAddress = useCallback( + (address: AztecAddress | null) => { + actions.setAddress(address); + }, + [actions], + ); + + // Set external wallet (called from WalletConnectionContext) + const setExternalWallet = useCallback( + (wallet: Wallet) => { + hasConnectedExternalWalletRef.current = true; + actions.setExternal(wallet); + }, + [actions], + ); + + // Disconnect wallet + const disconnectWallet = useCallback(async () => { + // Unsubscribe from disconnect callback before disconnecting + if (providerDisconnectUnsubscribeRef.current) { + providerDisconnectUnsubscribeRef.current(); + providerDisconnectUnsubscribeRef.current = null; + } + + // Disconnect from current provider + if (currentProviderRef.current) { + try { + await walletService.disconnectProvider(currentProviderRef.current); + } catch (error) { + console.warn('Error disconnecting wallet:', error); + } + } + currentProviderRef.current = null; + + // Restore embedded wallet + if (embeddedWalletRef.current) { + hasConnectedExternalWalletRef.current = false; + actions.restoreEmbedded(embeddedWalletRef.current, embeddedAddressRef.current); + } + }, [actions]); + + // Register disconnect callback + const onWalletDisconnect = useCallback((callback: WalletDisconnectCallback): (() => void) => { + disconnectCallbacksRef.current.add(callback); + return () => { + disconnectCallbacksRef.current.delete(callback); + }; + }, []); + + // Cleanup on unmount + useEffect(() => { + return () => { + if (providerDisconnectUnsubscribeRef.current) { + providerDisconnectUnsubscribeRef.current(); + } + }; + }, []); + + const value: WalletContextType = { + wallet: state.wallet, + node: state.node, + currentAddress: state.currentAddress, + isLoading: state.isLoading, + error: state.error, + isUsingEmbeddedWallet: state.isUsingEmbeddedWallet, + discoverWallets, + initiateConnection, + confirmConnection, + cancelConnection, + setCurrentAddress, + setExternalWallet, + disconnectWallet, + onWalletDisconnect, + }; + + return {children}; +} diff --git a/src/contexts/wallet/index.ts b/src/contexts/wallet/index.ts new file mode 100644 index 0000000..8d3f6cd --- /dev/null +++ b/src/contexts/wallet/index.ts @@ -0,0 +1,3 @@ +export { WalletProvider, useWallet } from './WalletContext'; +export type { WalletDisconnectCallback } from './WalletContext'; +export type { WalletState } from './reducer'; diff --git a/src/contexts/wallet/reducer.ts b/src/contexts/wallet/reducer.ts new file mode 100644 index 0000000..91c8070 --- /dev/null +++ b/src/contexts/wallet/reducer.ts @@ -0,0 +1,117 @@ +/** + * Wallet Reducer + * Manages wallet instances (embedded vs external) and current address + */ + +import type { AztecNode } from '@aztec/aztec.js/node'; +import type { Wallet } from '@aztec/aztec.js/wallet'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import { createReducerHook, type ActionsFrom } from '../utils'; + +// ============================================================================= +// State +// ============================================================================= + +export interface WalletState { + wallet: Wallet | null; + node: AztecNode | null; + currentAddress: AztecAddress | null; + isUsingEmbeddedWallet: boolean; + isLoading: boolean; + error: string | null; +} + +export const initialWalletState: WalletState = { + wallet: null, + node: null, + currentAddress: null, + isUsingEmbeddedWallet: true, + isLoading: true, + error: null, +}; + +// ============================================================================= +// Actions +// ============================================================================= + +export const walletActions = { + initStart: () => ({ type: 'wallet/INIT_START' as const }), + initEmbedded: (wallet: Wallet, node: AztecNode, address: AztecAddress) => ({ + type: 'wallet/INIT_EMBEDDED' as const, + wallet, + node, + address, + }), + setExternal: (wallet: Wallet) => ({ type: 'wallet/SET_EXTERNAL' as const, wallet }), + setAddress: (address: AztecAddress | null) => ({ type: 'wallet/SET_ADDRESS' as const, address }), + disconnect: () => ({ type: 'wallet/DISCONNECT' as const }), + restoreEmbedded: (wallet: Wallet, address: AztecAddress | null) => ({ + type: 'wallet/RESTORE_EMBEDDED' as const, + wallet, + address, + }), + setError: (error: string) => ({ type: 'wallet/SET_ERROR' as const, error }), +}; + +export type WalletAction = ActionsFrom; + +// ============================================================================= +// Reducer +// ============================================================================= + +export function walletReducer(state: WalletState, action: WalletAction): WalletState { + switch (action.type) { + case 'wallet/INIT_START': + return { ...state, isLoading: true, error: null }; + + case 'wallet/INIT_EMBEDDED': + return { + ...state, + wallet: action.wallet, + node: action.node, + currentAddress: action.address, + isUsingEmbeddedWallet: true, + isLoading: false, + error: null, + }; + + case 'wallet/SET_EXTERNAL': + return { + ...state, + wallet: action.wallet, + currentAddress: null, + isUsingEmbeddedWallet: false, + }; + + case 'wallet/SET_ADDRESS': + return { ...state, currentAddress: action.address }; + + case 'wallet/DISCONNECT': + return { + ...state, + wallet: null, + currentAddress: null, + isUsingEmbeddedWallet: true, + }; + + case 'wallet/RESTORE_EMBEDDED': + return { + ...state, + wallet: action.wallet, + currentAddress: action.address, + isUsingEmbeddedWallet: true, + }; + + case 'wallet/SET_ERROR': + return { ...state, isLoading: false, error: action.error }; + + default: + return state; + } +} + +// ============================================================================= +// Hook +// ============================================================================= + +export const useWalletReducer = createReducerHook(walletReducer, walletActions, initialWalletState); diff --git a/src/embedded_wallet.ts b/src/embedded_wallet.ts index e4b8192..a20ea8f 100644 --- a/src/embedded_wallet.ts +++ b/src/embedded_wallet.ts @@ -78,8 +78,7 @@ export class EmbeddedWallet extends BaseWallet { protected async getAccountFromAddress(address: AztecAddress): Promise { let account: Account | undefined; if (address.equals(AztecAddress.ZERO)) { - const chainInfo = await this.getChainInfo(); - account = new SignerlessAccount(chainInfo); + account = new SignerlessAccount(); } else if (this.accounts.has(address.toString())) { account = this.accounts.get(address.toString()); } else { @@ -103,14 +102,13 @@ export class EmbeddedWallet extends BaseWallet { } private async getFakeAccountDataFor(address: AztecAddress) { - const chainInfo = await this.getChainInfo(); const originalAccount = await this.getAccountFromAddress(address); const originalAddress = await originalAccount.getCompleteAddress(); - const { contractInstance } = await this.pxe.getContractMetadata(originalAddress.address); + const contractInstance = await this.pxe.getContractInstance(originalAddress.address); if (!contractInstance) { throw new Error(`No contract instance found for address: ${originalAddress.address}`); } - const stubAccount = createStubAccount(originalAddress, chainInfo); + const stubAccount = createStubAccount(originalAddress); const StubAccountContractArtifact = await getStubAccountContractArtifact(); const instance = await getContractInstanceFromInstantiationParams(StubAccountContractArtifact, { salt: Fr.random(), @@ -139,9 +137,11 @@ export class EmbeddedWallet extends BaseWallet { ? mergeExecutionPayloads([feeExecutionPayload, executionPayload]) : executionPayload; const { account: fromAccount, instance, artifact } = await this.getFakeAccountDataFor(opts.from); + const chainInfo = await this.getChainInfo(); const txRequest = await fromAccount.createTxExecutionRequest( finalExecutionPayload, feeOptions.gasSettings, + chainInfo, executionOptions, ); const contractOverrides = { diff --git a/src/hooks/useBalances.ts b/src/hooks/useBalances.ts deleted file mode 100644 index 6457d08..0000000 --- a/src/hooks/useBalances.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { useState, useEffect, useCallback } from 'react'; -import { useContracts } from '../contexts/ContractsContext'; -import { useWallet } from '../contexts/WalletContext'; -import { useOnboarding } from '../contexts/OnboardingContext'; - -interface Balances { - gregoCoin: bigint | null; - gregoCoinPremium: bigint | null; -} - -interface UseBalancesReturn { - balances: Balances; - isLoading: boolean; - refetch: () => Promise; -} - -export function useBalances(): UseBalancesReturn { - const { fetchBalances } = useContracts(); - const { currentAddress, isUsingEmbeddedWallet } = useWallet(); - const { onboardingResult } = useOnboarding(); - - const [balances, setBalances] = useState({ - gregoCoin: null, - gregoCoinPremium: null, - }); - const [isLoading, setIsLoading] = useState(false); - - // Pre-populate balances from onboarding result when available - useEffect(() => { - if (onboardingResult && balances.gregoCoin === null && balances.gregoCoinPremium === null) { - setBalances({ - gregoCoin: onboardingResult.balances.gregoCoin, - gregoCoinPremium: onboardingResult.balances.gregoCoinPremium, - }); - } - }, [onboardingResult, balances.gregoCoin, balances.gregoCoinPremium]); - - const refetch = useCallback(async () => { - // Only fetch for non-embedded wallets with an address - if (isUsingEmbeddedWallet || !currentAddress) { - setBalances({ gregoCoin: null, gregoCoinPremium: null }); - return; - } - - setIsLoading(true); - try { - const [gcBalance, gcpBalance] = await fetchBalances(); - setBalances({ - gregoCoin: gcBalance, - gregoCoinPremium: gcpBalance, - }); - } catch (err) { - // Silently fail and set to null - setBalances({ gregoCoin: null, gregoCoinPremium: null }); - } finally { - setIsLoading(false); - } - }, [fetchBalances, currentAddress, isUsingEmbeddedWallet]); - - return { - balances, - isLoading, - refetch, - }; -} diff --git a/src/hooks/useSwap.ts b/src/hooks/useSwap.ts deleted file mode 100644 index 20d72bd..0000000 --- a/src/hooks/useSwap.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { useState, useCallback, useEffect, useRef } from 'react'; -import { useContracts } from '../contexts/ContractsContext'; -import { useOnboarding } from '../contexts/OnboardingContext'; -import { waitForTxWithPhases } from '../utils/txUtils'; - -interface UseSwapProps { - fromAmount: string; - toAmount: string; - isDripping?: boolean; - fromTokenBalance?: bigint | null; -} - -interface UseSwapReturn { - // Exchange rate - exchangeRate: number | undefined; - isLoadingRate: boolean; - - // USD values - fromAmountUSD: number; - toAmountUSD: number; - - // Validation - canSwap: boolean; - - // Swap state - isSwapping: boolean; - swapPhase: 'sending' | 'mining'; - swapError: string | null; - - // Handlers - executeSwap: () => Promise; - dismissError: () => void; -} - -const GREGOCOIN_USD_PRICE = 10; - -export function useSwap({ fromAmount, toAmount, isDripping = false, fromTokenBalance = null }: UseSwapProps): UseSwapReturn { - // Pull from contexts - const { swap, isLoadingContracts, getExchangeRate } = useContracts(); - const { status: onboardingStatus, onboardingResult, isSwapPending, isDripPending } = useOnboarding(); - - // State for swap - const [isSwapping, setIsSwapping] = useState(false); - const [swapPhase, setSwapPhase] = useState<'sending' | 'mining'>('sending'); - const [swapError, setSwapError] = useState(null); - - // State for exchange rate - const [exchangeRate, setExchangeRate] = useState(undefined); - const [isLoadingRate, setIsLoadingRate] = useState(false); - const isFetchingRateRef = useRef(false); - - // Pre-populate exchange rate from onboarding result when available (only once) - const hasUsedOnboardingResultRef = useRef(false); - useEffect(() => { - if (onboardingResult && !hasUsedOnboardingResultRef.current) { - setExchangeRate(onboardingResult.exchangeRate); - hasUsedOnboardingResultRef.current = true; - } - }, [onboardingResult]); - - // Reset exchange rate when contracts are loading (e.g., network switch) - useEffect(() => { - if (isLoadingContracts) { - setExchangeRate(undefined); - setIsLoadingRate(false); - isFetchingRateRef.current = false; - } - }, [isLoadingContracts]); - - // Track previous isSwapping state to detect swap completion - const prevIsSwappingRef = useRef(isSwapping); - useEffect(() => { - const wasSwapping = prevIsSwappingRef.current; - const justFinishedSwapping = wasSwapping && !isSwapping; - - if (justFinishedSwapping && !swapError) { - // Swap just completed successfully - force immediate exchange rate refresh - isFetchingRateRef.current = false; // Allow new fetch - // The main fetch effect will pick this up on next render - } - - prevIsSwappingRef.current = isSwapping; - }, [isSwapping, swapError]); - - // Fetch exchange rate with auto-refresh every 10 seconds - useEffect(() => { - async function fetchExchangeRate() { - const isBusy = isLoadingContracts || isSwapping || isSwapPending || isDripping || isDripPending; - const isOnboardingInProgress = onboardingStatus !== 'completed' && onboardingStatus !== 'not_started'; - - if (isBusy || isOnboardingInProgress) { - setIsLoadingRate(false); - return; - } - - if (isFetchingRateRef.current) { - return; - } - - try { - isFetchingRateRef.current = true; - setIsLoadingRate(true); - - const rate = await getExchangeRate(); - setExchangeRate(rate); - } finally { - setIsLoadingRate(false); - - isFetchingRateRef.current = false; - } - } - - fetchExchangeRate(); - - // Set up interval for subsequent fetches - const intervalId = setInterval(() => { - fetchExchangeRate(); - }, 10000); - - return () => { - clearInterval(intervalId); - setIsLoadingRate(false); - isFetchingRateRef.current = false; - }; - }, [ - isLoadingContracts, - isSwapping, - isDripping, - isDripPending, - getExchangeRate, - onboardingStatus, - isSwapPending, - swapError, // Include to trigger refresh after swap completes - ]); - - // Calculate USD values (simplified - just based on amount) - const fromAmountUSD = fromAmount ? parseFloat(fromAmount) * GREGOCOIN_USD_PRICE : 0; - const toAmountUSD = toAmount ? parseFloat(toAmount) * GREGOCOIN_USD_PRICE : 0; - - const executeSwap = useCallback(async () => { - setSwapError(null); - - if (isLoadingContracts || !fromAmount || parseFloat(fromAmount) <= 0) { - setSwapError('Cannot perform swap: Missing data or invalid amount'); - return; - } - - // Check if FROM amount exceeds balance - if (fromTokenBalance !== null && fromTokenBalance !== undefined) { - const fromAmountBigInt = BigInt(Math.round(parseFloat(fromAmount))); - if (fromAmountBigInt > fromTokenBalance) { - setSwapError('Insufficient GregoCoin balance for swap'); - return; - } - } - - setIsSwapping(true); - setSwapPhase('sending'); - - try { - const sentTx = await swap(parseFloat(toAmount), parseFloat(fromAmount) * 1.1); - await waitForTxWithPhases(sentTx, setSwapPhase); - } catch (error) { - let errorMessage = 'Swap failed. Please try again.'; - - if (error instanceof Error) { - // Check for common error patterns and enhance messages - if (error.message.includes('Simulation failed')) { - errorMessage = error.message; - } else if (error.message.includes('User denied') || error.message.includes('rejected')) { - errorMessage = 'Transaction was rejected in wallet'; - } else if (error.message.includes('Insufficient') || error.message.includes('insufficient')) { - errorMessage = 'Insufficient GregoCoin balance for swap'; - } else { - errorMessage = error.message; - } - } - - setSwapError(errorMessage); - } finally { - setIsSwapping(false); - } - }, [isLoadingContracts, fromAmount, toAmount, swap, fromTokenBalance]); - - const dismissError = () => { - setSwapError(null); - }; - - // Calculate if swap can be executed - const canSwap = - !!fromAmount && - parseFloat(fromAmount) > 0 && - !isLoadingContracts && - onboardingStatus !== 'connecting_wallet' && - onboardingStatus !== 'registering_contracts' && - onboardingStatus !== 'simulating_queries'; - - return { - exchangeRate, - isLoadingRate, - fromAmountUSD, - toAmountUSD, - canSwap, - isSwapping, - swapPhase, - swapError, - executeSwap, - dismissError, - }; -} diff --git a/src/main.tsx b/src/main.tsx index c6d96a2..c8cb4b1 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,11 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { App } from './App.tsx'; -import { NetworkProvider } from './contexts/NetworkContext.tsx'; -import { WalletProvider } from './contexts/WalletContext.tsx'; -import { ContractsProvider } from './contexts/ContractsContext.tsx'; -import { OnboardingProvider } from './contexts/OnboardingContext.tsx'; +import { NetworkProvider } from './contexts/network/NetworkContext'; +import { WalletProvider } from './contexts/wallet/WalletContext'; +import { ContractsProvider } from './contexts/contracts/ContractsContext'; +import { SwapProvider } from './contexts/swap/SwapContext'; +import { OnboardingProvider } from './contexts/onboarding/OnboardingContext'; createRoot(document.getElementById('root')!).render( @@ -12,7 +13,9 @@ createRoot(document.getElementById('root')!).render( - + + + diff --git a/src/services/contractService.ts b/src/services/contractService.ts new file mode 100644 index 0000000..729463d --- /dev/null +++ b/src/services/contractService.ts @@ -0,0 +1,337 @@ +/** + * Contract Service + * Pure functions for contract-related operations + */ + +import type { Wallet } from '@aztec/aztec.js/wallet'; +import type { AztecNode } from '@aztec/aztec.js/node'; +import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import { AztecAddress as AztecAddressClass } from '@aztec/aztec.js/addresses'; +import { Fr } from '@aztec/aztec.js/fields'; +import { BatchCall, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts'; +import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee'; +import { SPONSORED_FPC_SALT } from '@aztec/constants'; +import type { TxReceipt } from '@aztec/stdlib/tx'; +import type { TokenContract } from '@aztec/noir-contracts.js/Token'; +import type { AMMContract } from '@aztec/noir-contracts.js/AMM'; +import type { ProofOfPasswordContract } from '../../contracts/target/ProofOfPassword'; +import { BigDecimal } from '../utils/bigDecimal'; +import type { NetworkConfig } from '../config/networks'; +import type { OnboardingResult } from '../contexts/onboarding/reducer'; + +/** + * Contracts returned after swap registration + */ +export interface SwapContracts { + gregoCoin: TokenContract; + gregoCoinPremium: TokenContract; + amm: AMMContract; +} + +/** + * Contracts returned after drip registration + */ +export interface DripContracts { + pop: ProofOfPasswordContract; +} + +/** + * Helper function to get SponsoredFPC contract data + */ +async function getSponsoredFPCData() { + const { SponsoredFPCContractArtifact } = await import('@aztec/noir-contracts.js/SponsoredFPC'); + const sponsoredFPCInstance = await getContractInstanceFromInstantiationParams(SponsoredFPCContractArtifact, { + salt: new Fr(SPONSORED_FPC_SALT), + }); + return { artifact: SponsoredFPCContractArtifact, instance: sponsoredFPCInstance }; +} + +/** + * Registers contracts needed for the swap flow + * Returns the contract instances after registration + * Skips registration for contracts that are already registered + */ +export async function registerSwapContracts( + wallet: Wallet, + node: AztecNode, + network: NetworkConfig +): Promise { + const gregoCoinAddress = AztecAddressClass.fromString(network.contracts.gregoCoin); + const gregoCoinPremiumAddress = AztecAddressClass.fromString(network.contracts.gregoCoinPremium); + const liquidityTokenAddress = AztecAddressClass.fromString(network.contracts.liquidityToken); + const ammAddress = AztecAddressClass.fromString(network.contracts.amm); + const deployerAddress = AztecAddressClass.fromString(network.deployer.address); + const contractSalt = Fr.fromString(network.contracts.salt); + + // Import contract artifacts + const { TokenContract, TokenContractArtifact } = await import('@aztec/noir-contracts.js/Token'); + const { AMMContract, AMMContractArtifact } = await import('@aztec/noir-contracts.js/AMM'); + + // Check which contracts are already registered + const [ammMetadata, gregoCoinMetadata, gregoCoinPremiumMetadata] = await wallet.batch([ + { name: 'getContractMetadata', args: [ammAddress] }, + { name: 'getContractMetadata', args: [gregoCoinAddress] }, + { name: 'getContractMetadata', args: [gregoCoinPremiumAddress] }, + ]); + + // Reconstruct contract instances for unregistered contracts + const [ammInstance, gregoCoinInstance, gregoCoinPremiumInstance] = await Promise.all([ + !ammMetadata.result.instance + ? getContractInstanceFromInstantiationParams(AMMContractArtifact, { + salt: contractSalt, + deployer: deployerAddress, + constructorArgs: [gregoCoinAddress, gregoCoinPremiumAddress, liquidityTokenAddress], + }) + : null, + !gregoCoinMetadata.result.instance + ? getContractInstanceFromInstantiationParams(TokenContractArtifact, { + salt: contractSalt, + deployer: deployerAddress, + constructorArgs: [deployerAddress, 'GregoCoin', 'GRG', 18], + }) + : null, + !gregoCoinPremiumMetadata.result.instance + ? getContractInstanceFromInstantiationParams(TokenContractArtifact, { + salt: contractSalt, + deployer: deployerAddress, + constructorArgs: [deployerAddress, 'GregoCoinPremium', 'GRGP', 18], + }) + : null, + ]); + + // Build registration batch for unregistered contracts only + const registrationBatch: { name: 'registerContract'; args: [any, any, any] }[] = []; + + if (ammInstance) { + registrationBatch.push({ name: 'registerContract', args: [ammInstance, AMMContractArtifact, undefined] }); + } + if (gregoCoinInstance) { + registrationBatch.push({ name: 'registerContract', args: [gregoCoinInstance, TokenContractArtifact, undefined] }); + } + if (gregoCoinPremiumInstance) { + // gregoCoinPremium shares the same artifact as gregoCoin, so we can omit it + registrationBatch.push({ name: 'registerContract', args: [gregoCoinPremiumInstance, undefined, undefined] }); + } + + // Only call batch if there are contracts to register + if (registrationBatch.length > 0) { + await wallet.batch(registrationBatch); + } + + // Instantiate the contracts + const gregoCoin = TokenContract.at(gregoCoinAddress, wallet); + const gregoCoinPremium = TokenContract.at(gregoCoinPremiumAddress, wallet); + const amm = AMMContract.at(ammAddress, wallet); + + return { gregoCoin, gregoCoinPremium, amm }; +} + +/** + * Registers contracts needed for the drip flow + * Returns the contract instances after registration + * Skips registration for contracts that are already registered + */ +export async function registerDripContracts( + wallet: Wallet, + node: AztecNode, + network: NetworkConfig +): Promise { + const popAddress = AztecAddressClass.fromString(network.contracts.pop); + + const { ProofOfPasswordContract, ProofOfPasswordContractArtifact } = await import( + '../../contracts/target/ProofOfPassword' + ); + + const { instance: sponsoredFPCInstance, artifact: SponsoredFPCContractArtifact } = await getSponsoredFPCData(); + + // Check which contracts are already registered + const [popMetadata, sponsoredFPCMetadata] = await wallet.batch([ + { name: 'getContractMetadata', args: [popAddress] }, + { name: 'getContractMetadata', args: [sponsoredFPCInstance.address] }, + ]); + + // Build registration batch for unregistered contracts only + const registrationBatch: { name: 'registerContract'; args: [any, any, any] }[] = []; + + if (!popMetadata.result.instance) { + const instance = await node.getContract(popAddress); + registrationBatch.push({ name: 'registerContract', args: [instance, ProofOfPasswordContractArtifact, undefined] }); + } + if (!sponsoredFPCMetadata.result.instance) { + registrationBatch.push({ + name: 'registerContract', + args: [sponsoredFPCInstance, SponsoredFPCContractArtifact, undefined], + }); + } + + // Only call batch if there are contracts to register + if (registrationBatch.length > 0) { + await wallet.batch(registrationBatch); + } + + // Instantiate the ProofOfPassword contract + const pop = ProofOfPasswordContract.at(popAddress, wallet); + + return { pop }; +} + +/** + * Gets the current exchange rate from the AMM + */ +export async function getExchangeRate( + wallet: Wallet, + contracts: SwapContracts, + fromAddress: AztecAddress +): Promise { + const { gregoCoin, gregoCoinPremium, amm } = contracts; + + const batchCall = new BatchCall(wallet, [ + gregoCoin.methods.balance_of_public(amm.address), + gregoCoinPremium.methods.balance_of_public(amm.address), + ]); + + const [token0Reserve, token1Reserve] = await batchCall.simulate({ from: fromAddress }); + return parseFloat(new BigDecimal(token1Reserve).divide(new BigDecimal(token0Reserve)).toString()); +} + +/** + * Fetches balances for a given address + */ +export async function fetchBalances( + wallet: Wallet, + contracts: SwapContracts, + address: AztecAddress +): Promise<[bigint, bigint]> { + const { gregoCoin, gregoCoinPremium } = contracts; + + const batchCall = new BatchCall(wallet, [ + gregoCoin.methods.balance_of_private(address), + gregoCoinPremium.methods.balance_of_private(address), + ]); + + const [gcBalance, gcpBalance] = await batchCall.simulate({ from: address }); + return [gcBalance, gcpBalance]; +} + +/** + * Simulates onboarding queries to get exchange rate and balances + * This triggers wallet approval for these queries, so future reads are seamless + */ +export async function simulateOnboardingQueries( + wallet: Wallet, + contracts: SwapContracts, + address: AztecAddress +): Promise { + const { gregoCoin, gregoCoinPremium, amm } = contracts; + + // Create a batched simulation that includes: + // 1. Exchange rate data (public balances of AMM) + // 2. User's private balances + const batchCall = new BatchCall(wallet, [ + gregoCoin.methods.balance_of_public(amm.address), + gregoCoinPremium.methods.balance_of_public(amm.address), + gregoCoin.methods.balance_of_private(address), + gregoCoinPremium.methods.balance_of_private(address), + ]); + + const [token0Reserve, token1Reserve, gcBalance, gcpBalance] = await batchCall.simulate({ from: address }); + const exchangeRate = parseFloat(new BigDecimal(token1Reserve).divide(new BigDecimal(token0Reserve)).toString()); + + return { + exchangeRate, + balances: { + gregoCoin: gcBalance, + gregoCoinPremium: gcpBalance, + }, + }; +} + +/** + * Executes a token swap through the AMM + */ +export async function executeSwap( + contracts: SwapContracts, + fromAddress: AztecAddress, + amountOut: number, + amountInMax: number +): Promise { + const { gregoCoin, gregoCoinPremium, amm } = contracts; + + const authwitNonce = Fr.random(); + return amm.methods + .swap_tokens_for_exact_tokens( + gregoCoin.address, + gregoCoinPremium.address, + BigInt(Math.round(amountOut)), + BigInt(Math.round(amountInMax)), + authwitNonce + ) + .send({ from: fromAddress }); +} + +/** + * Parses a swap error into a user-friendly message + */ +export function parseSwapError(error: unknown): string { + if (!(error instanceof Error)) { + return 'Swap failed. Please try again.'; + } + + const message = error.message; + + if (message.includes('Simulation failed')) { + return message; + } + if (message.includes('User denied') || message.includes('rejected')) { + return 'Transaction was rejected in wallet'; + } + if (message.includes('Insufficient') || message.includes('insufficient')) { + return 'Insufficient GregoCoin balance for swap'; + } + + return message; +} + +/** + * Executes a drip (token claim) transaction + */ +export async function executeDrip( + pop: ProofOfPasswordContract, + password: string, + recipient: AztecAddress +): Promise { + const { instance: sponsoredFPCInstance } = await getSponsoredFPCData(); + + return pop.methods.check_password_and_mint(password, recipient).send({ + from: AztecAddressClass.ZERO, + fee: { + paymentMethod: new SponsoredFeePaymentMethod(sponsoredFPCInstance.address), + }, + }); +} + +/** + * Parses a drip error into a user-friendly message + */ +export function parseDripError(error: unknown): string { + if (!(error instanceof Error)) { + return 'Failed to claim GregoCoin. Please try again.'; + } + + const message = error.message; + + if (message.includes('Simulation failed')) { + return message; + } + if (message.includes('User denied') || message.includes('rejected')) { + return 'Transaction was rejected in wallet'; + } + if (message.includes('password') || message.includes('Password')) { + return 'Invalid password. Please try again.'; + } + if (message.includes('already claimed') || message.includes('Already claimed')) { + return 'You have already claimed your GregoCoin tokens.'; + } + + return message; +} diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 0000000..40bbcaa --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1,7 @@ +/** + * Services Index + * Re-exports all service functions + */ + +export * from './walletService'; +export * from './contractService'; diff --git a/src/services/walletService.ts b/src/services/walletService.ts new file mode 100644 index 0000000..4021906 --- /dev/null +++ b/src/services/walletService.ts @@ -0,0 +1,88 @@ +/** + * Wallet Service + * Pure functions for wallet-related operations + */ + +import { createAztecNodeClient, type AztecNode } from '@aztec/aztec.js/node'; +import type { Wallet } from '@aztec/aztec.js/wallet'; +import type { ChainInfo } from '@aztec/aztec.js/account'; +import { Fr } from '@aztec/aztec.js/fields'; +import { + WalletManager, + type WalletProvider, + type PendingConnection, + type DiscoverySession, +} from '@aztec/wallet-sdk/manager'; +import { EmbeddedWallet } from '../embedded_wallet'; +import type { NetworkConfig } from '../config/networks'; + +const APP_ID = 'gregoswap'; + +/** + * Creates an Aztec node client for the given node URL + */ +export function createNodeClient(nodeUrl: string): AztecNode { + return createAztecNodeClient(nodeUrl); +} + +/** + * Creates an embedded wallet for use without an external wallet + */ +export async function createEmbeddedWallet(node: AztecNode): Promise { + return EmbeddedWallet.create(node); +} + +/** + * Gets the chain info from a network configuration + */ +export function getChainInfo(network: NetworkConfig): ChainInfo { + return { + chainId: Fr.fromString(network.chainId), + version: Fr.fromString(network.rollupVersion), + }; +} + +/** + * Starts wallet discovery process + * Returns a DiscoverySession that yields wallets as they are discovered + */ +export function discoverWallets(chainInfo: ChainInfo, timeout?: number): DiscoverySession { + const manager = WalletManager.configure({ extensions: { enabled: true } }); + return manager.getAvailableWallets({ + chainInfo, + appId: APP_ID, + timeout, + }); +} + +/** + * Initiates a secure connection with a wallet provider + * Returns a PendingConnection for emoji verification + */ +export async function initiateConnection(provider: WalletProvider): Promise { + return provider.establishSecureChannel(APP_ID); +} + +/** + * Confirms a pending connection after emoji verification + * Returns the connected wallet + */ +export async function confirmConnection(pendingConnection: PendingConnection): Promise { + return pendingConnection.confirm(); +} + +/** + * Cancels a pending connection + */ +export function cancelConnection(pendingConnection: PendingConnection): void { + pendingConnection.cancel(); +} + +/** + * Disconnects from a wallet provider + */ +export async function disconnectProvider(provider: WalletProvider): Promise { + if (provider.disconnect) { + await provider.disconnect(); + } +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..6641a45 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,10 @@ +/** + * Token balances + */ +export interface Balances { + gregoCoin: bigint | null; + gregoCoinPremium: bigint | null; +} + +export const GREGOCOIN_USD_PRICE = 10; +export const EXCHANGE_RATE_POLL_INTERVAL_MS = 10000; diff --git a/src/utils/txUtils.ts b/src/utils/txUtils.ts deleted file mode 100644 index 54c2cd7..0000000 --- a/src/utils/txUtils.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { SentTx } from '@aztec/aztec.js/contracts'; -import { TxStatus } from '@aztec/stdlib/tx'; - -/** - * Waits for a transaction to be sent to the node and updates the phase callback. - * This utility polls the transaction receipt to determine if it's been sent to the node - * (status = PENDING) or if it's been mined (status = SUCCESS or other final states). - * - * @param sentTx - The SentTx object returned from calling .send() - * @param onPhaseChange - Callback to notify phase changes ('sending' | 'mining') - * @param pollInterval - How often to poll for receipt in milliseconds (default: 500ms) - * @returns Promise that resolves when the transaction is mined - */ -export async function waitForTxWithPhases( - sentTx: SentTx, - onPhaseChange?: (phase: 'sending' | 'mining') => void, - pollInterval: number = 1000, -): Promise { - // Start in sending phase - onPhaseChange?.('sending'); - - // Poll for receipt until we get one with PENDING status or better - let hasSwitchedToMining = false; - - const checkReceipt = async (): Promise => { - try { - const receipt = await sentTx.getReceipt(); - - // If we have a receipt with PENDING status, the tx has been sent to the node - if (receipt.status === TxStatus.PENDING && !hasSwitchedToMining) { - hasSwitchedToMining = true; - onPhaseChange?.('mining'); - } - - // If status is final (not PENDING), we're done - if (receipt.status !== TxStatus.PENDING) { - return true; - } - - return false; - } catch (error) { - if (error.message.includes('failed') || error.message.includes('Error')) { - throw error; - } - // Receipt not available yet, keep polling - return false; - } - }; - - // Poll until transaction is mined - while (!(await checkReceipt())) { - await new Promise(resolve => setTimeout(resolve, pollInterval)); - } - - // Finally, call wait() to get the full receipt and handle any errors - await sentTx.wait(); -} diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..944cd68 --- /dev/null +++ b/vercel.json @@ -0,0 +1,17 @@ +{ + "headers": [ + { + "source": "/(.*)", + "headers": [ + { + "key": "Cross-Origin-Opener-Policy", + "value": "same-origin" + }, + { + "key": "Cross-Origin-Embedder-Policy", + "value": "require-corp" + } + ] + } + ] +} diff --git a/yarn.lock b/yarn.lock index afb2802..39d64bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -95,590 +95,603 @@ __metadata: linkType: hard "@aws-sdk/client-s3@npm:^3.892.0": - version: 3.967.0 - resolution: "@aws-sdk/client-s3@npm:3.967.0" + version: 3.981.0 + resolution: "@aws-sdk/client-s3@npm:3.981.0" dependencies: "@aws-crypto/sha1-browser": "npm:5.2.0" "@aws-crypto/sha256-browser": "npm:5.2.0" "@aws-crypto/sha256-js": "npm:5.2.0" - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/credential-provider-node": "npm:3.967.0" - "@aws-sdk/middleware-bucket-endpoint": "npm:3.966.0" - "@aws-sdk/middleware-expect-continue": "npm:3.965.0" - "@aws-sdk/middleware-flexible-checksums": "npm:3.967.0" - "@aws-sdk/middleware-host-header": "npm:3.965.0" - "@aws-sdk/middleware-location-constraint": "npm:3.965.0" - "@aws-sdk/middleware-logger": "npm:3.965.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.965.0" - "@aws-sdk/middleware-sdk-s3": "npm:3.967.0" - "@aws-sdk/middleware-ssec": "npm:3.965.0" - "@aws-sdk/middleware-user-agent": "npm:3.967.0" - "@aws-sdk/region-config-resolver": "npm:3.965.0" - "@aws-sdk/signature-v4-multi-region": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/util-endpoints": "npm:3.965.0" - "@aws-sdk/util-user-agent-browser": "npm:3.965.0" - "@aws-sdk/util-user-agent-node": "npm:3.967.0" - "@smithy/config-resolver": "npm:^4.4.5" - "@smithy/core": "npm:^3.20.2" - "@smithy/eventstream-serde-browser": "npm:^4.2.7" - "@smithy/eventstream-serde-config-resolver": "npm:^4.3.7" - "@smithy/eventstream-serde-node": "npm:^4.2.7" - "@smithy/fetch-http-handler": "npm:^5.3.8" - "@smithy/hash-blob-browser": "npm:^4.2.8" - "@smithy/hash-node": "npm:^4.2.7" - "@smithy/hash-stream-node": "npm:^4.2.7" - "@smithy/invalid-dependency": "npm:^4.2.7" - "@smithy/md5-js": "npm:^4.2.7" - "@smithy/middleware-content-length": "npm:^4.2.7" - "@smithy/middleware-endpoint": "npm:^4.4.3" - "@smithy/middleware-retry": "npm:^4.4.19" - "@smithy/middleware-serde": "npm:^4.2.8" - "@smithy/middleware-stack": "npm:^4.2.7" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/node-http-handler": "npm:^4.4.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/smithy-client": "npm:^4.10.4" - "@smithy/types": "npm:^4.11.0" - "@smithy/url-parser": "npm:^4.2.7" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/credential-provider-node": "npm:^3.972.4" + "@aws-sdk/middleware-bucket-endpoint": "npm:^3.972.3" + "@aws-sdk/middleware-expect-continue": "npm:^3.972.3" + "@aws-sdk/middleware-flexible-checksums": "npm:^3.972.3" + "@aws-sdk/middleware-host-header": "npm:^3.972.3" + "@aws-sdk/middleware-location-constraint": "npm:^3.972.3" + "@aws-sdk/middleware-logger": "npm:^3.972.3" + "@aws-sdk/middleware-recursion-detection": "npm:^3.972.3" + "@aws-sdk/middleware-sdk-s3": "npm:^3.972.5" + "@aws-sdk/middleware-ssec": "npm:^3.972.3" + "@aws-sdk/middleware-user-agent": "npm:^3.972.5" + "@aws-sdk/region-config-resolver": "npm:^3.972.3" + "@aws-sdk/signature-v4-multi-region": "npm:3.981.0" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/util-endpoints": "npm:3.981.0" + "@aws-sdk/util-user-agent-browser": "npm:^3.972.3" + "@aws-sdk/util-user-agent-node": "npm:^3.972.3" + "@smithy/config-resolver": "npm:^4.4.6" + "@smithy/core": "npm:^3.22.0" + "@smithy/eventstream-serde-browser": "npm:^4.2.8" + "@smithy/eventstream-serde-config-resolver": "npm:^4.3.8" + "@smithy/eventstream-serde-node": "npm:^4.2.8" + "@smithy/fetch-http-handler": "npm:^5.3.9" + "@smithy/hash-blob-browser": "npm:^4.2.9" + "@smithy/hash-node": "npm:^4.2.8" + "@smithy/hash-stream-node": "npm:^4.2.8" + "@smithy/invalid-dependency": "npm:^4.2.8" + "@smithy/md5-js": "npm:^4.2.8" + "@smithy/middleware-content-length": "npm:^4.2.8" + "@smithy/middleware-endpoint": "npm:^4.4.12" + "@smithy/middleware-retry": "npm:^4.4.29" + "@smithy/middleware-serde": "npm:^4.2.9" + "@smithy/middleware-stack": "npm:^4.2.8" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/node-http-handler": "npm:^4.4.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/smithy-client": "npm:^4.11.1" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" "@smithy/util-base64": "npm:^4.3.0" "@smithy/util-body-length-browser": "npm:^4.2.0" "@smithy/util-body-length-node": "npm:^4.2.1" - "@smithy/util-defaults-mode-browser": "npm:^4.3.18" - "@smithy/util-defaults-mode-node": "npm:^4.2.21" - "@smithy/util-endpoints": "npm:^3.2.7" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-retry": "npm:^4.2.7" - "@smithy/util-stream": "npm:^4.5.8" + "@smithy/util-defaults-mode-browser": "npm:^4.3.28" + "@smithy/util-defaults-mode-node": "npm:^4.2.31" + "@smithy/util-endpoints": "npm:^3.2.8" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-retry": "npm:^4.2.8" + "@smithy/util-stream": "npm:^4.5.10" "@smithy/util-utf8": "npm:^4.2.0" - "@smithy/util-waiter": "npm:^4.2.7" + "@smithy/util-waiter": "npm:^4.2.8" tslib: "npm:^2.6.2" - checksum: 10c0/eaf3dddee5885a84dbf76a45a8ba6c71d64e422e1bb5a63fbc7d9d8a80994d2c57b80f1633165c4f6c882729d6300c1811aea081796a50ec82294038704c3c37 + checksum: 10c0/1f3f9b650b2b70ceafe0ec2b3aaf2df8e721639bcf25b7f6f549166027dd69176dd6548ee66b393d46725f7a1de0a735a31c2674d4f9239f20854661e7998c2f languageName: node linkType: hard -"@aws-sdk/client-sso@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/client-sso@npm:3.967.0" +"@aws-sdk/client-sso@npm:3.980.0": + version: 3.980.0 + resolution: "@aws-sdk/client-sso@npm:3.980.0" dependencies: "@aws-crypto/sha256-browser": "npm:5.2.0" "@aws-crypto/sha256-js": "npm:5.2.0" - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/middleware-host-header": "npm:3.965.0" - "@aws-sdk/middleware-logger": "npm:3.965.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.965.0" - "@aws-sdk/middleware-user-agent": "npm:3.967.0" - "@aws-sdk/region-config-resolver": "npm:3.965.0" - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/util-endpoints": "npm:3.965.0" - "@aws-sdk/util-user-agent-browser": "npm:3.965.0" - "@aws-sdk/util-user-agent-node": "npm:3.967.0" - "@smithy/config-resolver": "npm:^4.4.5" - "@smithy/core": "npm:^3.20.2" - "@smithy/fetch-http-handler": "npm:^5.3.8" - "@smithy/hash-node": "npm:^4.2.7" - "@smithy/invalid-dependency": "npm:^4.2.7" - "@smithy/middleware-content-length": "npm:^4.2.7" - "@smithy/middleware-endpoint": "npm:^4.4.3" - "@smithy/middleware-retry": "npm:^4.4.19" - "@smithy/middleware-serde": "npm:^4.2.8" - "@smithy/middleware-stack": "npm:^4.2.7" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/node-http-handler": "npm:^4.4.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/smithy-client": "npm:^4.10.4" - "@smithy/types": "npm:^4.11.0" - "@smithy/url-parser": "npm:^4.2.7" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/middleware-host-header": "npm:^3.972.3" + "@aws-sdk/middleware-logger": "npm:^3.972.3" + "@aws-sdk/middleware-recursion-detection": "npm:^3.972.3" + "@aws-sdk/middleware-user-agent": "npm:^3.972.5" + "@aws-sdk/region-config-resolver": "npm:^3.972.3" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/util-endpoints": "npm:3.980.0" + "@aws-sdk/util-user-agent-browser": "npm:^3.972.3" + "@aws-sdk/util-user-agent-node": "npm:^3.972.3" + "@smithy/config-resolver": "npm:^4.4.6" + "@smithy/core": "npm:^3.22.0" + "@smithy/fetch-http-handler": "npm:^5.3.9" + "@smithy/hash-node": "npm:^4.2.8" + "@smithy/invalid-dependency": "npm:^4.2.8" + "@smithy/middleware-content-length": "npm:^4.2.8" + "@smithy/middleware-endpoint": "npm:^4.4.12" + "@smithy/middleware-retry": "npm:^4.4.29" + "@smithy/middleware-serde": "npm:^4.2.9" + "@smithy/middleware-stack": "npm:^4.2.8" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/node-http-handler": "npm:^4.4.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/smithy-client": "npm:^4.11.1" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" "@smithy/util-base64": "npm:^4.3.0" "@smithy/util-body-length-browser": "npm:^4.2.0" "@smithy/util-body-length-node": "npm:^4.2.1" - "@smithy/util-defaults-mode-browser": "npm:^4.3.18" - "@smithy/util-defaults-mode-node": "npm:^4.2.21" - "@smithy/util-endpoints": "npm:^3.2.7" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-retry": "npm:^4.2.7" + "@smithy/util-defaults-mode-browser": "npm:^4.3.28" + "@smithy/util-defaults-mode-node": "npm:^4.2.31" + "@smithy/util-endpoints": "npm:^3.2.8" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-retry": "npm:^4.2.8" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/6f8b7acf237c71e52f911724372819d8c990bb09a6162c6b6eaab8be4ae1cd33419451991beaa6a4e1734d1d49a79cd8f432b4561600b321d7cffda4cf657eca + checksum: 10c0/870a684d7772971d482361e9ed94d2cd86ffa0d47f572e2f01ba44e7f5954cd91b1e832961deadcb5afaf1fee6f26cce755a3cc5299f3336e1f26b1d652aa2c1 languageName: node linkType: hard -"@aws-sdk/core@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/core@npm:3.967.0" +"@aws-sdk/core@npm:^3.973.5": + version: 3.973.5 + resolution: "@aws-sdk/core@npm:3.973.5" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/xml-builder": "npm:3.965.0" - "@smithy/core": "npm:^3.20.2" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/signature-v4": "npm:^5.3.7" - "@smithy/smithy-client": "npm:^4.10.4" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/xml-builder": "npm:^3.972.2" + "@smithy/core": "npm:^3.22.0" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/signature-v4": "npm:^5.3.8" + "@smithy/smithy-client": "npm:^4.11.1" + "@smithy/types": "npm:^4.12.0" "@smithy/util-base64": "npm:^4.3.0" - "@smithy/util-middleware": "npm:^4.2.7" + "@smithy/util-middleware": "npm:^4.2.8" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/a5569c9c72b55c71fea8db60c10bd9a2756fad4dc7d009a17d2c7e54c35559cb1982684d2aa3bb19eabbeb4006356b90d319c3d81be7e72fd2cf5621f702fc47 + checksum: 10c0/d885f0cb18185a4958df724bc914b0d2ee18f4ed16fe4f250dc85b90d87c32251513b49806007a46f01f3220a7abe75990062f8e31c1e466e5e7a7e5d41dcae5 languageName: node linkType: hard -"@aws-sdk/crc64-nvme@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/crc64-nvme@npm:3.965.0" +"@aws-sdk/crc64-nvme@npm:3.972.0": + version: 3.972.0 + resolution: "@aws-sdk/crc64-nvme@npm:3.972.0" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/a819970f729e56562a8badd5f0aba5bfaf4fa038c6733ddf51ceaf5fe3430264a6ceafce87580495bacf24bbd9950425517cb509581bfcd5fd23e20a88182c79 + checksum: 10c0/c756b934baa51a7582f5efc8a935b3ce3403f0574451ffa8769e2cecac4cd5f08e0c6f0d5cb85c3e3bcf34cbc475c10e9d8302265a5b1fbb37424b5ac2580a6f languageName: node linkType: hard -"@aws-sdk/credential-provider-env@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.967.0" +"@aws-sdk/credential-provider-env@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/credential-provider-env@npm:3.972.3" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/5aeac0ccf17a457116a06fdda9cb7f95065f6dd7baeb4aed234d87c1d809017f0f945f9bcfdaaf4e5bfd58677343450c87ae07336a01d3df05debcf605c9fbdc + checksum: 10c0/f6eaa47673282fad838fc22d93ce2b81365955c689750b2a346ed49b646ec1f03424c22da6cbdd5673378da854f5de02ef5d3f3bee6a080f1656d79a3b0b0b4f languageName: node linkType: hard -"@aws-sdk/credential-provider-http@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-http@npm:3.967.0" +"@aws-sdk/credential-provider-http@npm:^3.972.5": + version: 3.972.5 + resolution: "@aws-sdk/credential-provider-http@npm:3.972.5" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/fetch-http-handler": "npm:^5.3.8" - "@smithy/node-http-handler": "npm:^4.4.7" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/smithy-client": "npm:^4.10.4" - "@smithy/types": "npm:^4.11.0" - "@smithy/util-stream": "npm:^4.5.8" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/fetch-http-handler": "npm:^5.3.9" + "@smithy/node-http-handler": "npm:^4.4.8" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/smithy-client": "npm:^4.11.1" + "@smithy/types": "npm:^4.12.0" + "@smithy/util-stream": "npm:^4.5.10" tslib: "npm:^2.6.2" - checksum: 10c0/f94e588109ce58f4e3d50755265ef0cd5f27c3232242e900d145f5b823401d5c8c4dc42ca9253e09412041b2c98324cfec2597b6ab0c3593645890aed39e75bd - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-ini@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.967.0" - dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/credential-provider-env": "npm:3.967.0" - "@aws-sdk/credential-provider-http": "npm:3.967.0" - "@aws-sdk/credential-provider-login": "npm:3.967.0" - "@aws-sdk/credential-provider-process": "npm:3.967.0" - "@aws-sdk/credential-provider-sso": "npm:3.967.0" - "@aws-sdk/credential-provider-web-identity": "npm:3.967.0" - "@aws-sdk/nested-clients": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/credential-provider-imds": "npm:^4.2.7" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + checksum: 10c0/cd1302286ad7e2a403c4a8217999af46ff3d00442a1392e7312acb2cf544154edfb4f3d1c9f263a6c76fb30f4d95d36dacf2881309cadbbd703cdea2ca9d26c9 + languageName: node + linkType: hard + +"@aws-sdk/credential-provider-ini@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/credential-provider-ini@npm:3.972.3" + dependencies: + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/credential-provider-env": "npm:^3.972.3" + "@aws-sdk/credential-provider-http": "npm:^3.972.5" + "@aws-sdk/credential-provider-login": "npm:^3.972.3" + "@aws-sdk/credential-provider-process": "npm:^3.972.3" + "@aws-sdk/credential-provider-sso": "npm:^3.972.3" + "@aws-sdk/credential-provider-web-identity": "npm:^3.972.3" + "@aws-sdk/nested-clients": "npm:3.980.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/credential-provider-imds": "npm:^4.2.8" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/39d2531fc4d9f2513bc961701b52602eb0f96aa45f2c84f55696bdb8e4635e1253aa258112e0fd3aca0a18c76acfc6842d2e8c1b08e9ac25a4b7ee9debd1e090 + checksum: 10c0/6a6bae412805829756afbad4250265c7bdc1c11fc24cd1892bc0cfb58c8178edfbe233e16bcf40fb38e772fcf76b5089fa4e46170609007d9ed03e7ca45f36b2 languageName: node linkType: hard -"@aws-sdk/credential-provider-login@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-login@npm:3.967.0" +"@aws-sdk/credential-provider-login@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/credential-provider-login@npm:3.972.3" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/nested-clients": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/nested-clients": "npm:3.980.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/6a996ac5dd12bf067528b4c36a35888803fbf89d3d9350af0613506aee3fda48f2a56dd0b3852d18a5b80f9d5a57b0d0dedbe5b7113a6225878646563fcb7c23 + checksum: 10c0/79d41f8437ffcb6a98e262ebd2a635848acec8c4c1f945b217a773e4352ef38a61e41f64481edab303ab27d8bb089d040295eba288e366e34237262aea7469cc languageName: node linkType: hard -"@aws-sdk/credential-provider-node@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.967.0" +"@aws-sdk/credential-provider-node@npm:^3.972.4": + version: 3.972.4 + resolution: "@aws-sdk/credential-provider-node@npm:3.972.4" dependencies: - "@aws-sdk/credential-provider-env": "npm:3.967.0" - "@aws-sdk/credential-provider-http": "npm:3.967.0" - "@aws-sdk/credential-provider-ini": "npm:3.967.0" - "@aws-sdk/credential-provider-process": "npm:3.967.0" - "@aws-sdk/credential-provider-sso": "npm:3.967.0" - "@aws-sdk/credential-provider-web-identity": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/credential-provider-imds": "npm:^4.2.7" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/credential-provider-env": "npm:^3.972.3" + "@aws-sdk/credential-provider-http": "npm:^3.972.5" + "@aws-sdk/credential-provider-ini": "npm:^3.972.3" + "@aws-sdk/credential-provider-process": "npm:^3.972.3" + "@aws-sdk/credential-provider-sso": "npm:^3.972.3" + "@aws-sdk/credential-provider-web-identity": "npm:^3.972.3" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/credential-provider-imds": "npm:^4.2.8" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/b9f613833ca295564253a10cd9c7b5ecb2c2c27d431ac7bbc1c7e6a0cf5c1878fd2f9ab4af203abb80018f8f622728d094ed341994075768766aff525fc6e1f6 + checksum: 10c0/5646e02bff929514aa255547868912df454419e39219ef4a1977ba68163554db5ce34b7b3dbed5f4f9856eac4387dcc9e687b5f8f21a4559aaf07b77b25cbb1e languageName: node linkType: hard -"@aws-sdk/credential-provider-process@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.967.0" +"@aws-sdk/credential-provider-process@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/credential-provider-process@npm:3.972.3" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/3c9f1ee475b09bfd0eb6d7077d1006e9130cd6f7f19d0d92544b39faaca5ceb9169a87992fb833bc53cee060a3852d3529f9fcd2e4c4595e20f7e46c9fb29f53 + checksum: 10c0/e8b8d502d879228f05b1abb9f372fa7645ed64d66385ad0771c621d0a374a4b0d54b8bb9657f073945bebfd42a732cf5b621bb2ac0f476a68143027809e6fc2d languageName: node linkType: hard -"@aws-sdk/credential-provider-sso@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.967.0" +"@aws-sdk/credential-provider-sso@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/credential-provider-sso@npm:3.972.3" dependencies: - "@aws-sdk/client-sso": "npm:3.967.0" - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/token-providers": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/client-sso": "npm:3.980.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/token-providers": "npm:3.980.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/5bfa48799eb18cd214922c0261e8c7a7ef027dec9313dd62e43efa95b7ab58391f23cd291f8bd51c5d3476993eb9125f64251f6f6fd52bdc38d69e5d54575c15 + checksum: 10c0/0fac73cc425afea70b8237b12f561dcc7c9991b700c051fa74a8d438ffbc9bbfe255fd66fc40bf646d8e87092f59179f439de5106d9c1d8eef19577e64091272 languageName: node linkType: hard -"@aws-sdk/credential-provider-web-identity@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.967.0" +"@aws-sdk/credential-provider-web-identity@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/credential-provider-web-identity@npm:3.972.3" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/nested-clients": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/nested-clients": "npm:3.980.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/d4b0ee221fe333f31735df5b45e240915fa18deced6e97f87e5282a77c708b478bba6b0666123deb36bbe2836129390494b696215e2637ad65b46bbeb10f03db + checksum: 10c0/5e8661ccd91a6452c357afe6c62d8ea74df71bccae71e7f64fcdf2c9e70331033f414f4a435fdd163015963d223fafc90125e85b20e29aa213b0dee0600b8db9 languageName: node linkType: hard -"@aws-sdk/middleware-bucket-endpoint@npm:3.966.0": - version: 3.966.0 - resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.966.0" +"@aws-sdk/middleware-bucket-endpoint@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/util-arn-parser": "npm:3.966.0" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/util-arn-parser": "npm:^3.972.2" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" "@smithy/util-config-provider": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/75d50814e3fbf5ad6058bffbfe3291897b74cfe5bbcb6267ad1f027d1b13f8550457370082b9392c784d7694bdc39dff3fcbf7bd6b0f411cbd70e116f36b5a2f + checksum: 10c0/391c8f6d514c41543c6a66578ce6d7d29c9cf8677d9a4d07bc0cae27418fb47b65e8104a7a4f9ac2bc3d6ae2ce73dca3ed44fd7fbafb4bcb3cb06858bcae8230 languageName: node linkType: hard -"@aws-sdk/middleware-expect-continue@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/middleware-expect-continue@npm:3.965.0" +"@aws-sdk/middleware-expect-continue@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-expect-continue@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/917488832313388f58a52edcc6d2767a30450d2d8bc40ec6c1abf3ecc8364e251f0978b8d4b2c558e3dc729ac91822e750afe86db52638b7707a470c78970d16 + checksum: 10c0/69bcb15de22c3895df744d85eb668238fb7a307975b4e236c6c19f41f3c2f07a036de06db637abd8accbfadf06c557d3578ad71ac18ef71a3d52091f8ade5b87 languageName: node linkType: hard -"@aws-sdk/middleware-flexible-checksums@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.967.0" +"@aws-sdk/middleware-flexible-checksums@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.972.3" dependencies: "@aws-crypto/crc32": "npm:5.2.0" "@aws-crypto/crc32c": "npm:5.2.0" "@aws-crypto/util": "npm:5.2.0" - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/crc64-nvme": "npm:3.965.0" - "@aws-sdk/types": "npm:3.965.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/crc64-nvme": "npm:3.972.0" + "@aws-sdk/types": "npm:^3.973.1" "@smithy/is-array-buffer": "npm:^4.2.0" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-stream": "npm:^4.5.8" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-stream": "npm:^4.5.10" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/5d9f67db921ffa05076279afbc42ada742f0efeb554bdad76d7ce0638e5791310ee0e8a772b3995e420867d280e81220f027da68278e2cfa493abbaca43d96f4 + checksum: 10c0/c843377b467edb626f5a11c9aa84ef525491236dcaec02b17363d409d13c755c8df29170b93f0940d140c131b8a197d664c43fdb7bb32d4072c4d201939a55cf languageName: node linkType: hard -"@aws-sdk/middleware-host-header@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/middleware-host-header@npm:3.965.0" +"@aws-sdk/middleware-host-header@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-host-header@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/bd139e5b231d3eff3f407263d1ad9b49b6b0791186bafa56e3e5b9dbab560bd89b99167fa6dff04d0308f72e3b2d5a64dac4c3ec236df1e9f7b2c58f4518da09 + checksum: 10c0/680a1934403b1544cbe1998ca22d684ff28bbbea78db8bea515bae80f7ede7ce762b2eb6fd5a56030b3a9a56a964e1c62ad40a8e2343e06862e1ccaa0cc3331b languageName: node linkType: hard -"@aws-sdk/middleware-location-constraint@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/middleware-location-constraint@npm:3.965.0" +"@aws-sdk/middleware-location-constraint@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-location-constraint@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/aca7c7bcd6b67f8a510633c704e0b0c7ce98ff6f4daa06cc493732e44f26167cdb6b6f6967e20c2810ae8351664015b0e17fdcde6d8f781e326c35785faab601 + checksum: 10c0/a2a284f24147aaf2a5367cd280f6646700bec03bd5dc66e1db0cf871904d64d21d77f45767edc2cbe2d9ffbd7d55141ff30df0143cc63ae7fe8b89559916bbb5 languageName: node linkType: hard -"@aws-sdk/middleware-logger@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/middleware-logger@npm:3.965.0" +"@aws-sdk/middleware-logger@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-logger@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/9efc280c9de443b0861c9150e4824f8b837f782c326bc85615500cfa2b2c842705b42adb53b7d6a24116666c2418cd25d1afcf06144ed1467476cddf758179e2 + checksum: 10c0/3cb6c1eddb7344f14f634fe1d6c9e7571ec8fe856ccf62dab71fae5fcef302f3b0e97d9ddb5ee90a427e14f28672cf406e8dadf30693e590f0d2a7eb1b439934 languageName: node linkType: hard -"@aws-sdk/middleware-recursion-detection@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.965.0" +"@aws-sdk/middleware-recursion-detection@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-recursion-detection@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" + "@aws-sdk/types": "npm:^3.973.1" "@aws/lambda-invoke-store": "npm:^0.2.2" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/a74b5bf6e9ffb84a58486be600a52c87257763b6ad400cae0d4c372519faff73c85d818b1aff13b593a1985b4f4c63b9f803e0b635a0ff29e2e4e87da3aa6e15 + checksum: 10c0/cc3e30e6968f18a5456c9b786b95579f688dd429422f6792211ebeaa462cf87186fd93996a8f034ce4abd95f39cfc0071c1cb801ad751be766617aac585cbb09 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-s3@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/middleware-sdk-s3@npm:3.967.0" +"@aws-sdk/middleware-sdk-s3@npm:^3.972.5": + version: 3.972.5 + resolution: "@aws-sdk/middleware-sdk-s3@npm:3.972.5" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/util-arn-parser": "npm:3.966.0" - "@smithy/core": "npm:^3.20.2" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/signature-v4": "npm:^5.3.7" - "@smithy/smithy-client": "npm:^4.10.4" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/util-arn-parser": "npm:^3.972.2" + "@smithy/core": "npm:^3.22.0" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/signature-v4": "npm:^5.3.8" + "@smithy/smithy-client": "npm:^4.11.1" + "@smithy/types": "npm:^4.12.0" "@smithy/util-config-provider": "npm:^4.2.0" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-stream": "npm:^4.5.8" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-stream": "npm:^4.5.10" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/291a6acb5340f6c1ce545e0dfb34f91fbe9f4307404d4dd9f426f750c6ebe1b96bce13594d896ee4a7c6814b509d7d637e90d89fedaed19731f36013fb90cdf2 + checksum: 10c0/d60f867c8a4293aee79474abdae5a13e84f0d8eb71b556316dc7b56a0108cb4fae94514284a0b2764c39545661b28edb06f18b46f88bc4023762a64d814ea956 languageName: node linkType: hard -"@aws-sdk/middleware-ssec@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/middleware-ssec@npm:3.965.0" +"@aws-sdk/middleware-ssec@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/middleware-ssec@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/1ebcad870236fcdb7da0a5ac1af5ccb27504d5bab0d5c8dab0dd6bd0bbf17246ea4ee99b5163a8ca8f952e0ad3c2bb30f06461823bf7e9eb7b1fc182fd6a0655 + checksum: 10c0/d4e1df3531947adbbd1cf64d89c5ad7b3596ffc471e83a32f555e0bd05e976d2bd183975689da60e4229bd0611cd53642a3b2355877348e99cdd3a1b7d4135ad languageName: node linkType: hard -"@aws-sdk/middleware-user-agent@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.967.0" +"@aws-sdk/middleware-user-agent@npm:^3.972.5": + version: 3.972.5 + resolution: "@aws-sdk/middleware-user-agent@npm:3.972.5" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/util-endpoints": "npm:3.965.0" - "@smithy/core": "npm:^3.20.2" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/util-endpoints": "npm:3.980.0" + "@smithy/core": "npm:^3.22.0" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/bbc129be48ce59d5d732c27da81c1e164e44f2858bca74ac430a0fba3b0229aa67272140ddb0ef68f60554b54717a6ffe9adef07f3e8568970fc82d7880344cf + checksum: 10c0/62b39d3c1dcd008d168bd91cb8ab872a7d2079be363359c55b7e3383d4d3eb0ed0e8cdb8eeeb0762f664d1c4c0d73fd1c3f3cc7ee28c2619ec6328ce5f05c426 languageName: node linkType: hard -"@aws-sdk/nested-clients@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/nested-clients@npm:3.967.0" +"@aws-sdk/nested-clients@npm:3.980.0": + version: 3.980.0 + resolution: "@aws-sdk/nested-clients@npm:3.980.0" dependencies: "@aws-crypto/sha256-browser": "npm:5.2.0" "@aws-crypto/sha256-js": "npm:5.2.0" - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/middleware-host-header": "npm:3.965.0" - "@aws-sdk/middleware-logger": "npm:3.965.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.965.0" - "@aws-sdk/middleware-user-agent": "npm:3.967.0" - "@aws-sdk/region-config-resolver": "npm:3.965.0" - "@aws-sdk/types": "npm:3.965.0" - "@aws-sdk/util-endpoints": "npm:3.965.0" - "@aws-sdk/util-user-agent-browser": "npm:3.965.0" - "@aws-sdk/util-user-agent-node": "npm:3.967.0" - "@smithy/config-resolver": "npm:^4.4.5" - "@smithy/core": "npm:^3.20.2" - "@smithy/fetch-http-handler": "npm:^5.3.8" - "@smithy/hash-node": "npm:^4.2.7" - "@smithy/invalid-dependency": "npm:^4.2.7" - "@smithy/middleware-content-length": "npm:^4.2.7" - "@smithy/middleware-endpoint": "npm:^4.4.3" - "@smithy/middleware-retry": "npm:^4.4.19" - "@smithy/middleware-serde": "npm:^4.2.8" - "@smithy/middleware-stack": "npm:^4.2.7" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/node-http-handler": "npm:^4.4.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/smithy-client": "npm:^4.10.4" - "@smithy/types": "npm:^4.11.0" - "@smithy/url-parser": "npm:^4.2.7" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/middleware-host-header": "npm:^3.972.3" + "@aws-sdk/middleware-logger": "npm:^3.972.3" + "@aws-sdk/middleware-recursion-detection": "npm:^3.972.3" + "@aws-sdk/middleware-user-agent": "npm:^3.972.5" + "@aws-sdk/region-config-resolver": "npm:^3.972.3" + "@aws-sdk/types": "npm:^3.973.1" + "@aws-sdk/util-endpoints": "npm:3.980.0" + "@aws-sdk/util-user-agent-browser": "npm:^3.972.3" + "@aws-sdk/util-user-agent-node": "npm:^3.972.3" + "@smithy/config-resolver": "npm:^4.4.6" + "@smithy/core": "npm:^3.22.0" + "@smithy/fetch-http-handler": "npm:^5.3.9" + "@smithy/hash-node": "npm:^4.2.8" + "@smithy/invalid-dependency": "npm:^4.2.8" + "@smithy/middleware-content-length": "npm:^4.2.8" + "@smithy/middleware-endpoint": "npm:^4.4.12" + "@smithy/middleware-retry": "npm:^4.4.29" + "@smithy/middleware-serde": "npm:^4.2.9" + "@smithy/middleware-stack": "npm:^4.2.8" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/node-http-handler": "npm:^4.4.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/smithy-client": "npm:^4.11.1" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" "@smithy/util-base64": "npm:^4.3.0" "@smithy/util-body-length-browser": "npm:^4.2.0" "@smithy/util-body-length-node": "npm:^4.2.1" - "@smithy/util-defaults-mode-browser": "npm:^4.3.18" - "@smithy/util-defaults-mode-node": "npm:^4.2.21" - "@smithy/util-endpoints": "npm:^3.2.7" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-retry": "npm:^4.2.7" + "@smithy/util-defaults-mode-browser": "npm:^4.3.28" + "@smithy/util-defaults-mode-node": "npm:^4.2.31" + "@smithy/util-endpoints": "npm:^3.2.8" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-retry": "npm:^4.2.8" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/a4060f1f5edbc183cc008de3622a84fa029c6364780fa86e401bf04b0e35ba94ef9a425d9287f3e2643368feeba326cb55ba6e01479fdb2a86ec3f2e4223161c + checksum: 10c0/0a5d36cf859ea7c717fdf0cae9cdd29c23a161068f3b16e4dfd6330ac32d564dc155c18b99b6feb058524afaee88ad7c7515d781b8e7622a0b94020dd3bf16ff languageName: node linkType: hard -"@aws-sdk/region-config-resolver@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/region-config-resolver@npm:3.965.0" +"@aws-sdk/region-config-resolver@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/region-config-resolver@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/config-resolver": "npm:^4.4.5" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/config-resolver": "npm:^4.4.6" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/e67a9f4787d14ffa678b0eb831c85133c2c2960c464ba76fd01f9379c99c74ab813d0094c4616b5a7a86988d0c29dc57ece09accf57f213ce166d71459d91af5 + checksum: 10c0/6682f729ba131b9067f7af77bcb49f3cae41668614e5c3b21ce8f091346a6961e852d0b72e15f262ad1fdccc9f4190680b35f756244cd691b6314b2866e071d9 languageName: node linkType: hard -"@aws-sdk/signature-v4-multi-region@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/signature-v4-multi-region@npm:3.967.0" +"@aws-sdk/signature-v4-multi-region@npm:3.981.0": + version: 3.981.0 + resolution: "@aws-sdk/signature-v4-multi-region@npm:3.981.0" dependencies: - "@aws-sdk/middleware-sdk-s3": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/signature-v4": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/middleware-sdk-s3": "npm:^3.972.5" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/signature-v4": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/61528d6353ef4f66b3403eaf3f642d905ec2fd8a4c2bbc82604bdee2071cb3cefa4a111e38d49ba7005a0da8e0ae165efb96418606a6cdf2067047401a9d2a36 + checksum: 10c0/23a098f78ac58c1bc4ebeca2fae6a2667a468d8e22fe022a606ddd1c63a1a998d0b0737789f0aad3dd3c6a1329b4c1bf8d36c45959a1bbf8a95ba2c260fac3fe languageName: node linkType: hard -"@aws-sdk/token-providers@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/token-providers@npm:3.967.0" +"@aws-sdk/token-providers@npm:3.980.0": + version: 3.980.0 + resolution: "@aws-sdk/token-providers@npm:3.980.0" dependencies: - "@aws-sdk/core": "npm:3.967.0" - "@aws-sdk/nested-clients": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/core": "npm:^3.973.5" + "@aws-sdk/nested-clients": "npm:3.980.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/c50992b1a872e50dde85115a10034cc203e099583eb5257af4890dd2508fc67c5123f7f279d7b8c05dcc05b3ae77faa0d1cc43d720f227854a2215f9c0025dd6 + checksum: 10c0/2ab2bd78bf356dce70c6ba12a5f288644c0b9d2cce90bcfb6a72f48eef9ea34f2579e8a485644ba16ef5501d10e2f0b8e312a2c3d893f721043a27a07663d588 languageName: node linkType: hard -"@aws-sdk/types@npm:3.965.0, @aws-sdk/types@npm:^3.222.0": - version: 3.965.0 - resolution: "@aws-sdk/types@npm:3.965.0" +"@aws-sdk/types@npm:^3.222.0, @aws-sdk/types@npm:^3.973.1": + version: 3.973.1 + resolution: "@aws-sdk/types@npm:3.973.1" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/59ee62046aef9ba74ccafcd3e28293075b085a99b5814af4a7539a05a81bb922abe9dbb2d08cecf789724ae4c65034ca6acf604e1fa915515438926db3a279e9 + checksum: 10c0/8a4a183cc39b4d6f4d065ece884b50d397a54b17add32b649f49adbe676174e7bee2c3c94394fc5227a4fccb96c34482291a1eb2702158e1dbb12c441af32863 languageName: node linkType: hard -"@aws-sdk/util-arn-parser@npm:3.966.0": - version: 3.966.0 - resolution: "@aws-sdk/util-arn-parser@npm:3.966.0" +"@aws-sdk/util-arn-parser@npm:^3.972.2": + version: 3.972.2 + resolution: "@aws-sdk/util-arn-parser@npm:3.972.2" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/55bbe6ff2f95084f57990b191db0a77744b1edf226361c0d303a3734978f98b0bf60ace493a3dae9d2d7f96284b2e5ec0b361ea0c65c1d8bf6ff7640cbe4e078 + checksum: 10c0/94aec6e0217da6add9d2334e8ec1c0c23955d279478e0161d00f66fd3527baf8a483e6fc41ecc2fb44e0b4116b52e85847a525ee7bdf43ff07d206f1e4ef03c9 languageName: node linkType: hard -"@aws-sdk/util-endpoints@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/util-endpoints@npm:3.965.0" +"@aws-sdk/util-endpoints@npm:3.980.0": + version: 3.980.0 + resolution: "@aws-sdk/util-endpoints@npm:3.980.0" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/types": "npm:^4.11.0" - "@smithy/url-parser": "npm:^4.2.7" - "@smithy/util-endpoints": "npm:^3.2.7" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" + "@smithy/util-endpoints": "npm:^3.2.8" tslib: "npm:^2.6.2" - checksum: 10c0/5b8b70b6910cdbad1a598aea357972fd44e7add699ed8813a6adb26dea9bb3872c95fdcd7997ed43c1d8f5f5bfdaf4686025f1d022a6d04471fcfad1dcfeab9c + checksum: 10c0/0de91a4d1e2382f45fbfcbd4e1424d2088fd58479483235b5dec23875a10fe11502a2482295ef14763793eeb607c4a0c1f75d2fc4101868e33f0837deab9a6ba + languageName: node + linkType: hard + +"@aws-sdk/util-endpoints@npm:3.981.0": + version: 3.981.0 + resolution: "@aws-sdk/util-endpoints@npm:3.981.0" + dependencies: + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" + "@smithy/util-endpoints": "npm:^3.2.8" + tslib: "npm:^2.6.2" + checksum: 10c0/d5256572280189e00ea7257f952a1c3fcc23e2245d65abda80c6734fe8dc7874658d74a09bf3284c5119a7fc5dfa5b2c4d711c5a812fdf0519ae0fa9997b5f68 languageName: node linkType: hard "@aws-sdk/util-locate-window@npm:^3.0.0": - version: 3.965.0 - resolution: "@aws-sdk/util-locate-window@npm:3.965.0" + version: 3.965.4 + resolution: "@aws-sdk/util-locate-window@npm:3.965.4" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/f7d454056656bad7d07aea7bbb9db67e45ac046c8caadbf0c12873696f1b27a8bef7e7222a1ae884c250e9446e780e293bd3e4ea39b6b60c45bae264ddc27c41 + checksum: 10c0/c87bef4cbeef564cb101f3d80b1dee008667e5a8c301b974dc25ec275e8d503a3226d3740bbfc4c1e17781719b7b8f06a25deea8196919caeaf87b0b8117286d languageName: node linkType: hard -"@aws-sdk/util-user-agent-browser@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.965.0" +"@aws-sdk/util-user-agent-browser@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/util-user-agent-browser@npm:3.972.3" dependencies: - "@aws-sdk/types": "npm:3.965.0" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/types": "npm:^4.12.0" bowser: "npm:^2.11.0" tslib: "npm:^2.6.2" - checksum: 10c0/d53fdd8fe3330c9235fa633d7cee73e27526a1e81854b46e57d8c709b963f4ab4a72567d5f673a0fec07f977e91d8ee833bdfdf46a1a2a33841c0f535e588839 + checksum: 10c0/637f1396cfbca7b352ffaf332998c4223c35d0fa41431c106151a34c6bfe7c9e32e6a6dc7e75c495714e05f3729ae1f61996da923156c3edcb33e217e24328ad languageName: node linkType: hard -"@aws-sdk/util-user-agent-node@npm:3.967.0": - version: 3.967.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.967.0" +"@aws-sdk/util-user-agent-node@npm:^3.972.3": + version: 3.972.3 + resolution: "@aws-sdk/util-user-agent-node@npm:3.972.3" dependencies: - "@aws-sdk/middleware-user-agent": "npm:3.967.0" - "@aws-sdk/types": "npm:3.965.0" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/types": "npm:^4.11.0" + "@aws-sdk/middleware-user-agent": "npm:^3.972.5" + "@aws-sdk/types": "npm:^3.973.1" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" peerDependencies: aws-crt: ">=1.0.0" peerDependenciesMeta: aws-crt: optional: true - checksum: 10c0/95087ea09519405341c935252f00071e55313a43c5d631ea4f2b43c0230dd934359f01e859d611da28e1e79cfc0377faa8c091005c9a58546bf0412368c835ca + checksum: 10c0/179a8554c503b5239d27a1c0b2592092a8afcec324bb5b97c23816577d94172f62817d4f789f6ad0c9f7245909e47ba53666e8dbf9f655d1507bda71ae6fadfc languageName: node linkType: hard -"@aws-sdk/xml-builder@npm:3.965.0": - version: 3.965.0 - resolution: "@aws-sdk/xml-builder@npm:3.965.0" +"@aws-sdk/xml-builder@npm:^3.972.2": + version: 3.972.3 + resolution: "@aws-sdk/xml-builder@npm:3.972.3" dependencies: - "@smithy/types": "npm:^4.11.0" - fast-xml-parser: "npm:5.2.5" + "@smithy/types": "npm:^4.12.0" + fast-xml-parser: "npm:5.3.4" tslib: "npm:^2.6.2" - checksum: 10c0/60fe1747946227d12f0cb14a1292bb672b15ebb98632571d6b78164e39666e7c40bf665fb120ae4141a8942cbcc3e2e9a5ee7d360965464476cca2c7bdea5f8c + checksum: 10c0/b2e6d8da88f7089f2bf5cf3eaac75828b3470070c7d1959836dc4ed28b31621788e4c5355f9216188c44ba2787931b78665e9eeb8317f41ca534ef6288eee27a languageName: node linkType: hard @@ -689,66 +702,66 @@ __metadata: languageName: node linkType: hard -"@aztec/accounts@npm:3.0.0-devnet.6-patch.1, @aztec/accounts@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/accounts@npm:3.0.0-devnet.6-patch.1" +"@aztec/accounts@npm:4.0.0-devnet.1-patch.0, @aztec/accounts@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/accounts@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/aztec.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/entrypoints": "npm:3.0.0-devnet.6-patch.1" - "@aztec/ethereum": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/aztec.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/entrypoints": "npm:4.0.0-devnet.1-patch.0" + "@aztec/ethereum": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" tslib: "npm:^2.4.0" - checksum: 10c0/0f93862c2af0a1aed375b0d3e57c6bb497470cef7ee81c95a02bd5c216bd57ddd32c4eb82c701f433dcab585536ba3c686201542793d4476995b493570ecd4b2 + checksum: 10c0/4fa62291dd72d7451b9102340cdee069f64df6156dd17221db0893ebd64fdd97c8b1d1d565cee66d6483723d624882b39c97babd26068ce007cac066a9202327 languageName: node linkType: hard -"@aztec/aztec.js@npm:3.0.0-devnet.6-patch.1, @aztec/aztec.js@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/aztec.js@npm:3.0.0-devnet.6-patch.1" +"@aztec/aztec.js@npm:4.0.0-devnet.1-patch.0, @aztec/aztec.js@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/aztec.js@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/entrypoints": "npm:3.0.0-devnet.6-patch.1" - "@aztec/ethereum": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/l1-artifacts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/protocol-contracts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/entrypoints": "npm:4.0.0-devnet.1-patch.0" + "@aztec/ethereum": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/l1-artifacts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/protocol-contracts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" axios: "npm:^1.12.0" tslib: "npm:^2.4.0" viem: "npm:@aztec/viem@2.38.2" zod: "npm:^3.23.8" - checksum: 10c0/373d21e6e8ec42ac95a0c2381d023cd4689ac985bbd381179c488b00ce5505b33e6d51f2eb3d0a3ed2e7df1e65304097ca6474492396729e72d4f2181bbc16ae + checksum: 10c0/83f08bc755118427d9d5f75fb376964f9454eca338c1f79de21bf879cfa729682b2001db38423f1b74ec7a8e0c3d0e3a443235939bed1c186f33377578404e95 languageName: node linkType: hard -"@aztec/bb-prover@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/bb-prover@npm:3.0.0-devnet.6-patch.1" +"@aztec/bb-prover@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/bb-prover@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/bb.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-noirc_abi": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-protocol-circuits-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/simulator": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/telemetry-client": "npm:3.0.0-devnet.6-patch.1" - "@aztec/world-state": "npm:3.0.0-devnet.6-patch.1" + "@aztec/bb.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-noirc_abi": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-protocol-circuits-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/simulator": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/telemetry-client": "npm:4.0.0-devnet.1-patch.0" + "@aztec/world-state": "npm:4.0.0-devnet.1-patch.0" commander: "npm:^12.1.0" pako: "npm:^2.1.0" source-map-support: "npm:^0.5.21" tslib: "npm:^2.4.0" bin: bb-cli: dest/bb/index.js - checksum: 10c0/d638c9ae18a58836cb71e566ac701f7aeaf2a7a17e6bf12459039a55f820fa8ad7a6902b9659354e56b3f8635454cbbb31851150966be1d195e9c52bc5bb8da7 + checksum: 10c0/4aa4ac502b7debc7a4ce3c063359cf477da8a50bd6fd6a98389ae1389db58a94837cc7bc1283b8bcd3bcfc1e4682b7696c557960be63f1792463d97832ff960c languageName: node linkType: hard -"@aztec/bb.js@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/bb.js@npm:3.0.0-devnet.6-patch.1" +"@aztec/bb.js@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/bb.js@npm:4.0.0-devnet.1-patch.0" dependencies: comlink: "npm:^4.4.1" commander: "npm:^12.1.0" @@ -758,67 +771,65 @@ __metadata: tslib: "npm:^2.4.0" bin: bb: dest/node/bin/index.js - checksum: 10c0/38282927a036fd419da0497a657fff2ff890433b757fe7808dd7519ef440824e757707fb7ff7d1eb6d7ada6a6c07874d744c4f3fa09f2eeef025d24309aed70e + checksum: 10c0/785850cc11cdb8ae724e3d82440e019184bd3b7fbd32e21ab4259d8696c546ea30cc4753448b796b79198a1482eb45cc94cee772dde9234be1c082ef69a71cfe languageName: node linkType: hard -"@aztec/blob-lib@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/blob-lib@npm:3.0.0-devnet.6-patch.1" +"@aztec/blob-lib@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/blob-lib@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" "@crate-crypto/node-eth-kzg": "npm:^0.10.0" tslib: "npm:^2.4.0" - checksum: 10c0/bd0ee0008a528d22a5c2af57119d0583e541560d7aed4859f2e58fd9bea7e47ad0081a2279e66a09bfb4dc4a6be017521e039019566c333d0cadfe6e4e9d23b7 + checksum: 10c0/cbafb3948e5f707762fcf3273854eab80b2ec5ae0f3f9e202c3d89e5bb1e6383e13db7df043f3dfdd4cf977ca26d2e95c28a4b555e6f86bc762f1e73b984affb languageName: node linkType: hard -"@aztec/builder@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/builder@npm:3.0.0-devnet.6-patch.1" +"@aztec/builder@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/builder@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" commander: "npm:^12.1.0" - bin: - aztec-builder: dest/bin/cli.js - checksum: 10c0/f03f891981063179bc3f3fc1f32939e617babad231d2cb4415a33da7266eebb1b8ec2ba771943fb486a4d1852a4e57db5314d0a1d0db9cfe2088d7ffb5ed7023 + checksum: 10c0/3083cda6ead4b67ebc276dc7c5ae8782835a068516880f0a85bfc23d5526ad30f82f296ce656d8e24799d377bd444c4c1ccb9a1332861f62ee89245fcd224551 languageName: node linkType: hard -"@aztec/constants@npm:3.0.0-devnet.6-patch.1, @aztec/constants@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/constants@npm:3.0.0-devnet.6-patch.1" +"@aztec/constants@npm:4.0.0-devnet.1-patch.0, @aztec/constants@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/constants@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" tslib: "npm:^2.4.0" - checksum: 10c0/38fdb6d9d3587d3248242574e8400e1ade4c1f2e60c3083da13173b62c927a1dca1e64e906a1924f615f185c6537663692da7e679cfd54908127a9077796a77d + checksum: 10c0/c40a715e7dd1cf404fb9d3f6fbf3d5a6f6f50c8c38461fcb5785a6f87a407dde92dc011b96ca8225152b1148d3242a944cd05e0a997f1d267bf02564fcd7f754 languageName: node linkType: hard -"@aztec/entrypoints@npm:3.0.0-devnet.6-patch.1, @aztec/entrypoints@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/entrypoints@npm:3.0.0-devnet.6-patch.1" +"@aztec/entrypoints@npm:4.0.0-devnet.1-patch.0, @aztec/entrypoints@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/entrypoints@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/protocol-contracts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/protocol-contracts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" tslib: "npm:^2.4.0" zod: "npm:^3.23.8" - checksum: 10c0/5953b907b5ad537812ef6930d47fa512664fe07dda3a19dc824875b94527193ab9146d1e71458156644815880a39d947e93f0a7961421e8c088028af69f7148d + checksum: 10c0/d0355d8f3e678801fdcf37ddddaa0d697c22bb01b32a82f267320a6b43ae21eb7f8c744cd607e6a0974b9da36a4a52081dc7d8404bbaeeb5e047c35055744265 languageName: node linkType: hard -"@aztec/ethereum@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/ethereum@npm:3.0.0-devnet.6-patch.1" +"@aztec/ethereum@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/ethereum@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/blob-lib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/l1-artifacts": "npm:3.0.0-devnet.6-patch.1" + "@aztec/blob-lib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/l1-artifacts": "npm:4.0.0-devnet.1-patch.0" "@viem/anvil": "npm:^0.0.10" dotenv: "npm:^16.0.3" lodash.chunk: "npm:^4.2.0" @@ -826,15 +837,15 @@ __metadata: tslib: "npm:^2.4.0" viem: "npm:@aztec/viem@2.38.2" zod: "npm:^3.23.8" - checksum: 10c0/6e9225bb42058bf743a9a6aeec28f3851827689f1d9b2f150761f9c4856641edc046e93350ff11d94a91102e3f4d30453a3ba5cb592898f4ac6292e038a721e8 + checksum: 10c0/48d7ec2f6813e5bdc30d727425b55b05d27ebfb744c4d897e48f21a1ec49d7399ded57a3c3854658254ed35e1e63b4ebfeb67c54d7895facfd3c50ebabd2c92a languageName: node linkType: hard -"@aztec/foundation@npm:3.0.0-devnet.6-patch.1, @aztec/foundation@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/foundation@npm:3.0.0-devnet.6-patch.1" +"@aztec/foundation@npm:4.0.0-devnet.1-patch.0, @aztec/foundation@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/foundation@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/bb.js": "npm:3.0.0-devnet.6-patch.1" + "@aztec/bb.js": "npm:4.0.0-devnet.1-patch.0" "@koa/cors": "npm:^5.0.0" "@noble/curves": "npm:=1.7.0" "@noble/hashes": "npm:^1.6.1" @@ -856,169 +867,169 @@ __metadata: sha3: "npm:^2.1.4" undici: "npm:^5.28.5" zod: "npm:^3.23.8" - checksum: 10c0/28a9eb727f054e3e43c56e08ba46aac508cf8271007786b41f7ea033f51e7ddd406ccf2cb3b90d85dfa1862e195b2cdea9a668c77fbecc428897e5f0bcfac03c + checksum: 10c0/583a7df21c9f2471376cdc1c4be27221475d2921195943d9e890198d1ee3e76710b97c27f10188084577f39f2d0878f282527eb07fac5cc6a5d1db5817a38bf8 languageName: node linkType: hard -"@aztec/key-store@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/key-store@npm:3.0.0-devnet.6-patch.1" +"@aztec/key-store@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/key-store@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/kv-store": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/kv-store": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" tslib: "npm:^2.4.0" - checksum: 10c0/8d8222b9b4c5516bf830c19627ec4a58db205442ec3dd6384e401582242a9f2cbc50a7412ff2354f035622d37ffb7a5a126b46e1bda3c103898aa57169a523a3 + checksum: 10c0/d45afc92e1e90489e4230cb22283459e177be5ed7011db45f42c2b8ce9fd98697fad62441b48bf9ef375dabc84106ea613d6897a050438495bc4fc20a4865c69 languageName: node linkType: hard -"@aztec/kv-store@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/kv-store@npm:3.0.0-devnet.6-patch.1" +"@aztec/kv-store@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/kv-store@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/ethereum": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/native": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/ethereum": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/native": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" idb: "npm:^8.0.0" lmdb: "npm:^3.2.0" msgpackr: "npm:^1.11.2" ohash: "npm:^2.0.11" ordered-binary: "npm:^1.5.3" - checksum: 10c0/ac8ba099839ef7b101afc7f23fe87a3f58852fea992c37466b41417cdad9b1052c412c78a79ff9509bc3fc8a987974b6db1035071033731b1f5350c999a3b342 + checksum: 10c0/256e53fba3cff9520100fe45dbc6afda0b28cc797a1d4df7ecefbdce2a48110b6fd0d3dd3836999df09db101ee21d4a6534bb51035917ca1c633661daa5c554e languageName: node linkType: hard -"@aztec/l1-artifacts@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/l1-artifacts@npm:3.0.0-devnet.6-patch.1" +"@aztec/l1-artifacts@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/l1-artifacts@npm:4.0.0-devnet.1-patch.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/5a9ed19b12aba356c849a5e067db63a961ac9aa0280c7d4d4b48e8b75eecf8f6746e8c40039a3c6431856a8cd2baeaf66d24cab158b4edfe558f2968560103dd + checksum: 10c0/b59077832e0a09d6696aadc1875955788410e5d4c6d6c410bed2880c8a0167211d646961a041c227fb08269ddc74f98149bc5601a7fd1e3978fb736e218d4ff9 languageName: node linkType: hard -"@aztec/merkle-tree@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/merkle-tree@npm:3.0.0-devnet.6-patch.1" +"@aztec/merkle-tree@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/merkle-tree@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/kv-store": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/kv-store": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" sha256: "npm:^0.2.0" tslib: "npm:^2.4.0" - checksum: 10c0/230a881e636a3cd03b6192ba12a8a87837dbee17f4d1f59982c36a008f7219936c01447a72d8b0fa113402274b8e9b7c2d5850f27edf30474d480a3e015c8ce1 + checksum: 10c0/5c7d90c9eb71dd08e7ef73f4b5ce534eb4bcb6fac65665d1a03b891c1401df329c58d3cc08727bacf78247105765a6f19fec44883c2a94fb4e4f959f70820026 languageName: node linkType: hard -"@aztec/native@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/native@npm:3.0.0-devnet.6-patch.1" +"@aztec/native@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/native@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/bb.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" + "@aztec/bb.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" msgpackr: "npm:^1.11.2" - checksum: 10c0/bc10f9fb3711f98869893b61fa3866ad6c98a56ea4982436fbddfc95a1ef7991a75a64ffb6d59562ddddb6c06c9f5f1ffd6663e8f553621c98ff5d16a84fa263 + checksum: 10c0/25fce21bb1c1c0e2514efd664242a8e51f8c5eedfdeffcc30e346e8c067648f208338b12ac39f3cfb83dd5225c1bc390c5e532b0579ca9a8216793547c6dc594 languageName: node linkType: hard -"@aztec/noir-acvm_js@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/noir-acvm_js@npm:3.0.0-devnet.6-patch.1" - checksum: 10c0/1ba4bd7f578f9e7c9d8e4d91eb6ac537d417af74a01fb50d4ef96c91108c411bc63297e382599221ca52d974ebf9fe01c08654d61276752c9f5922eaa644957b +"@aztec/noir-acvm_js@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/noir-acvm_js@npm:4.0.0-devnet.1-patch.0" + checksum: 10c0/cb86c3e60de358cd524e5a9732c4bc888c773deac0ca88c81dc4161c1e8b8c1f98313a090255dbe4f5045250da02e2552f60602c75a06e539ebdc3bb767c2ee6 languageName: node linkType: hard -"@aztec/noir-contracts.js@npm:3.0.0-devnet.6-patch.1, @aztec/noir-contracts.js@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/noir-contracts.js@npm:3.0.0-devnet.6-patch.1" +"@aztec/noir-contracts.js@npm:4.0.0-devnet.1-patch.0, @aztec/noir-contracts.js@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/noir-contracts.js@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/aztec.js": "npm:3.0.0-devnet.6-patch.1" + "@aztec/aztec.js": "npm:4.0.0-devnet.1-patch.0" tslib: "npm:^2.4.0" - checksum: 10c0/bd3924a1c1f226ff4be2bc98877f01a2d28663e06bbc8e0cf6edc77da872362729a3e6f4866e08ca3cb59876f06d309f046dd53b52fa206feef83aa203ecec1c + checksum: 10c0/f214089ebe76e07ccb16f2f29d709058365aa31fa21dd6fd4f415beea2e5e5271b19bd20411d1b08dcf4155b7429baf2cebe0e9bd34563047a06787772a05403 languageName: node linkType: hard -"@aztec/noir-noir_codegen@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/noir-noir_codegen@npm:3.0.0-devnet.6-patch.1" +"@aztec/noir-noir_codegen@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/noir-noir_codegen@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/noir-types": "npm:3.0.0-devnet.6-patch.1" - glob: "npm:^11.0.3" + "@aztec/noir-types": "npm:4.0.0-devnet.1-patch.0" + glob: "npm:^13.0.0" ts-command-line-args: "npm:^2.5.1" bin: noir-codegen: lib/main.js - checksum: 10c0/827a2cd2272810215815490138e781717a1abaa26c49daf3f265bcebf95233cf23695899dde3e251ee3bd3c49fe079b7c799f596c8c9666981bc9af2e7b0e424 + checksum: 10c0/6fba409e70a25b4c8ab1d76ae50c79cfbe01dc095d1e683af74e66214a4d44ac10834f4153d438aa336da83abee1a31e83aaa0923098a3e567f407869e625cc5 languageName: node linkType: hard -"@aztec/noir-noirc_abi@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/noir-noirc_abi@npm:3.0.0-devnet.6-patch.1" +"@aztec/noir-noirc_abi@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/noir-noirc_abi@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/noir-types": "npm:3.0.0-devnet.6-patch.1" - checksum: 10c0/6a4d40a4585772f3a28a85b713d85186eb115b711709d23e05eced5f141bfb4c26353b0c13b15efb489e851ecc37f36c8a57230fba43c2e18ea734a08a3e71d6 + "@aztec/noir-types": "npm:4.0.0-devnet.1-patch.0" + checksum: 10c0/347cc6912cc5a85dfdac4db51260314364edbe8128de7d0af32ce2f8de972dd4e788b91c7abbfff3a05c6f6e32c4fc62d6afd63bf02ee1884db1f715f1ad610f languageName: node linkType: hard -"@aztec/noir-protocol-circuits-types@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/noir-protocol-circuits-types@npm:3.0.0-devnet.6-patch.1" +"@aztec/noir-protocol-circuits-types@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/noir-protocol-circuits-types@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/blob-lib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-acvm_js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-noir_codegen": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-noirc_abi": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/blob-lib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-acvm_js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-noir_codegen": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-noirc_abi": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" change-case: "npm:^5.4.4" tslib: "npm:^2.4.0" - checksum: 10c0/39f0088548eb856876fd917aabd58028b576e3ffd23c6bda50858b85bc0591b6030c8476f1cdba94e2c1e94bc2533cb6f116c71619a96976553a7a27cc78101a + checksum: 10c0/e44db67e12897c0685bf7c1a2bb3ecdbd8d7989c8c9aca30690344fc234563d6f71b60d86fa3c87026beb00df70ae85999cbe06320a4b61e730145ab43e3c153 languageName: node linkType: hard -"@aztec/noir-types@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/noir-types@npm:3.0.0-devnet.6-patch.1" - checksum: 10c0/d77736f8a6bd644ec0a254fbb425e8a6965ec134a36c3a00a650e48724c609154c7c405c0164cc9a7878553c333e94da08704b69ae016bbcfcc2183e618166c6 +"@aztec/noir-types@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/noir-types@npm:4.0.0-devnet.1-patch.0" + checksum: 10c0/d0bc46e11fd5f53e3335a1610418e3d1389d1c7980e606de0bd28ed9cc4ab2df14de3230d2105da7367d5326b67666e8facafed13f437a79e0c912539f700bdf languageName: node linkType: hard -"@aztec/protocol-contracts@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/protocol-contracts@npm:3.0.0-devnet.6-patch.1" +"@aztec/protocol-contracts@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/protocol-contracts@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" lodash.chunk: "npm:^4.2.0" lodash.omit: "npm:^4.5.0" tslib: "npm:^2.4.0" - checksum: 10c0/4b9d176acede698cf9066de4b03a147fb1621303457f535087382a35ad467396a508b9e2405557fad6910804a6cb855baa402a5b9803131f9543effc98f70242 - languageName: node - linkType: hard - -"@aztec/pxe@npm:3.0.0-devnet.6-patch.1, @aztec/pxe@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/pxe@npm:3.0.0-devnet.6-patch.1" - dependencies: - "@aztec/bb-prover": "npm:3.0.0-devnet.6-patch.1" - "@aztec/bb.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/builder": "npm:3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/ethereum": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/key-store": "npm:3.0.0-devnet.6-patch.1" - "@aztec/kv-store": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-protocol-circuits-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/protocol-contracts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/simulator": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + checksum: 10c0/b85942636b86b6ca52875964101ad51a4c2d3fc5aacb7e1d1a7d32833e60f6e2ff94f9827624465a10705757361e1d3612b9b413e601cebc5f89c2b782c7668f + languageName: node + linkType: hard + +"@aztec/pxe@npm:4.0.0-devnet.1-patch.0, @aztec/pxe@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/pxe@npm:4.0.0-devnet.1-patch.0" + dependencies: + "@aztec/bb-prover": "npm:4.0.0-devnet.1-patch.0" + "@aztec/bb.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/builder": "npm:4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/ethereum": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/key-store": "npm:4.0.0-devnet.1-patch.0" + "@aztec/kv-store": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-protocol-circuits-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/protocol-contracts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/simulator": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" koa: "npm:^2.16.1" koa-router: "npm:^13.1.1" lodash.omit: "npm:^4.5.0" @@ -1027,44 +1038,45 @@ __metadata: viem: "npm:@aztec/viem@2.38.2" bin: pxe: dest/bin/index.js - checksum: 10c0/d3002a669d02d0cc818e4304388615c4c05cfc04c1c20c19fda728e319210c997aefdcd4d608b518d73d32835de1fc7c685cf048fb0e4592f2779fb9302551df + checksum: 10c0/3e1b967535b033908d48cb36f07894cb769daf079f96d9e46fd52cb5f2ff0d1783fa443bd8615da6ddd167f31f2392bc80d2f95c6943efadaa8b561f6c7ae338 languageName: node linkType: hard -"@aztec/simulator@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/simulator@npm:3.0.0-devnet.6-patch.1" +"@aztec/simulator@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/simulator@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/native": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-acvm_js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-noirc_abi": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-protocol-circuits-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-types": "npm:3.0.0-devnet.6-patch.1" - "@aztec/protocol-contracts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/telemetry-client": "npm:3.0.0-devnet.6-patch.1" - "@aztec/world-state": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/native": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-acvm_js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-noirc_abi": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-protocol-circuits-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-types": "npm:4.0.0-devnet.1-patch.0" + "@aztec/protocol-contracts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/telemetry-client": "npm:4.0.0-devnet.1-patch.0" + "@aztec/world-state": "npm:4.0.0-devnet.1-patch.0" lodash.clonedeep: "npm:^4.5.0" lodash.merge: "npm:^4.6.2" tslib: "npm:^2.4.0" - checksum: 10c0/c25f9cef74eff0de66c6c237bab610710abbc0b9eb88a67d29b2e64703217cd71c19043e453319e008d1603caf0725ee32d609d1fad80907533c23f6e3b86006 + checksum: 10c0/76b12802eaeed46399950adc840554ba7bfcd41db6fb1dee610f06f519ddfec7521815180eed9e3a3bcff7942fd124b2cebae9e111bacaa713db09e8ff7b1ba4 languageName: node linkType: hard -"@aztec/stdlib@npm:3.0.0-devnet.6-patch.1, @aztec/stdlib@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/stdlib@npm:3.0.0-devnet.6-patch.1" +"@aztec/stdlib@npm:4.0.0-devnet.1-patch.0, @aztec/stdlib@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/stdlib@npm:4.0.0-devnet.1-patch.0" dependencies: "@aws-sdk/client-s3": "npm:^3.892.0" - "@aztec/bb.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/blob-lib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/ethereum": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/l1-artifacts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-noirc_abi": "npm:3.0.0-devnet.6-patch.1" + "@aztec/bb.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/blob-lib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/ethereum": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/l1-artifacts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-noirc_abi": "npm:4.0.0-devnet.1-patch.0" + "@aztec/validator-ha-signer": "npm:4.0.0-devnet.1-patch.0" "@google-cloud/storage": "npm:^7.15.0" axios: "npm:^1.12.0" json-stringify-deterministic: "npm:1.0.12" @@ -1077,16 +1089,16 @@ __metadata: tslib: "npm:^2.4.0" viem: "npm:@aztec/viem@2.38.2" zod: "npm:^3.23.8" - checksum: 10c0/d3d094becc4247f61b0219d6dd7d8cfab22f278280b9dda0a060809e78f0caaed9c59d93f585daad8adf3e1c67668369ceb5a1e7820bb6b70874ccd8eb7e7a5c + checksum: 10c0/3e52eb9bbbe48cea9a80340bbb6e52e0b0f90feff2934929b0b743998866dc75ab23bae142d8d22dd9fcab4f09051963674209738cf9cea4fa057f306921287c languageName: node linkType: hard -"@aztec/telemetry-client@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/telemetry-client@npm:3.0.0-devnet.6-patch.1" +"@aztec/telemetry-client@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/telemetry-client@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" "@opentelemetry/api": "npm:^1.9.0" "@opentelemetry/api-logs": "npm:^0.55.0" "@opentelemetry/core": "npm:^1.28.0" @@ -1103,55 +1115,69 @@ __metadata: "@opentelemetry/semantic-conventions": "npm:^1.28.0" prom-client: "npm:^15.1.3" viem: "npm:@aztec/viem@2.38.2" - checksum: 10c0/f89c64affef2ea2671a1f9b93362dd7b83b33d71106b1bdb6ad0f215b6347415ca88f9ed64b5db59005a295b746b38e28adc169d37293b9d3d07819556406d63 + checksum: 10c0/71684ea7543f16bf120c75eafb5fb70f791ebdf245ba271943bbf134f1ab00ff2a0287a0410a6053884a3b5fac6bf8739c11b84767c4e3e5c975c7573cddd5b2 + languageName: node + linkType: hard + +"@aztec/test-wallet@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/test-wallet@npm:4.0.0-devnet.1-patch.0" + dependencies: + "@aztec/accounts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/aztec.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/entrypoints": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/noir-contracts.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/pxe": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/wallet-sdk": "npm:4.0.0-devnet.1-patch.0" + checksum: 10c0/038094118233cb2cdc8c59758afc1273aaba568c478def0949d853a25a3848610a3d56452aa9aaa8157d7dd642aa36f441a82fa4afca9e2e15a0785de8c56555 languageName: node linkType: hard -"@aztec/test-wallet@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/test-wallet@npm:3.0.0-devnet.6-patch.1" +"@aztec/validator-ha-signer@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/validator-ha-signer@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/accounts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/aztec.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/entrypoints": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/noir-contracts.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/pxe": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/wallet-sdk": "npm:3.0.0-devnet.6-patch.1" - checksum: 10c0/52507a7fcbd0027e28b7a4bf58f2d25bacdd4f1fad4da415ace6a8a21ba569eeb45e801f5fbb0dc1090866e9d1e9e0a7ae9357ca0531dd9a41700dd3669865ef + "@aztec/ethereum": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + node-pg-migrate: "npm:^8.0.4" + pg: "npm:^8.11.3" + tslib: "npm:^2.4.0" + zod: "npm:^3.23.8" + checksum: 10c0/3902f99efa13d5d7191e3084645513222f2dbe3900c4d3f4ffe542c77a5874849323a77da5144af20e051156a21a776f802361399a50d20518aef21129aaa55f languageName: node linkType: hard -"@aztec/wallet-sdk@npm:3.0.0-devnet.6-patch.1, @aztec/wallet-sdk@npm:v3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/wallet-sdk@npm:3.0.0-devnet.6-patch.1" +"@aztec/wallet-sdk@npm:4.0.0-devnet.1-patch.0, @aztec/wallet-sdk@npm:v4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/wallet-sdk@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/aztec.js": "npm:3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/entrypoints": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/pxe": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" - checksum: 10c0/e331b8c932b5a754396add5071e282c03d5a4170a70052689fb62673100feb4135f1bf92662a51f5fc0c3c016798ac68f7398e8a2c284bf037d3afab33e9f8bc + "@aztec/aztec.js": "npm:4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/entrypoints": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/pxe": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" + checksum: 10c0/cde3a1ac8c15ff79447c205f671799c7d2e9ad7905f869e5062d4b2e4d3c2122157022256dcfa11ad8ae0c2e69ae14c2fd612b8593f02b392920ed40f78d172f languageName: node linkType: hard -"@aztec/world-state@npm:3.0.0-devnet.6-patch.1": - version: 3.0.0-devnet.6-patch.1 - resolution: "@aztec/world-state@npm:3.0.0-devnet.6-patch.1" +"@aztec/world-state@npm:4.0.0-devnet.1-patch.0": + version: 4.0.0-devnet.1-patch.0 + resolution: "@aztec/world-state@npm:4.0.0-devnet.1-patch.0" dependencies: - "@aztec/constants": "npm:3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:3.0.0-devnet.6-patch.1" - "@aztec/kv-store": "npm:3.0.0-devnet.6-patch.1" - "@aztec/merkle-tree": "npm:3.0.0-devnet.6-patch.1" - "@aztec/native": "npm:3.0.0-devnet.6-patch.1" - "@aztec/protocol-contracts": "npm:3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:3.0.0-devnet.6-patch.1" - "@aztec/telemetry-client": "npm:3.0.0-devnet.6-patch.1" + "@aztec/constants": "npm:4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:4.0.0-devnet.1-patch.0" + "@aztec/kv-store": "npm:4.0.0-devnet.1-patch.0" + "@aztec/merkle-tree": "npm:4.0.0-devnet.1-patch.0" + "@aztec/native": "npm:4.0.0-devnet.1-patch.0" + "@aztec/protocol-contracts": "npm:4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:4.0.0-devnet.1-patch.0" + "@aztec/telemetry-client": "npm:4.0.0-devnet.1-patch.0" tslib: "npm:^2.4.0" zod: "npm:^3.23.8" - checksum: 10c0/7dd35e42529cd5d3590b78d9260e01d820427f43607aea5a0d0bed2200597bac021749d1f84708540351a5e0859e772008f2c09403d12324c53b6ca7c2a753bf + checksum: 10c0/fdfcea4cf13fcfd1eb0057de80905d462500b2c0dee2f6a9e17836bb1bda0c082ebedb9d47318b761930e5357dd9a06121b98de82f2cad292ab37f0a4ded2034 languageName: node linkType: hard @@ -1810,6 +1836,13 @@ __metadata: languageName: node linkType: hard +"@harperfast/extended-iterable@npm:^1.0.3": + version: 1.0.3 + resolution: "@harperfast/extended-iterable@npm:1.0.3" + checksum: 10c0/13146fb69f0beaad4cf426ee00b57306bfdef2c2c38ed8cce12b432bf267ce6190e926efc3637db80ff01948cbcc7dcfcbdd3526e53eb5de2623856f8381b515 + languageName: node + linkType: hard + "@humanfs/core@npm:^0.19.1": version: 0.19.1 resolution: "@humanfs/core@npm:0.19.1" @@ -1923,51 +1956,51 @@ __metadata: languageName: node linkType: hard -"@lmdb/lmdb-darwin-arm64@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-darwin-arm64@npm:3.4.4" +"@lmdb/lmdb-darwin-arm64@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-darwin-arm64@npm:3.5.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@lmdb/lmdb-darwin-x64@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-darwin-x64@npm:3.4.4" +"@lmdb/lmdb-darwin-x64@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-darwin-x64@npm:3.5.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@lmdb/lmdb-linux-arm64@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-linux-arm64@npm:3.4.4" +"@lmdb/lmdb-linux-arm64@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-linux-arm64@npm:3.5.1" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@lmdb/lmdb-linux-arm@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-linux-arm@npm:3.4.4" +"@lmdb/lmdb-linux-arm@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-linux-arm@npm:3.5.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@lmdb/lmdb-linux-x64@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-linux-x64@npm:3.4.4" +"@lmdb/lmdb-linux-x64@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-linux-x64@npm:3.5.1" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@lmdb/lmdb-win32-arm64@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-win32-arm64@npm:3.4.4" +"@lmdb/lmdb-win32-arm64@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-win32-arm64@npm:3.5.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@lmdb/lmdb-win32-x64@npm:3.4.4": - version: 3.4.4 - resolution: "@lmdb/lmdb-win32-x64@npm:3.4.4" +"@lmdb/lmdb-win32-x64@npm:3.5.1": + version: 3.5.1 + resolution: "@lmdb/lmdb-win32-x64@npm:3.5.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2594,9 +2627,9 @@ __metadata: linkType: hard "@opentelemetry/semantic-conventions@npm:^1.27.0, @opentelemetry/semantic-conventions@npm:^1.28.0": - version: 1.38.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.38.0" - checksum: 10c0/ae93e39ac18bf47df2b11d43e9a0dc1673b9d33e5f1e7f357c92968e6329fb9a67cf8a447e9a7150948ee3f8178b38274db365b8fa775a8c54802e0c6ccdd2ca + version: 1.39.0 + resolution: "@opentelemetry/semantic-conventions@npm:1.39.0" + checksum: 10c0/1a8cc16e83ccd80aeb910e78146e8cde8482ac45feb3693348eec5983d8ad254f977f2b61db76f043ab0fa6009a27df610a9cff286a217d6cd4c114216861d0f languageName: node linkType: hard @@ -2943,13 +2976,13 @@ __metadata: languageName: node linkType: hard -"@smithy/abort-controller@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/abort-controller@npm:4.2.7" +"@smithy/abort-controller@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/abort-controller@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/4f992bdff9f035a62c1403da1999e0170f8703a4ad0c7fbc93bc992d4ffcb20d12cebf40ad6dc006c7f0a7e80253646a147ee64ca29266dd7e52800f0ebf93fe + checksum: 10c0/2c2094ebd0b842a478746da74a74feaf579ca5fe03d7a1a7868ba7d048d88e2479edad8d2791d22d7bb9e5e774c1df4201a3ffa360c3aefaf158f692c45594f8 languageName: node linkType: hard @@ -2972,161 +3005,161 @@ __metadata: languageName: node linkType: hard -"@smithy/config-resolver@npm:^4.4.5": - version: 4.4.5 - resolution: "@smithy/config-resolver@npm:4.4.5" +"@smithy/config-resolver@npm:^4.4.6": + version: 4.4.6 + resolution: "@smithy/config-resolver@npm:4.4.6" dependencies: - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/types": "npm:^4.12.0" "@smithy/util-config-provider": "npm:^4.2.0" - "@smithy/util-endpoints": "npm:^3.2.7" - "@smithy/util-middleware": "npm:^4.2.7" + "@smithy/util-endpoints": "npm:^3.2.8" + "@smithy/util-middleware": "npm:^4.2.8" tslib: "npm:^2.6.2" - checksum: 10c0/0a7c365bc50e82c9e22897b26cafe1d2a176b425a1303ff55fd5bd5f851e85534e7147d2a1408328dc6ca29f535143eab3289a39d03969e924302226711c0d55 + checksum: 10c0/ab3de62329d53ca886d0efb2e10e904c3d3a7e564cda6b4d710d8512d2f4b9980e5346614da511d978c6a9a6c3c71f968e7c752dac36dfd61219d2e6fd0695cc languageName: node linkType: hard -"@smithy/core@npm:^3.20.2, @smithy/core@npm:^3.20.3": - version: 3.20.3 - resolution: "@smithy/core@npm:3.20.3" +"@smithy/core@npm:^3.22.0, @smithy/core@npm:^3.22.1": + version: 3.22.1 + resolution: "@smithy/core@npm:3.22.1" dependencies: - "@smithy/middleware-serde": "npm:^4.2.8" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/middleware-serde": "npm:^4.2.9" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" "@smithy/util-base64": "npm:^4.3.0" "@smithy/util-body-length-browser": "npm:^4.2.0" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-stream": "npm:^4.5.8" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-stream": "npm:^4.5.11" "@smithy/util-utf8": "npm:^4.2.0" "@smithy/uuid": "npm:^1.1.0" tslib: "npm:^2.6.2" - checksum: 10c0/84f404ddb70382047808cfc302594471b692d64ef5c8b164956374b6703c388cf6e790b6767b8785170a4a58b08084634844aa3c328b00ada2993b79543c1abf + checksum: 10c0/f1f65f7f323128f0b2d9a3ee13b1b4a5942e966ff12016549f4bff8a83ccd6d8d539e29d27c11ccf66d4948e4766bb1b2ea8f37b08c70f85ae8cb2a2ab034e3b languageName: node linkType: hard -"@smithy/credential-provider-imds@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/credential-provider-imds@npm:4.2.7" +"@smithy/credential-provider-imds@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/credential-provider-imds@npm:4.2.8" dependencies: - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" - "@smithy/url-parser": "npm:^4.2.7" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" tslib: "npm:^2.6.2" - checksum: 10c0/5c190b46879a9ce12c73099db4fd302089de79b5efd4177be256faa096778817cb9bc8e682f01abe397482ed90b00a726888630aecaaed47c2e3214169a23351 + checksum: 10c0/e53cec39703aa197df6bf38985403ad69ecd45e17ee5caadb53945d0a36b22332ff04e4d2d6a8d7c8e4bea9e6edabf6abf7cc6dafbc6cfbf7c20a88223e6fc55 languageName: node linkType: hard -"@smithy/eventstream-codec@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/eventstream-codec@npm:4.2.7" +"@smithy/eventstream-codec@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/eventstream-codec@npm:4.2.8" dependencies: "@aws-crypto/crc32": "npm:5.2.0" - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" "@smithy/util-hex-encoding": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/4388969ead1da4d657e3b05d7a031ad80b54c7e5635d1f6b1c1e3f56ffaeebf928a157b7c7aa886249f223fb0ee8c1b020bf9ab2a08cfdb0840066f40348272a + checksum: 10c0/ec468850dabce86d88075765b3a5f95e865850a6d98f6f395ead49af3d20316f50cce755b31f0e0b9ab027676f688814f76f68acc7c642483a6e196b25643e78 languageName: node linkType: hard -"@smithy/eventstream-serde-browser@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/eventstream-serde-browser@npm:4.2.7" +"@smithy/eventstream-serde-browser@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/eventstream-serde-browser@npm:4.2.8" dependencies: - "@smithy/eventstream-serde-universal": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/eventstream-serde-universal": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/76f9f5e9aa3dd0e1162fe66e516d1a6b740f6c0119c8e2a247e24636d58dad7887f233c57dafcdb0842b3b5edee7195aab9bd6dbd653bfeab779c358be0e1645 + checksum: 10c0/9f5abf3073ac58dcd88db3cf28f1edaa73c2b5c4b3249b0b6bfdb4cd51b328f64f66ac5918145aa20842a3277b38339d88ae414c86610b9ee6ef099b2f8310a0 languageName: node linkType: hard -"@smithy/eventstream-serde-config-resolver@npm:^4.3.7": - version: 4.3.7 - resolution: "@smithy/eventstream-serde-config-resolver@npm:4.3.7" +"@smithy/eventstream-serde-config-resolver@npm:^4.3.8": + version: 4.3.8 + resolution: "@smithy/eventstream-serde-config-resolver@npm:4.3.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/3aac405fae327db2fd2d588e5970e656ee385abaae3612a6c56418a14a291054916d36f409e69f2d61b96ebe615d3130310c33f28fa4c35b653e839927b6626d + checksum: 10c0/10f80501ab34918e26caed612d7bd8c4cfb0771994c108212be27dd0a05cec4175141b24edfc455255af3677513cf75154946fc4c2e3ae5093ee1065e06801f2 languageName: node linkType: hard -"@smithy/eventstream-serde-node@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/eventstream-serde-node@npm:4.2.7" +"@smithy/eventstream-serde-node@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/eventstream-serde-node@npm:4.2.8" dependencies: - "@smithy/eventstream-serde-universal": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/eventstream-serde-universal": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/bdbb3372508c45215f4503195d7a60a09ad0433742d90a4b3fcfc415d206e9cca6687ca362131c3d8454629c80154f54bcebef66121a6874a25a41b81b3d8878 + checksum: 10c0/9b0c37ffd3f0d08a9c4170742fbc8fb14e38e34ee164642d102477a9e339fa8f12920b2ff9017903954e036a7219bbc9008a6942d3e68fefbfd1285a5fd9168b languageName: node linkType: hard -"@smithy/eventstream-serde-universal@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/eventstream-serde-universal@npm:4.2.7" +"@smithy/eventstream-serde-universal@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/eventstream-serde-universal@npm:4.2.8" dependencies: - "@smithy/eventstream-codec": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/eventstream-codec": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/05d0f1d1b03c0d4d5b688508e2c04e4197b53c1ed7da4d68c1161b9b5ec54bc83ffff90d02e400753e6f490c4fe90f7d1ae74c6be0fd4dc1d64499365f221fe8 + checksum: 10c0/06a3388efbc10bebb97b78800c72dea0baf5552b33e51d64cada6fa5eea891389c81a8e214d1eb0b5d72a8135c121b610b7dcecaef2a160e017d59d99110e956 languageName: node linkType: hard -"@smithy/fetch-http-handler@npm:^5.3.8": - version: 5.3.8 - resolution: "@smithy/fetch-http-handler@npm:5.3.8" +"@smithy/fetch-http-handler@npm:^5.3.9": + version: 5.3.9 + resolution: "@smithy/fetch-http-handler@npm:5.3.9" dependencies: - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/querystring-builder": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/querystring-builder": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" "@smithy/util-base64": "npm:^4.3.0" tslib: "npm:^2.6.2" - checksum: 10c0/94ca27084fe0aa1626f5dec3755811d61bb7ec81c0a3d9428c324b238495e695f568800e30fdb127129fba95625355d8c51cbcae52796a008c7cfd4ff5074cb5 + checksum: 10c0/43b341d1594da4a076a48896f552b96d5e817054e9a354d10001ad51f05cb0f976c8d12529bd462a88cff23c8ab3ca475705db0855751616c08505fc6d083db2 languageName: node linkType: hard -"@smithy/hash-blob-browser@npm:^4.2.8": - version: 4.2.8 - resolution: "@smithy/hash-blob-browser@npm:4.2.8" +"@smithy/hash-blob-browser@npm:^4.2.9": + version: 4.2.9 + resolution: "@smithy/hash-blob-browser@npm:4.2.9" dependencies: "@smithy/chunked-blob-reader": "npm:^5.2.0" "@smithy/chunked-blob-reader-native": "npm:^4.2.1" - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/69fc710a64151c1b1bc585cd92bcb2c4a8434ecb9e65ccae13503a3deef1c2e061213eb151e7b5eb079eb7cdda6d2c5fcc6eb8822fe12253ff974eb52aea8c8d + checksum: 10c0/19a55c5ebd62ea489e6a7c4e47267739ee83c00cc73430c4584b1685db7f1444d33814e78489f8346bcf20689d719e554010ec9cd4d2758acf9c724fa3590692 languageName: node linkType: hard -"@smithy/hash-node@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/hash-node@npm:4.2.7" +"@smithy/hash-node@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/hash-node@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" "@smithy/util-buffer-from": "npm:^4.2.0" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/fa3b2194c22dd240b8dcfc191ca68ed563513fc7e852537eb69223933e70a50b365fb53d1a150a37a091cf6d449b4b7aecaa51892b9f49fd3763174e27e1ec5c + checksum: 10c0/541de03fce0623ea72c0e44cb15d16001d3c4ff7f0ac8b03a53b59c3c526d9d0196297f0f2bc9b08f9e108c4920983a54df0281ba36941b30c7940195c618222 languageName: node linkType: hard -"@smithy/hash-stream-node@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/hash-stream-node@npm:4.2.7" +"@smithy/hash-stream-node@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/hash-stream-node@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/7d29f2feb91636242f6a1c0f6365584861de47803e778217c3e3d37091d6a2bb9ef9d4fdf1a8d55d9d9332360c21bc7ddbd8b17ece0affe8b9637545a9a9d9aa + checksum: 10c0/fc9639d55e4131fe40a299abb0a83b22a43ea88138c0a5074768b5b1ce2e7c9980b34298983739d01507b2408d5fd9fe4f234f581ad4656fb7198605c5dc3d35 languageName: node linkType: hard -"@smithy/invalid-dependency@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/invalid-dependency@npm:4.2.7" +"@smithy/invalid-dependency@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/invalid-dependency@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/eadbdd4e7dd94f7caa8c17c003e4c48ef03ff2af0401fab3884468535b016cf318c95e57cdad2b170cb852119303e5500f3bb138635705e8a4d6a2fc58a111ed + checksum: 10c0/b224c6692ec745c30c022114c53328a69caf00e6848f3920fe180e5836440a9dfebf67bf4d6cc8f1fabe4d88be2f60f5428c93cbe80de3baefb0710b7a4b0e7c languageName: node linkType: hard @@ -3148,215 +3181,215 @@ __metadata: languageName: node linkType: hard -"@smithy/md5-js@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/md5-js@npm:4.2.7" +"@smithy/md5-js@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/md5-js@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/08910bf3131bfc82445b20a254f5adc978087e76c309aee9a63dd24084d4c7ea5d96f99bc99a0542553091951127f47731af5f2f6af60cf4bfc423833b4dc8b4 + checksum: 10c0/cbc2ad4862214437ca04c0e946d21df9c2553006725a13f97c3dc3b5bc9fd9b95ccbb1005c0763e75b29f88ebcbbd7b217f19c8f4c88ab36be1ab60ded030859 languageName: node linkType: hard -"@smithy/middleware-content-length@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/middleware-content-length@npm:4.2.7" +"@smithy/middleware-content-length@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/middleware-content-length@npm:4.2.8" dependencies: - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/23237a15d0a39b95157c3d370edd48aeb0be23daff78b858c3a2e8af081c1a91ef6b5800d2746d9c8094e7af7d4aeb44bb2b400b887527bcdab3be4dc0c3b46c + checksum: 10c0/27a732a4207936da2b57212d7abb2d55d398d483e507fefb540e2ea20247795770bd73bfc7a4d488de3aa923810241014eb05a4cfa1b8354b4e284161d1bec42 languageName: node linkType: hard -"@smithy/middleware-endpoint@npm:^4.4.3, @smithy/middleware-endpoint@npm:^4.4.4": - version: 4.4.4 - resolution: "@smithy/middleware-endpoint@npm:4.4.4" +"@smithy/middleware-endpoint@npm:^4.4.12, @smithy/middleware-endpoint@npm:^4.4.13": + version: 4.4.13 + resolution: "@smithy/middleware-endpoint@npm:4.4.13" dependencies: - "@smithy/core": "npm:^3.20.3" - "@smithy/middleware-serde": "npm:^4.2.8" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" - "@smithy/url-parser": "npm:^4.2.7" - "@smithy/util-middleware": "npm:^4.2.7" + "@smithy/core": "npm:^3.22.1" + "@smithy/middleware-serde": "npm:^4.2.9" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" + "@smithy/url-parser": "npm:^4.2.8" + "@smithy/util-middleware": "npm:^4.2.8" tslib: "npm:^2.6.2" - checksum: 10c0/0e656a7fe081ac7512d0bc928749fc738ccc02ff0cb62b8e2b928d1eeb5478b1c6c54c4936e020e3565e185e844a58aecb1c4ecac58e7140d1cc7729827e010e + checksum: 10c0/0a67cf539065c1c2750006d37eee92ed50aca976febf3281f5cb7b52ee028a6f5c66ee8337d9ba7afd21915a17756e8301f0540911ad6d59669353b22450a119 languageName: node linkType: hard -"@smithy/middleware-retry@npm:^4.4.19": - version: 4.4.20 - resolution: "@smithy/middleware-retry@npm:4.4.20" +"@smithy/middleware-retry@npm:^4.4.29": + version: 4.4.30 + resolution: "@smithy/middleware-retry@npm:4.4.30" dependencies: - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/service-error-classification": "npm:^4.2.7" - "@smithy/smithy-client": "npm:^4.10.5" - "@smithy/types": "npm:^4.11.0" - "@smithy/util-middleware": "npm:^4.2.7" - "@smithy/util-retry": "npm:^4.2.7" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/service-error-classification": "npm:^4.2.8" + "@smithy/smithy-client": "npm:^4.11.2" + "@smithy/types": "npm:^4.12.0" + "@smithy/util-middleware": "npm:^4.2.8" + "@smithy/util-retry": "npm:^4.2.8" "@smithy/uuid": "npm:^1.1.0" tslib: "npm:^2.6.2" - checksum: 10c0/660236d3f9902e107999cddac749602844f284e6e773ec3810baaebc3a8b4af069f6bb900fbec4df784f55bd653336120067108030dd14cec5032f609eae79d0 + checksum: 10c0/bf3294fd62696714a5c66a54e5ce01ce578c55a62f657ea409d55d2c7fe1cb806db9f9f4125fb17fba1d15323165f68758923686c45ab50579c7578e56945894 languageName: node linkType: hard -"@smithy/middleware-serde@npm:^4.2.8": - version: 4.2.8 - resolution: "@smithy/middleware-serde@npm:4.2.8" +"@smithy/middleware-serde@npm:^4.2.9": + version: 4.2.9 + resolution: "@smithy/middleware-serde@npm:4.2.9" dependencies: - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/5ed53af095d605940b540253c38a723d2cc37400c116071455a23b17fdf60af59b74b67b15d84f7bfb3738c9c37e3664b57f24c670d5c96ee46737225c147344 + checksum: 10c0/72164c91690f3cb3bcbb1638dad4ddc245c48cf92f1663740a65df430c35e5f6c94c51a88645c0085ff138ad6ededba45106b94698fbaaec527ae653e40829a9 languageName: node linkType: hard -"@smithy/middleware-stack@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/middleware-stack@npm:4.2.7" +"@smithy/middleware-stack@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/middleware-stack@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/199aa2575a8e4e3fa1a1a7989958e2f3aeb8dae115b41547d8bef18b5573e369d7eacc206ec6648194cdce491fe8c54abcccedd4a5c0bca370a11c480bd11ca7 + checksum: 10c0/3d931a12f1e9d691bcdca5f1889378266fcd20ab97f46983a08585492bf90fecb644b00886db908ec902efadb5f983a6365ae0dd351245d52c78ef3091e0d058 languageName: node linkType: hard -"@smithy/node-config-provider@npm:^4.3.7": - version: 4.3.7 - resolution: "@smithy/node-config-provider@npm:4.3.7" +"@smithy/node-config-provider@npm:^4.3.8": + version: 4.3.8 + resolution: "@smithy/node-config-provider@npm:4.3.8" dependencies: - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/shared-ini-file-loader": "npm:^4.4.2" - "@smithy/types": "npm:^4.11.0" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/shared-ini-file-loader": "npm:^4.4.3" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/2fbe9f22e315253d8d4f5a8d16d41d36ff4467c9f7e515d456c3172b59af8fbd67004d0d44bdb7638886eb6057d04ce269f84de65a382d2ccd0c08114dea840c + checksum: 10c0/da474576b586f70e90db8f7c2c0d03aac40380435b973b4c5c759910b11cd5c75d89191da21499a83bae3ef12b8317b7421e509c3b5114f3d42d672de7c35f93 languageName: node linkType: hard -"@smithy/node-http-handler@npm:^4.4.7": - version: 4.4.7 - resolution: "@smithy/node-http-handler@npm:4.4.7" +"@smithy/node-http-handler@npm:^4.4.8, @smithy/node-http-handler@npm:^4.4.9": + version: 4.4.9 + resolution: "@smithy/node-http-handler@npm:4.4.9" dependencies: - "@smithy/abort-controller": "npm:^4.2.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/querystring-builder": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/abort-controller": "npm:^4.2.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/querystring-builder": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/8f1114b2bc2232b50c0777b58ab5195c91a5aa1a76c48de7aa403f0c3245be287b070498924845036ab558b28827df916c9730f975a1edfc2e7345d1022350c1 + checksum: 10c0/e60d3724aa8a09273688ca81d5c3d613c3952b0011dc34034b78ab16b08d404c11cf9676b3265f299f7347fc5ad05c9ac0637b70488d9356a7c4b01222ab49e8 languageName: node linkType: hard -"@smithy/property-provider@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/property-provider@npm:4.2.7" +"@smithy/property-provider@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/property-provider@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/7caaeec11262a169c6509c5cd687900342ab02900f3074e54aeafbd2ce8a112c83ce3190225b2dab9f2a7f737f7176960329f882935ae7bd9d624984387d0fc1 + checksum: 10c0/3883dc620ad63db9df86aae19c6cad12be76deb8775f5b75a94773c1b907173dce5dcdd6cd255bcd7f8156ea2840c05e15c9e68e975344989710daaa3e63761c languageName: node linkType: hard -"@smithy/protocol-http@npm:^5.3.7": - version: 5.3.7 - resolution: "@smithy/protocol-http@npm:5.3.7" +"@smithy/protocol-http@npm:^5.3.8": + version: 5.3.8 + resolution: "@smithy/protocol-http@npm:5.3.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/c5bde38fbb71a63e2e25e33792d8b186523afbe1d520ffc821943c40eb41ca804a99afca7917798337b1f2bdea4ae64d3ae745f1036f7e65291d7c7ff301a953 + checksum: 10c0/13285091174a893c695f4e44debcaf7fc8be3e8140188020c9a29d9cc70acf46345039b231b0b7c136f864dc02b87d48e7aedb657f6888eaa5ff76295a7deafe languageName: node linkType: hard -"@smithy/querystring-builder@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/querystring-builder@npm:4.2.7" +"@smithy/querystring-builder@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/querystring-builder@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" "@smithy/util-uri-escape": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/24e3b2a35d2828fb19b4213b823b5adc0ce7edcf8e096a618e2dfcd9df3c2a750ee518af4b754759ab49b2a656c5cb66989d6fbbcfc085f8511dc9e02a0e2dce + checksum: 10c0/21995656fad2198b6d2960367e84ec847609dd317a6dcc2eb133b78abd3c3816221316a50cbdcd20fb773d24e942a182b3844a334c7694bae091085c6edc2798 languageName: node linkType: hard -"@smithy/querystring-parser@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/querystring-parser@npm:4.2.7" +"@smithy/querystring-parser@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/querystring-parser@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/4efddf97b35e7b2a04018acf5afd0f658506242adab77098b32e4bb625c5a607fdcfd9df2a7504dcacc7ac5e8624757abb881b2013862a098319a08b5c75a0d1 + checksum: 10c0/997a4e94438091461c1e8ccc66b3c1e7f243eaac22b2598d34d67de7332c1b8a2963cca98499f91638a4505aab07c968b3c9db1ff2aa29682a783fb6374b53e1 languageName: node linkType: hard -"@smithy/service-error-classification@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/service-error-classification@npm:4.2.7" +"@smithy/service-error-classification@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/service-error-classification@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" - checksum: 10c0/ddbbae91b4eb83ee66262059a3ce0fa2cee7874bcc0704481f5681966ef25af175afe8bfef7cd0868d86901d08cfb61fe34964f5a4c8f7a6347228a34e40845b + "@smithy/types": "npm:^4.12.0" + checksum: 10c0/10a31e4c73839f2b372df026223df3370f06ea584854c57e13967a306eac3de073af1f3998ae4df5ecb0d46ccc2cb737270794f9be572b36510ece946010a5b3 languageName: node linkType: hard -"@smithy/shared-ini-file-loader@npm:^4.4.2": - version: 4.4.2 - resolution: "@smithy/shared-ini-file-loader@npm:4.4.2" +"@smithy/shared-ini-file-loader@npm:^4.4.3": + version: 4.4.3 + resolution: "@smithy/shared-ini-file-loader@npm:4.4.3" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/3d401b87b21113aa9bb7490d80ec02d7655c1abc1b23eb384fea13b7e1348f1c599011ed109a3fe2e3675b3bc51f91f43b66d7e46f565f78c3f0d45d3b997058 + checksum: 10c0/6d625499d5c61d68c0adbfca8e9f04f0c1e011137226f8af09fc8c7aa1594e4297317d7ef64345f5ca09b8948833ea7f4f3df7df621f2fc68c74d540c1a017b8 languageName: node linkType: hard -"@smithy/signature-v4@npm:^5.3.7": - version: 5.3.7 - resolution: "@smithy/signature-v4@npm:5.3.7" +"@smithy/signature-v4@npm:^5.3.8": + version: 5.3.8 + resolution: "@smithy/signature-v4@npm:5.3.8" dependencies: "@smithy/is-array-buffer": "npm:^4.2.0" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" "@smithy/util-hex-encoding": "npm:^4.2.0" - "@smithy/util-middleware": "npm:^4.2.7" + "@smithy/util-middleware": "npm:^4.2.8" "@smithy/util-uri-escape": "npm:^4.2.0" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/01cae99baa7298adadbce6b293548adf1520fa8072086b48a0ef64cb13c3a156cb4d575753fc72af8fe0b50c65fa364ccce8931bd0d8ffe398d210da96efb54a + checksum: 10c0/5959ae4d22fedb707543b193a4fb12902fcc9b07452ea1ea9366fde702680a6e862f4b92d12a2f7d1677bc62a97963e707092147f1e7876bb2e419d7a8842d67 languageName: node linkType: hard -"@smithy/smithy-client@npm:^4.10.4, @smithy/smithy-client@npm:^4.10.5": - version: 4.10.5 - resolution: "@smithy/smithy-client@npm:4.10.5" +"@smithy/smithy-client@npm:^4.11.1, @smithy/smithy-client@npm:^4.11.2": + version: 4.11.2 + resolution: "@smithy/smithy-client@npm:4.11.2" dependencies: - "@smithy/core": "npm:^3.20.3" - "@smithy/middleware-endpoint": "npm:^4.4.4" - "@smithy/middleware-stack": "npm:^4.2.7" - "@smithy/protocol-http": "npm:^5.3.7" - "@smithy/types": "npm:^4.11.0" - "@smithy/util-stream": "npm:^4.5.8" + "@smithy/core": "npm:^3.22.1" + "@smithy/middleware-endpoint": "npm:^4.4.13" + "@smithy/middleware-stack": "npm:^4.2.8" + "@smithy/protocol-http": "npm:^5.3.8" + "@smithy/types": "npm:^4.12.0" + "@smithy/util-stream": "npm:^4.5.11" tslib: "npm:^2.6.2" - checksum: 10c0/7e75ce65f6881a27298704a2219bd425311b63fc4bffb4a8548284887ca0f92050828a540c40119102119d8414ffb8543853e925819345901bf26ceb16fe6782 + checksum: 10c0/496ef496306a5acfb0faeb6a5235c8089ac6fb928b6f1b14fb714d60cdf592c2fb6fb5f5f288da5395adc96948314357d47b815397409f4a6aa2db7cc3cc41cd languageName: node linkType: hard -"@smithy/types@npm:^4.11.0": - version: 4.11.0 - resolution: "@smithy/types@npm:4.11.0" +"@smithy/types@npm:^4.12.0": + version: 4.12.0 + resolution: "@smithy/types@npm:4.12.0" dependencies: tslib: "npm:^2.6.2" - checksum: 10c0/8be4af86df4a78fe43afe7dc3f875bf8ec6ce7c04f7bb167152bf3c7ab2eef26db38ed7ae365c2f283e8796e40372b01b4c857b8db43da393002c5638ef3f249 + checksum: 10c0/ac81de3f24b43e52a5089279bced4ff04a853e0bdc80143a234e79f7f40cbd61d85497b08a252265570b4637a3cf265cf85a7a09e5f194937fe30706498640b7 languageName: node linkType: hard -"@smithy/url-parser@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/url-parser@npm:4.2.7" +"@smithy/url-parser@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/url-parser@npm:4.2.8" dependencies: - "@smithy/querystring-parser": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/querystring-parser": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/ca78587b15a843cc62f3439ae062a24f217e90fa0ec3e50a1ada09cf75c681afa1ccb92ca7a90f63c8f53627d51c6e0c83140422ce98713e1f4866c725923ec0 + checksum: 10c0/a3a5fa00b01ccc89de620a12286278f3dc86a14c1de0a7a576db2f2296c71a8b21b7ed8f8776d770647225a73f33afba4fe1a69de741515246117506532dad3c languageName: node linkType: hard @@ -3418,41 +3451,41 @@ __metadata: languageName: node linkType: hard -"@smithy/util-defaults-mode-browser@npm:^4.3.18": - version: 4.3.19 - resolution: "@smithy/util-defaults-mode-browser@npm:4.3.19" +"@smithy/util-defaults-mode-browser@npm:^4.3.28": + version: 4.3.29 + resolution: "@smithy/util-defaults-mode-browser@npm:4.3.29" dependencies: - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/smithy-client": "npm:^4.10.5" - "@smithy/types": "npm:^4.11.0" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/smithy-client": "npm:^4.11.2" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/69c56cf0f46b7b47801815183304c4b0feefc6aa32dab1b30079d0a16e98d0b393f7f6b5e4abb5dda299b0715c12f6ceebdd1f9127d6b3b1d10ffa8b7c91ee0d + checksum: 10c0/1e74208a450182cc786fd59e33b256791690512e233338a68506b932149755297fe08ce8f87da90bc63d6594870d58f7c9b3d100ec3aeea9361688601c8a5f23 languageName: node linkType: hard -"@smithy/util-defaults-mode-node@npm:^4.2.21": - version: 4.2.22 - resolution: "@smithy/util-defaults-mode-node@npm:4.2.22" +"@smithy/util-defaults-mode-node@npm:^4.2.31": + version: 4.2.32 + resolution: "@smithy/util-defaults-mode-node@npm:4.2.32" dependencies: - "@smithy/config-resolver": "npm:^4.4.5" - "@smithy/credential-provider-imds": "npm:^4.2.7" - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/property-provider": "npm:^4.2.7" - "@smithy/smithy-client": "npm:^4.10.5" - "@smithy/types": "npm:^4.11.0" + "@smithy/config-resolver": "npm:^4.4.6" + "@smithy/credential-provider-imds": "npm:^4.2.8" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/property-provider": "npm:^4.2.8" + "@smithy/smithy-client": "npm:^4.11.2" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/11f5238add6a1f2e72fbba8acd5978a5d780f0b59ed2bae97637f1f76bd64cea22d7dfeefcb4432e20ca4ff2d0940ce2a1956bf2d9842946f2b877b7c0d71c61 + checksum: 10c0/fb8eee0a2cf72cc055d6944912279940365dc584aa341922aa3b8b59809cff13ef55b483017405bb46e905e90960d20760126f7abd4c88d763b5f2bd687895b2 languageName: node linkType: hard -"@smithy/util-endpoints@npm:^3.2.7": - version: 3.2.7 - resolution: "@smithy/util-endpoints@npm:3.2.7" +"@smithy/util-endpoints@npm:^3.2.8": + version: 3.2.8 + resolution: "@smithy/util-endpoints@npm:3.2.8" dependencies: - "@smithy/node-config-provider": "npm:^4.3.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/node-config-provider": "npm:^4.3.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/ca4b134e0ed8b62dfedb82b9ea91fa028567732e271e934b9b878a9aa43f1c5c9d8860ad49f60992290c7705b7b6d2e734769304b9ea38eec40eaf524bb27ad8 + checksum: 10c0/7baade0e0b8c1a9ae04251aea5572908d27007305eaf9a9a01350d702ac02492cf4311040edcb766e77091c70dc58c0aadb6145b319ca309dc43caf43512c05c languageName: node linkType: hard @@ -3465,40 +3498,40 @@ __metadata: languageName: node linkType: hard -"@smithy/util-middleware@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/util-middleware@npm:4.2.7" +"@smithy/util-middleware@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/util-middleware@npm:4.2.8" dependencies: - "@smithy/types": "npm:^4.11.0" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/76c598cfe8062b6daf0bf88bc855544ce071f1d2df5d9d2c2d1c08402a577cb9ade8f33102a869dfb8aae9f679b86b5faacc9011b032bf453ced255fd8d0a0d3 + checksum: 10c0/9c3faa8445e377d83da404a449e84ebc95c29faed210bb0f1fe28ddfb0ab0f8fe9ef54db7920a2dc0312c7db04c1590c805e25abcb9c1e3ac21f79597fc2c25c languageName: node linkType: hard -"@smithy/util-retry@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/util-retry@npm:4.2.7" +"@smithy/util-retry@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/util-retry@npm:4.2.8" dependencies: - "@smithy/service-error-classification": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/service-error-classification": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/51445769ce5382a85f5c78758d6d7d631b3a3f8277fa49ae2c2730536b1a53babfe27efb30e4b96ebc68faead2aafa9ab877e6ed728eb8018d080e26d9a42f58 + checksum: 10c0/5329f7e0144114ce7bece310a30c0f094adfe3bcb4a3c9d6d67bb0a8fef72b454bad4ccfecb8cfbeaae025c10a668e88beca08a7e04f28ec8faad8f16db791e9 languageName: node linkType: hard -"@smithy/util-stream@npm:^4.5.8": - version: 4.5.8 - resolution: "@smithy/util-stream@npm:4.5.8" +"@smithy/util-stream@npm:^4.5.10, @smithy/util-stream@npm:^4.5.11": + version: 4.5.11 + resolution: "@smithy/util-stream@npm:4.5.11" dependencies: - "@smithy/fetch-http-handler": "npm:^5.3.8" - "@smithy/node-http-handler": "npm:^4.4.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/fetch-http-handler": "npm:^5.3.9" + "@smithy/node-http-handler": "npm:^4.4.9" + "@smithy/types": "npm:^4.12.0" "@smithy/util-base64": "npm:^4.3.0" "@smithy/util-buffer-from": "npm:^4.2.0" "@smithy/util-hex-encoding": "npm:^4.2.0" "@smithy/util-utf8": "npm:^4.2.0" tslib: "npm:^2.6.2" - checksum: 10c0/71f43fdf93ccde982edf4ae3b481006dd42146d17f6594abcca21e2f41e5b40ad69d6038052e016f7135011586294d6ed8c778465ea076deaa50b7808f66bc32 + checksum: 10c0/ebc5f2b46ffacea6530df5ff8940a6d1a4d0019bd9b4bc9158b8ad4973b4a25143fa007c75c6f45a6971813b3c7b6d6c69cc0291f9f451e5972307740cfe1bed languageName: node linkType: hard @@ -3531,14 +3564,14 @@ __metadata: languageName: node linkType: hard -"@smithy/util-waiter@npm:^4.2.7": - version: 4.2.7 - resolution: "@smithy/util-waiter@npm:4.2.7" +"@smithy/util-waiter@npm:^4.2.8": + version: 4.2.8 + resolution: "@smithy/util-waiter@npm:4.2.8" dependencies: - "@smithy/abort-controller": "npm:^4.2.7" - "@smithy/types": "npm:^4.11.0" + "@smithy/abort-controller": "npm:^4.2.8" + "@smithy/types": "npm:^4.12.0" tslib: "npm:^2.6.2" - checksum: 10c0/0de99074db038eb09c4ebe2ed7f0ff3a13aa0ce5baf0b62a4b684f282e772e281f9eab8936d7aa577d8f419b676df60aa752e3c2b5edf07b44d8e999d983253f + checksum: 10c0/456ef90229d342af8869599a4977c5058f798d051bf9b5df4069cf742e07be7ec62d0d9793829099dd90b96595fd2d4035346db8e75986b2166edb27d44423d4 languageName: node linkType: hard @@ -3719,11 +3752,11 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>=13.7.0": - version: 25.0.7 - resolution: "@types/node@npm:25.0.7" + version: 25.2.0 + resolution: "@types/node@npm:25.2.0" dependencies: undici-types: "npm:~7.16.0" - checksum: 10c0/a9feeb16a6487621ef96158e7a9759f89e3c1726189c7b19a9e6d3e0d581499c62e441e120e5a334e9eb01bc4d26644f27767fd5931d6d4f177d14f4f8e3f9ab + checksum: 10c0/89559ea0de5c8c2da051b384f2cd3161012446816e05d18841838f814e57eb1865f000622e903f08d14f5242736063ed4003a4a359730fdd367e35e2122a8fce languageName: node linkType: hard @@ -4218,13 +4251,13 @@ __metadata: linkType: hard "axios@npm:^1.12.0": - version: 1.13.2 - resolution: "axios@npm:1.13.2" + version: 1.13.4 + resolution: "axios@npm:1.13.4" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.4" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/e8a42e37e5568ae9c7a28c348db0e8cf3e43d06fcbef73f0048669edfe4f71219664da7b6cc991b0c0f01c28a48f037c515263cb79be1f1ae8ff034cd813867b + checksum: 10c0/474c00b7d71f4de4ad562589dae6b615149df7c2583bbc5ebba96229f3f85bfb0775d23705338df072f12e48d3e85685c065a3cf6855d58968a672d19214c728 languageName: node linkType: hard @@ -4590,6 +4623,17 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 + languageName: node + linkType: hard + "clsx@npm:^2.1.1": version: 2.1.1 resolution: "clsx@npm:2.1.1" @@ -5302,6 +5346,13 @@ __metadata: languageName: node linkType: hard +"escalade@npm:^3.1.1": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 + languageName: node + linkType: hard + "escape-html@npm:^1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" @@ -5594,14 +5645,14 @@ __metadata: languageName: node linkType: hard -"fast-xml-parser@npm:5.2.5": - version: 5.2.5 - resolution: "fast-xml-parser@npm:5.2.5" +"fast-xml-parser@npm:5.3.4": + version: 5.3.4 + resolution: "fast-xml-parser@npm:5.3.4" dependencies: strnum: "npm:^2.1.0" bin: fxparser: src/cli/cli.js - checksum: 10c0/d1057d2e790c327ccfc42b872b91786a4912a152d44f9507bf053f800102dfb07ece3da0a86b33ff6a0caa5a5cad86da3326744f6ae5efb0c6c571d754fe48cd + checksum: 10c0/d77866ca860ad185153e12f6ba12274d32026319ad8064e4681342b8a8e1ffad3f1f98daf04d77239fb12eb1d906ee7185fd328deda74529680e8dae0f3e9327 languageName: node linkType: hard @@ -5855,6 +5906,13 @@ __metadata: languageName: node linkType: hard +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde + languageName: node + linkType: hard + "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": version: 1.3.1 resolution: "get-intrinsic@npm:1.3.1" @@ -5934,7 +5992,18 @@ __metadata: languageName: node linkType: hard -"glob@npm:^11.0.3": +"glob@npm:^13.0.0": + version: 13.0.0 + resolution: "glob@npm:13.0.0" + dependencies: + minimatch: "npm:^10.1.1" + minipass: "npm:^7.1.2" + path-scurry: "npm:^2.0.0" + checksum: 10c0/8e2f5821f3f7c312dd102e23a15b80c79e0837a9872784293ba2e15ec73b3f3749a49a42a31bfcb4e52c84820a474e92331c2eebf18819d20308f5c33876630a + languageName: node + linkType: hard + +"glob@npm:~11.1.0": version: 11.1.0 resolution: "glob@npm:11.1.0" dependencies: @@ -6010,16 +6079,16 @@ __metadata: version: 0.0.0-use.local resolution: "gregoswap@workspace:." dependencies: - "@aztec/accounts": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/aztec.js": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/constants": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/entrypoints": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/foundation": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/noir-contracts.js": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/pxe": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/stdlib": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/test-wallet": "npm:v3.0.0-devnet.6-patch.1" - "@aztec/wallet-sdk": "npm:v3.0.0-devnet.6-patch.1" + "@aztec/accounts": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/aztec.js": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/constants": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/entrypoints": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/foundation": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/noir-contracts.js": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/pxe": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/stdlib": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/test-wallet": "npm:v4.0.0-devnet.1-patch.0" + "@aztec/wallet-sdk": "npm:v4.0.0-devnet.1-patch.0" "@emotion/react": "npm:^11.14.0" "@emotion/styled": "npm:^11.14.0" "@eslint/js": "npm:^9.18.0" @@ -6921,16 +6990,17 @@ __metadata: linkType: hard "lmdb@npm:^3.2.0": - version: 3.4.4 - resolution: "lmdb@npm:3.4.4" - dependencies: - "@lmdb/lmdb-darwin-arm64": "npm:3.4.4" - "@lmdb/lmdb-darwin-x64": "npm:3.4.4" - "@lmdb/lmdb-linux-arm": "npm:3.4.4" - "@lmdb/lmdb-linux-arm64": "npm:3.4.4" - "@lmdb/lmdb-linux-x64": "npm:3.4.4" - "@lmdb/lmdb-win32-arm64": "npm:3.4.4" - "@lmdb/lmdb-win32-x64": "npm:3.4.4" + version: 3.5.1 + resolution: "lmdb@npm:3.5.1" + dependencies: + "@harperfast/extended-iterable": "npm:^1.0.3" + "@lmdb/lmdb-darwin-arm64": "npm:3.5.1" + "@lmdb/lmdb-darwin-x64": "npm:3.5.1" + "@lmdb/lmdb-linux-arm": "npm:3.5.1" + "@lmdb/lmdb-linux-arm64": "npm:3.5.1" + "@lmdb/lmdb-linux-x64": "npm:3.5.1" + "@lmdb/lmdb-win32-arm64": "npm:3.5.1" + "@lmdb/lmdb-win32-x64": "npm:3.5.1" msgpackr: "npm:^1.11.2" node-addon-api: "npm:^6.1.0" node-gyp: "npm:latest" @@ -6954,7 +7024,7 @@ __metadata: optional: true bin: download-lmdb-prebuilds: bin/download-prebuilds.js - checksum: 10c0/9bcaa26ded2fd58c642061218f3d16d710adc0a11859fb803bb6bed401f147aeaf41d42eda0644dcf1962bc251dd12e7fe1c4fc10c89fa80fcff3caf67cad3d2 + checksum: 10c0/1fd63b1fa981569ec79ea952886a5ac31773cca19d4d4d21f26297dda52c21ae67818cf2026af0adcc80efd675189afaf4c57e130308beaa1a4cfdb379b5c10a languageName: node linkType: hard @@ -7056,9 +7126,9 @@ __metadata: linkType: hard "lru-cache@npm:^11.0.0": - version: 11.2.4 - resolution: "lru-cache@npm:11.2.4" - checksum: 10c0/4a24f9b17537619f9144d7b8e42cd5a225efdfd7076ebe7b5e7dc02b860a818455201e67fbf000765233fe7e339d3c8229fc815e9b58ee6ede511e07608c19b2 + version: 11.2.5 + resolution: "lru-cache@npm:11.2.5" + checksum: 10c0/cc98958d25dddf1c8a8cbdc49588bd3b24450e8dfa78f32168fd188a20d4a0331c7406d0f3250c86a46619ee288056fd7a1195e8df56dc8a9592397f4fbd8e1d languageName: node linkType: hard @@ -7468,6 +7538,24 @@ __metadata: languageName: node linkType: hard +"node-pg-migrate@npm:^8.0.4": + version: 8.0.4 + resolution: "node-pg-migrate@npm:8.0.4" + dependencies: + glob: "npm:~11.1.0" + yargs: "npm:~17.7.0" + peerDependencies: + "@types/pg": ">=6.0.0 <9.0.0" + pg: ">=4.3.0 <9.0.0" + peerDependenciesMeta: + "@types/pg": + optional: true + bin: + node-pg-migrate: bin/node-pg-migrate.js + checksum: 10c0/bf25ae7873ff7658609052da693d9067112b74c5f09bb9f49eb0656c0d0ea495ca690be75f3d12ee569230232f1941882bbe7c6eecc60d0e89e27c56fb4792c0 + languageName: node + linkType: hard + "node-stdlib-browser@npm:^1.2.0": version: 1.3.1 resolution: "node-stdlib-browser@npm:1.3.1" @@ -7835,6 +7923,87 @@ __metadata: languageName: node linkType: hard +"pg-cloudflare@npm:^1.3.0": + version: 1.3.0 + resolution: "pg-cloudflare@npm:1.3.0" + checksum: 10c0/b0866c88af8e54c7b3ed510719d92df37714b3af5e3a3a10d9f761fcec99483e222f5b78a1f2de590368127648087c45c01aaf66fadbe46edb25673eedc4f8fc + languageName: node + linkType: hard + +"pg-connection-string@npm:^2.11.0": + version: 2.11.0 + resolution: "pg-connection-string@npm:2.11.0" + checksum: 10c0/7a4bcf9b4f1e1fee6482e2bd814f544d451240059be6b8a186f24f73f163f1c599bb8c4984c398254869f744f6c3659b83e285c3d525fc640e99c60c453bd0df + languageName: node + linkType: hard + +"pg-int8@npm:1.0.1": + version: 1.0.1 + resolution: "pg-int8@npm:1.0.1" + checksum: 10c0/be6a02d851fc2a4ae3e9de81710d861de3ba35ac927268973eb3cb618873a05b9424656df464dd43bd7dc3fc5295c3f5b3c8349494f87c7af50ec59ef14e0b98 + languageName: node + linkType: hard + +"pg-pool@npm:^3.11.0": + version: 3.11.0 + resolution: "pg-pool@npm:3.11.0" + peerDependencies: + pg: ">=8.0" + checksum: 10c0/4b104b48a47257a0edad0c62e5ea1908b72cb79386270264b452e69895e9e4c589d00cdbf6e46d4e9c05bc7e7d191656b66814b5282d65f33b12648a21df3c7f + languageName: node + linkType: hard + +"pg-protocol@npm:^1.11.0": + version: 1.11.0 + resolution: "pg-protocol@npm:1.11.0" + checksum: 10c0/93e83581781418c9173eba4e4545f73392cfe66b78dd1d3624d7339fbd37e7f4abebaf2615e68e0701a9bf0edf5b81a4ad533836f388f775fe25fa24a691c464 + languageName: node + linkType: hard + +"pg-types@npm:2.2.0": + version: 2.2.0 + resolution: "pg-types@npm:2.2.0" + dependencies: + pg-int8: "npm:1.0.1" + postgres-array: "npm:~2.0.0" + postgres-bytea: "npm:~1.0.0" + postgres-date: "npm:~1.0.4" + postgres-interval: "npm:^1.1.0" + checksum: 10c0/ab3f8069a323f601cd2d2279ca8c425447dab3f9b61d933b0601d7ffc00d6200df25e26a4290b2b0783b59278198f7dd2ed03e94c4875797919605116a577c65 + languageName: node + linkType: hard + +"pg@npm:^8.11.3": + version: 8.18.0 + resolution: "pg@npm:8.18.0" + dependencies: + pg-cloudflare: "npm:^1.3.0" + pg-connection-string: "npm:^2.11.0" + pg-pool: "npm:^3.11.0" + pg-protocol: "npm:^1.11.0" + pg-types: "npm:2.2.0" + pgpass: "npm:1.0.5" + peerDependencies: + pg-native: ">=3.0.1" + dependenciesMeta: + pg-cloudflare: + optional: true + peerDependenciesMeta: + pg-native: + optional: true + checksum: 10c0/9525e34d603ee5d715b8952269b2fa9fdd350a55fc5a3360104e7613724441858e57d52eed435fb16e993d028b45d8175dc277d270d31f69e5746987a549f772 + languageName: node + linkType: hard + +"pgpass@npm:1.0.5": + version: 1.0.5 + resolution: "pgpass@npm:1.0.5" + dependencies: + split2: "npm:^4.1.0" + checksum: 10c0/5ea6c9b2de04c33abb08d33a2dded303c4a3c7162a9264519cbe85c0a9857d712463140ba42fad0c7cd4b21f644dd870b45bb2e02fcbe505b4de0744fd802c1d + languageName: node + linkType: hard + "picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -7898,9 +8067,9 @@ __metadata: linkType: hard "pino-std-serializers@npm:^7.0.0": - version: 7.0.0 - resolution: "pino-std-serializers@npm:7.0.0" - checksum: 10c0/73e694d542e8de94445a03a98396cf383306de41fd75ecc07085d57ed7a57896198508a0dec6eefad8d701044af21eb27253ccc352586a03cf0d4a0bd25b4133 + version: 7.1.0 + resolution: "pino-std-serializers@npm:7.1.0" + checksum: 10c0/d158615aa93ebdeac2d3912ad4227a23ef78cf14229e886214771f581e96eff312257f2d6368c75b2fbf53e5024eda475d81305014f4ed1a6d5eeab9107f6ef0 languageName: node linkType: hard @@ -7976,6 +8145,36 @@ __metadata: languageName: node linkType: hard +"postgres-array@npm:~2.0.0": + version: 2.0.0 + resolution: "postgres-array@npm:2.0.0" + checksum: 10c0/cbd56207e4141d7fbf08c86f2aebf21fa7064943d3f808ec85f442ff94b48d891e7a144cc02665fb2de5dbcb9b8e3183a2ac749959e794b4a4cfd379d7a21d08 + languageName: node + linkType: hard + +"postgres-bytea@npm:~1.0.0": + version: 1.0.1 + resolution: "postgres-bytea@npm:1.0.1" + checksum: 10c0/10b28a27c9d703d5befd97c443e62b551096d1014bc59ab574c65bf0688de7f3f068003b2aea8dcff83cf0f6f9a35f9f74457c38856cf8eb81b00cf3fb44f164 + languageName: node + linkType: hard + +"postgres-date@npm:~1.0.4": + version: 1.0.7 + resolution: "postgres-date@npm:1.0.7" + checksum: 10c0/0ff91fccc64003e10b767fcfeefb5eaffbc522c93aa65d5051c49b3c4ce6cb93ab091a7d22877a90ad60b8874202c6f1d0f935f38a7235ed3b258efd54b97ca9 + languageName: node + linkType: hard + +"postgres-interval@npm:^1.1.0": + version: 1.2.0 + resolution: "postgres-interval@npm:1.2.0" + dependencies: + xtend: "npm:^4.0.0" + checksum: 10c0/c1734c3cb79e7f22579af0b268a463b1fa1d084e742a02a7a290c4f041e349456f3bee3b4ee0bb3f226828597f7b76deb615c1b857db9a742c45520100456272 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -8289,6 +8488,13 @@ __metadata: languageName: node linkType: hard +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 + languageName: node + linkType: hard + "requires-port@npm:^1.0.0": version: 1.0.0 resolution: "requires-port@npm:1.0.0" @@ -8731,7 +8937,7 @@ __metadata: languageName: node linkType: hard -"split2@npm:^4.0.0": +"split2@npm:^4.0.0, split2@npm:^4.1.0": version: 4.2.0 resolution: "split2@npm:4.2.0" checksum: 10c0/b292beb8ce9215f8c642bb68be6249c5a4c7f332fc8ecadae7be5cbdf1ea95addc95f0459ef2e7ad9d45fd1064698a097e4eb211c83e772b49bc0ee423e91534 @@ -8806,7 +9012,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -9472,7 +9678,7 @@ __metadata: languageName: node linkType: hard -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" dependencies: @@ -9531,13 +9737,20 @@ __metadata: languageName: node linkType: hard -"xtend@npm:^4.0.2": +"xtend@npm:^4.0.0, xtend@npm:^4.0.2": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e languageName: node linkType: hard +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 + languageName: node + linkType: hard + "yallist@npm:^4.0.0": version: 4.0.0 resolution: "yallist@npm:4.0.0" @@ -9559,6 +9772,28 @@ __metadata: languageName: node linkType: hard +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 + languageName: node + linkType: hard + +"yargs@npm:~17.7.0": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: "npm:^8.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.3" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^21.1.1" + checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 + languageName: node + linkType: hard + "ylru@npm:^1.2.0": version: 1.4.0 resolution: "ylru@npm:1.4.0"